Use Cases and Alignment in Solo Development

A practical reflection on why solo development with clients fails through conceptual misalignment rather than poor design, and why use cases are the most effective tool for maintaining shared understanding.

Previous article: Designing Software for AI Code Generation

The Risk That Actually Kills Projects

When I think back over the projects that went seriously wrong, the pattern I find most consistently is not a design failure.

The design was sometimes mediocre. That is true. But mediocre design rarely killed the project on its own. What actually caused the damage was something earlier and less visible: the people involved had stopped sharing a clear understanding of what was being built.

That sounds simple. In practice it is surprisingly hard to maintain.

When I was working within Japan’s contract engineering services structure, I experienced this problem mostly from one side. A requirement would be handed down, and its ambiguity would only surface after implementation was finished. The fix would arrive labeled as a specification change, and everyone would quietly pretend that this had been the intent all along. That was an uncomfortable ritual, but it was still a ritual. There were established procedures for absorbing the gap.

Solo development with a client is different. There is no handoff ceremony to partially contain the misunderstanding. If what you built is not what the client meant, that gap belongs to you entirely. And by the time it becomes visible, you are usually far further into development than the misalignment deserved.

Misalignment Is Not a Technical Problem

I want to be precise about what I mean by misalignment, because it is easy to confuse it with other problems.

Misalignment is not a disagreement about technical implementation choices. It is something simpler and more dangerous: the client and the developer no longer agree on what the thing being built is actually supposed to do, and neither party may realize this until the costs of correction are already high.

I have walked into this situation several times. It does not appear dramatically at first. It arrives looking like a requirements change. The client introduces a scenario you assumed was out of scope. They reject behavior you were certain was obviously correct. They describe a screen in a way that reveals they had been imagining something structurally different from what you built.

The engineer replacement arguments I sometimes encounter online seem to me to largely miss this point. Whether AI writes more code or less code does not change the fact that someone has to understand what to build before building it. I think those arguments are mostly nonsense. But the frustration underlying them is real: software keeps delivering something other than what people actually needed, and the explanation offered is usually technical, while the actual failure was often not.

Design matters. I have written about the importance of structural decisions across several articles in the design series, and I stand behind that work. Weak entity modeling causes real damage. Poor lifecycle coordination produces screen behavior that becomes fragile under pressure. But design problems typically appear after a project has some momentum. Misalignment can destroy a project before it earns any momentum at all.

How My Own Practice Changed

I started treating use cases as an early deliverable because of a specific kind of failure that I could not ignore.

I had completed something technically solid, and the client was still clearly dissatisfied. Not because the software was broken or slow. Because it did not match what they had been picturing. What they had been picturing was not written down anywhere. I had not asked. I had moved from a general description of the need into architecture, and then into implementation, and the result was internally consistent and technically reasonable, while still being wrong about what mattered.

That failure cost more to repair than it would have cost to prevent. And it was not the first time.

Use cases forced me to stop treating alignment as something that would happen naturally. A use case, written at the right level of detail, describes what a person does inside the system, in sequence, in plain language. Not how the system is constructed. Not what data model underlies it. Just what happens, step by step, from the perspective of the person using it.

A non-engineer can read a use case description. They may not be able to parse a class diagram or follow a sequence diagram without guidance. They may not be able to interpret a wireframe with confidence. But a clearly written use case is something a client who has never participated in software development can follow and respond to. They can check it against their own mental model and tell you whether it matches what they need.

That feedback, obtained before a single screen exists, prevents the most expensive category of late-stage correction. Use cases can be shared early precisely because they do not depend on the implementation. They describe intent, not structure. That makes them readable at the stage when changing direction is still cheap.

Building It Together

There is a second reason I now treat use cases as the first deliverable, and it is less about accuracy and more about how projects feel to the people who commissioned them.

Stakeholders need to sense that something is taking shape. When a project runs for months and the only visible output is “we are working on it,” anxiety builds. That anxiety changes the working relationship in ways that are hard to recover from. Clients begin asking more questions than they would otherwise. They suggest changes they might not have raised if they felt more confident. They start second-guessing earlier decisions.

But I think there is something more important than progress visibility alone, and it took me a while to clearly separate the two.

What clients actually need is not only to feel that the project is moving. They need to feel that the thing being built is theirs, that they participated in shaping it, and that the direction reflects decisions they made intentionally rather than decisions that were made for them. The difference matters. A client who watched the project progress from the outside will still show up at delivery with a different mental model than the developer. A client who was involved in clarifying what each flow does will arrive at delivery with ownership of those decisions.

Use cases create that involvement before any implementation exists. When a client reads a use case description and corrects something in it, they are not just giving feedback. They are participating in design. That participation changes how they receive the final result. They recognize it as something they built with you, not something delivered to them.

Use cases, written clearly and shared early, make this kind of involvement practical.

When a client can read a description of what each actor does in each major flow, they can understand what is in progress. When those descriptions are paired with rough mockups, they can begin imagining the final system. When the use cases are structured so that additional flows can be introduced naturally, they can see how the system will grow.

