Previous article: Managing Client Risk as a Solo Contractor
Where This View Comes From
In small teams, projects often do not fail because the implementation is too difficult. They fail because knowledge disappears with a person, and the work can no longer continue coherently.
When I was younger, I often worked on large external projects through the kind of company structure where design and programming were treated as separate jobs. One group wrote the specifications. Another group implemented them. That separation was never perfect even then, but it was at least recognizable as an operating model.
Now the situation is changing again. Even where programming used to be treated as a clearly distinct role, part of that work may now be handled by AI. I do not think that removes the need for design. If anything, it makes the question of who understands the whole system more important.
What I want to write down here is not a universal method. It is simply how I think about projects done by one to three people, usually in direct contact with a client, or with the internal department that will actually use the system. Like the previous article, this is somewhat defensive in tone. That is intentional. But it is not meant as a rigid rulebook. The important point is still that the system has to be built together with the people who will use it. These are only patterns that have made that easier in my own experience. In teams this small, continuity is not guaranteed by role structure. It has to be constructed deliberately.
Small Teams Cannot Rely on Horizontal Role Separation
In a small team, I do not think horizontal role separation is realistic. Everyone needs to speak with the client, write requirements, design parts of the solution, and implement. Of course people still have strengths and weaknesses. In practice, one person may be better at organizing requirements, another at data design, and another at implementation speed. The work does get divided. But I still think the baseline assumption should be that every member understands the whole project well enough to keep it moving, even if individual efficiency differs.
There are several reasons for this. The first is obvious: when the team is small, there is very little redundancy. If one person is unavailable, there may be no specialist waiting beside them to take over that exact category of work. The second is that mutual checking is limited. You cannot expect deep review from a different perspective unless the reviewer already understands what the team is trying to achieve and what direction the project is moving in. The third is that direct communication with the client becomes one of the main mechanisms that keeps the project aligned. If only one person holds that context, the team becomes fragile very quickly.
Why I Start With Use Cases and Shared Diagrams
Because of that, I usually want the requirements stage to begin with people facing each other and writing use cases together. That includes the team members, and if possible the client or the actual users as well.
After that first step, the detailed use case descriptions may be divided and written individually. That is normal. But even when the writing work is split, I still think it helps enormously if at least the use case diagram is made together first. Once that shared picture exists, it becomes much easier to keep a common understanding through later work.
I like use cases for a simple reason. They are one of the few design artifacts that remain understandable to non-engineers without much translation. A sequence diagram, a class diagram, or a data model can all be useful, but they are not equally easy to share with the people who will actually operate the system. Use case diagrams and use case descriptions are simple enough to become common reference points instead of specialist materials.
There is also another practical advantage. Use cases do not only explain the system. They also make the list of things that must be achieved visible in a form the whole team can share. That makes them useful not only for alignment but also for progress control. When the target flows are written down clearly, people can see what has been clarified, what is still undecided, what has already been implemented, and what remains. In a small team, where planning and execution are often mixed together, that kind of shared progress surface is more valuable than it may sound.
I think this also connects naturally to a very reasonable Agile idea: progress should ultimately be judged by what actually works, not by how much documentation has been produced. That principle is sound. But in a small team, before working software exists, you still need some shared surface that makes the intended outcomes visible. Use cases work well for that. They are not a substitute for working software. They are one of the most practical ways to make pre-implementation progress visible before working software can take over that role.
There is another kind of document I treat as more important than many engineers seem to expect: meeting records, together with an index showing which meeting decided what. For the people who were in the room from the beginning, those records often feel unnecessary. They remember the conversation. But the person who joins later, or the person who inherits the system after the original developers have left, does not have that memory. For them, even a partial chronological trail is extremely valuable. Seeing how the current shape emerged is often the fastest path to understanding why certain decisions were made. Without that structure, the project becomes dependent on memory, and memory does not survive handover.
How Work Actually Gets Divided
After the early requirement stage, there are projects where I assign ownership by function. That still happens. But quite often, once the work has been broken into tasks, the team simply takes them from the front and moves through them in order.
I should add that I do not think this was always equally practical. When I was working in older environments with much weaker source control practices, this style was easier to break. Back when I was using Visual SourceSafe, I often had little choice but to divide work more rigidly by function, even in a small team. If multiple people touched the same area too freely, the coordination cost rose quickly and the risk of confusion rose with it. Under those conditions, saying that everyone should understand everything was one thing, but letting several people work across the same feature area was much harder in practice.
Branch-based workflows changed that significantly for me. With Git, and especially with the habit of splitting work into branches and then reviewing it through pull requests before approval, it became much easier for several people to touch the same feature without the whole process becoming fragile. I assume similar workflows are possible in other systems as well, but Git is the one I know from actual practice. What matters is not the brand name by itself. What matters is that the workflow makes it realistic for one person to implement a task while another still has a structured chance to understand, review, and approve the change.
That works only if everyone already shares the purpose of the project. When the requirement stage has been handled together, local misunderstandings are easier to fix through ordinary conversation. Review becomes easier as well. I prefer review to involve the whole team as much as possible, not because that is always the most efficient use of time in the short term, but because it keeps the shared understanding alive. I also do not mean that every change must always receive the same depth of review from every person. The cost is real, and when less experienced members are part of the team, that cost can rise sharply. I still think review is necessary and should be treated as necessary work rather than as waste, but how much of it should be fully shared is still something I judge case by case and am still trying to refine in practice. In a small team, shared understanding is part of the delivery capacity. It should be protected as such.
Document Granularity Matters More Than People Think
At the design stage, I care a great deal about document granularity. There are two reasons.
The first is planning with the client. At some point, I want to be able to stop and ask whether development should move to the next step, which functions should be implemented first, what effect is expected from them, and how later expansion is supposed to happen. That conversation becomes much easier if each function has been reduced to a simple enough unit that it can be recombined into an implementation plan.
When I need fine granularity, I often try to break the use cases down until they are no longer meaningfully divisible. At that level, the design documents start to sit very close to individual screens or very small functional units. That makes it easier to decide implementation order, to assign work in small pieces, and to see what exactly has or has not been finished. Of course, that level of detail has a cost. If everything is written repeatedly in full detail, the documentation effort becomes too heavy. So when I work this way, I usually try to save effort by defining common parts once in a shared place, and by not writing things that are already obvious either from those shared definitions or from ordinary common sense in the context of the project. I also think AI can be useful on the support side here. Organizing meeting notes, reshaping rough notes into cleaner drafts, and checking document consistency are all places where AI can reduce the clerical burden. What I do not think it can replace is the underlying act of deciding what actually matters and what must remain explicit. Without that kind of compression, fine-grained design can become more expensive than the project can realistically support.
The second is operational flexibility. If the design unit is too large, everything becomes all-or-nothing. Priorities cannot be shifted cleanly. Budget discussion becomes vague. And when something changes, the amount of redesign needed becomes harder to judge.
That said, I do not think there is one correct granularity for every project. If the client already has substantial system knowledge and a multi-year view of how the business will change, then larger design units may be more appropriate. In that kind of situation, I may keep the use cases somewhat broader, or even organize the documents more around business units than around near-screen-level functions. That kind of coarser structure can still support a meaningful discussion when the client is able to think in those larger operational chunks. So this is one of the places where flexibility matters most. The right granularity depends on the client’s goals, their familiarity with systems, and the real schedule pressure of the project. I think this choice affects success more than many formal development rules do.
What Matters Most in Solo Development
In solo development, the same continuity problem becomes even sharper. If something goes wrong and the work has to be handed over, the project needs enough structure to survive that handover.
What I consider most important is not a beautiful specification set in the abstract. It is the combination of design documents, an index showing where those documents are, meeting records, and a record of which meeting decided what. That package gives the next person a way in.
I say this because I have actually inherited a small project after the original person could no longer continue it. The other design documents mattered. They were not useless at all. Because they existed, I did not have to throw away partially written code and restart from zero. There was confusion, naturally, but the project could continue. Still, the single most helpful thing at the point of entry was the meeting record index. It showed the flow of decisions. Without that, understanding the half-finished code and half-finished design would have been much slower.
Why I Distrust Document-Light Small Projects
There are many practices in the world about design method and document style. I do not claim to have invented anything special here. What concerns me more is how often documentation itself seems to be treated as optional in small projects.
In the company where I work now, we have at times asked freelance engineers to build small systems. My impression, not as a universal law but as a repeated pattern, is that document work is often undervalued there. I have experienced this directly on the client side as well. There was a case where I asked an outside developer about an internal system when I did not have enough time to build it myself. There was no real requirements discussion. There was no meaningful clarification stage. From nothing more than the rough notes I brought to the first meeting, the developer came back with a mockup and an estimate far above what I had expected.
To be clear, I do not think mockups themselves are unnecessary. I use them too. But I think they should be used either as a way to help the client and developer reach agreement, or as a rough discussion surface that helps both sides react to something concrete. The problem is not making a mockup. The problem is treating the mockup as if it were a substitute for the slower work of understanding what is actually being asked for.
If I had not known how development work is supposed to be discussed, and if I had not spoken with other vendors before, that speed might have looked impressive. It might even have made the proposal look more professional. But speed at that stage is not always competence. Sometimes it only means that the hard part, which is understanding what should actually be built, has been skipped. Speed at that stage is not efficiency. It is the absence of understanding, and it often ends in expensive confusion or a system that is not really usable. That was enough for me not to trust that engagement, and I did not give that person the work.
The next point is not something I present as part of my own direct experience. It is something I have been hearing more often recently from people around me, including business contacts and engineer friends, and I do not claim to know the full details of every case or to be certain that it reflects society as a whole. Still, since AI coding agents became more common, I have heard more cases of people being approached with that kind of pitch, or of people trying that kind of work and then regretting it after the result turned out to be weak. The pattern, as it is described to me, is very cheap, lightly specified work with little or no documentation, repeated in short cycles and sold as if speed itself were the main proof of value. What concerns me is not only the quality problem. AI should be creating a real opportunity for small and medium-sized companies to build information systems that fit their own operations closely enough to compete more effectively with larger firms. If that opportunity gets flooded instead by disposable systems built without enough understanding, then one of the most valuable effects of AI-assisted development may be weakened rather than strengthened.
Continuity Is a Design Responsibility
When people talk about small-team development, they often focus on speed, flexibility, or cost. Those things matter. But I think continuity deserves equal attention.
A small team has to move quickly, yes. But it also has to leave enough structure behind that someone else can understand what happened, why it happened, and how to continue from there. That is why I care about shared use cases, shared review, manageable document granularity, and indexed meeting records. None of these things guarantee success. They simply reduce the chance that the project becomes dependent on one person’s memory.
For one-to-three-person development, I think that is one of the most practical definitions of good process. Not a process that looks advanced, and not a process that follows fashionable methodology, but a process that keeps the work understandable enough to survive reality. For me, continuity means the work can still be understood, continued, and completed even if the original developer is no longer present.