Every product I had worked on before this had constraints I could argue with.
A deadline moves. A scope shrinks. A feature that seemed essential in October gets quietly dropped in December and nobody outside the team notices. You learn to treat constraints as opening positions in a negotiation, because most of the time that is exactly what they are.
Then I worked on an app for distributing humanitarian aid, and none of the constraints negotiated.
The scene
Distribution day. People have been queuing since morning in the heat. The supervisor is holding a paper list of a hundred names, and every person who reaches the front means scanning that page by hand until the name is found.
That day, some people collected twice. Not through dishonesty — because there was no fast way to check. And someone genuinely eligible was not where the supervisor expected him on the sheet, so he waited two hours while it got sorted out.
The problem in aid distribution is usually not a shortage of aid. It is that nobody can say quickly who has already received and who has not.
What the constraints actually were
There were four, and I could not design around any of them.
No signal. Connectivity in these locations is intermittent at best and often absent entirely. Not slow — absent. Any design that waits on a server is a design that fails on the day it matters.
No undo. A confirmation has to be final, because a reversible record is not a record. If a collection can be un-collected, the whole system stops being evidence.
No time. A distributor with forty people waiting has no capacity to learn an interface, interpret an ambiguous state, or make a judgment call. Whatever the screen says, it has to say instantly and without interpretation.
No budget. The organization runs on donations. A per-message platform fee, a subscription, a server cost — any recurring expense is the thing that stops the tool being used at all.
Everything failed the same test
What I noticed, working through it, was that almost every idea I had failed for the same reason.
A richer confirmation flow — fails on time. A better sync indicator — assumes there is something to sync. An audit trail with corrections — fails on undo. Anything that improved the experience by adding a step, a state, or a service failed one of the four.
That is not how product work usually goes. Normally the constraints trade off against each other and the craft is in finding the balance. Here they were closer to a filter. Ideas went in and most of them did not come out.
The version that survived
What came through was simpler than anything I would have arrived at by design.
Each beneficiary gets one code, delivered by SMS to their own phone, using the device's own SIM so there is no gateway to pay for. The distributor searches by name, code, or phone — three ways in, because you do not control how someone identifies themselves at the front of a queue. Confirmation takes one deliberate step and then cannot be undone. The collected row is marked four separate ways: struck through, checked, filled, and the button changes state.
Four signals for one status sounds excessive. It is not. It is being read in sunlight, at speed, by someone who cannot afford to look twice.
Everything runs locally after first login and syncs when a connection returns. Offline is not a fallback mode in this product. It is the normal condition, and the sync is what is occasional.
What I took from it
I have started asking a different question about constraints.
Not can we move this, which is the reflex, but what happens to the person at the other end if we do. Most of the time the honest answer is: not much, and the constraint really was negotiable. But asking it properly changes what you notice.
The other thing is that severe constraints produce simpler products, and simpler is usually better than what I would have designed with more freedom. Given room, I add. Given four immovable limits, I found out which parts were actually load-bearing.
That is not an argument for artificial constraints. Inventing hardship to sharpen your thinking is a designer's fantasy, and the real version is not romantic — it is a hundred people in a queue and someone waiting two hours for a name to be found.
But when the constraints are real, they are worth listening to precisely. They are describing the situation more accurately than any brief could.