I think of this as three things that need to be true at once. The work has to be understandable by the client, not only by the developer. It has to be imaginable in its final shape, not only describable in abstract terms. And it has to feel expandable in a way the client can sense, so that changes and additions feel like natural progression rather than disruptions to a finished thing.

When this goes well, something else happens too.

A client who has been reading and responding to use cases throughout the project starts approaching mockups differently. They are no longer looking at a screen layout for the first time and trying to figure out what it means. They already hold a partial mental model of how each flow works. The mockup becomes confirmation of something they already partially understand, rather than a new thing to interpret from scratch. That changes the quality of feedback they can give, and it changes the kind of questions they ask.

There is also a harder problem that many engineers have learned to quietly accept: most clients do not have a precise understanding of what software can and cannot do. That gap produces feedback that can be frustrating on both sides. Clients ask for things that require significant structural changes without realizing the cost. They reject limitations that are not arbitrary but are inherent to the approach being used. This is not a failure of intelligence. It is the expected result of never having had a way to build that understanding.

Use cases do not solve this completely. I would not want to overstate what any process can do. But when a client has been actively reading flow descriptions and asking questions throughout the project, they do tend to develop a working sense of what the system does at each point. And from that, some understanding of what it would take to make it do something different tends to follow. It is not always enough. But it is more than what you get when the system appears as a finished object at delivery.

None of these three things require a working system. They require that thinking be made legible. Use cases are the most direct path to making that happen early enough to matter.

When Requirements Change Anyway

I want to be honest about where use cases stop helping.

They do not prevent clients from changing what they want. Late-stage reversals still happen, and some of them are large. In Japanese development culture there is an expression I use internally when this happens: ちゃぶ台返し, which describes the kind of reversal where the whole table gets turned over and everything has to begin again.

That risk remains real. What use cases do is reduce the probability of the worst version of that scenario, which is the reversal that happens because the client only now discovered that they never properly understood what was being built. If use cases were shared, reviewed, and agreed upon at an early stage, the conversation around a late change shifts. A reversal becomes harder to frame as a correction to a misunderstanding. It becomes more clearly a change of direction, and a change of direction is a more honest and negotiable thing than a discovered failure.

There is another side to this worth naming. Sometimes a difficult change cannot simply be refused. The system as designed may be technically correct but operationally wrong, and refusing to accommodate the change might mean delivering something that no one will actually use. That is its own kind of failure, and it is one that engineers often underweight.

When a client has been involved from the beginning through use cases, that conversation changes shape as well. They are not arriving with a demand and waiting for a verdict. They understand enough of the constraints to think alongside you. And clients who know their own business deeply will sometimes come up with approaches that a developer would not have found alone. I have experienced this more than once. The client’s domain knowledge, once the technical situation is made legible to them, becomes a resource rather than an obstacle. The problem becomes a shared one, and shared problems tend to get better solutions.

That is not a guarantee either. But it is considerably more likely to happen when the client has been a participant throughout than when they have been a passive recipient of updates.

The Real Goal Is Building Together

Solo development is not especially hard at the implementation level. A single capable developer can build large and complex systems. The hard part is keeping the direction aligned with the person who ultimately needs to use and live with the result. In solo development, there is no team layer to absorb that misalignment, no handoff ceremony to surface the discrepancy. The gap belongs entirely to the developer, and it grows quietly until delivery makes it visible.

This kind of direct alignment is most achievable at the scale where the developer and the client can communicate without heavy intermediaries. Once a project grows large enough that the client side becomes a corporate IT department, or the commercial relationship adds layers of vendors and subcontractors in between, the mechanics change entirely. The direct line disappears, and with it much of what makes this approach work. What I am describing here applies most directly to the scale where that direct line still exists.

Everything I have written about in this series, from compact screen structure to careful entity design , is about building systems that hold together structurally and remain maintainable over time. All of that matters. But it matters at a later stage. Before structure can matter, the direction has to be right. And the direction is only reliably right when the client is not a passive recipient but an active participant in deciding what is being built.

That is the real goal. Not use cases specifically, but building together. Use cases are how I consistently get there. They are not a formal methodology I follow rigidly, and they are not the only possible approach. They are the tool that has most reliably prevented the kind of failure that no amount of good architecture can fix.

When it works well, everyone gains something from it. The client ends up with a system that reflects genuine decisions they made, not a product they received and are now learning to interpret. The people who actually operate the system day to day see their real workflows represented, because those workflows were part of the conversation from the start. And the developer works with clearer direction, receives fewer late-stage corrections that require structural rework, and delivers to a client who already understands what they have.

That is as close to a genuine win for everyone involved as solo development tends to get. Not because use cases are magic, but because building things together tends to produce better outcomes than building things for people.

Alignment does not maintain itself. Left unattended, it decays quietly until the distance becomes visible only at delivery. It must be enforced, and enforcing it requires something legible enough for both sides to engage with. That is exactly why I rely on use cases.

If that alignment breaks down, good architecture will not save the project. No amount of careful design will save a project that is building the wrong thing.

Next article: How I Work Solo Without Losing Reliability

Learn Cotomy

Cotomy is a DOM-first UI runtime for long-lived business applications.