A Startup Autopsy: Building the Architecture Before the Product
Published on May 3, 2025 · 4 min read
In 2019, a friend asked me to help with “a few development bits” for a CRM startup. I was early in my career, and the product was already halfway through development when I joined.
The system had separate backend-for-frontend services for its mobile and web applications. Behind them were user, notification, administration, and email services. Several services had their own database or external provider integration. The team had also designed caching and reporting components that are omitted from the diagram below.
The diagram suggested a mature platform. The company still had no paying customers.
What the complexity cost
Microservices were a poor fit for the company’s immediate constraint. The team needed to learn whether anyone would pay for the CRM, while the architecture increased the work required to finish and operate it.
| Work | Effect of the architecture |
|---|---|
| Feature development | Changes could cross frontend gateways and several backend services |
| Testing | A scenario could require multiple services and their contracts to be available |
| Operations | Every deployed component needed configuration, logs, monitoring, and maintenance |
The engineers understood distributed systems. The problem was the amount of engineering committed before the product had customer evidence to guide it.
I had been brought in to implement features rather than review the architecture. I could see the coordination cost from outside the core team, but I did not push the discussion far enough. At that point in my career, questioning the system design felt outside the role I had been given.
Limits of the diagnosis
The startup closed a few months later. I did not have its full financial or sales context, so I cannot isolate architecture as the cause.
I can describe what I observed. The company had no committed customer generating revenue. Delivery involved coordination across a larger system than the current product required, and each service widened the operating footprint. The architecture consumed time and runway during a period when the company needed feedback.
That distinction matters because a simpler codebase would not have guaranteed a viable business. It would have reduced the cost of testing the idea.
Architecture should follow current constraints
For a product with no customers, the main technical requirement is often the ability to change direction without a long release process. A modular application could have preserved the same domain boundaries while running as one deployable unit.
Splitting those modules later would still involve work. The company could then make that investment in response to evidence gathered while operating the product.
Customer count is not the only input. A small product may need strict isolation for regulatory reasons, or it may depend on an integration with unusual availability requirements. The point is to connect each architectural boundary to an observed constraint.
Questions I now ask
Before adding a service or infrastructure component, I record the current problem and the evidence that it exists. I also describe which change becomes easier, what the component will cost to operate, and when the decision should be revisited.
If those answers are based only on an imagined future scale, I keep the boundary inside the application and preserve a path to extract it later.
This also changes how I think about an MVP. It is a way to buy information with limited time. The implementation must still protect data and meet the product’s real reliability requirements, but work aimed at hypothetical scale competes with work that tests the product.
A different starting point
For this CRM, I would begin with one deployable application and a database, with modules that reflect the main business areas. Background work or an external integration could move behind a queue when its failure behavior justified that separation.
I would also define evidence for the next architectural change. Sustained load might justify independent scaling. Repeated release conflicts might justify separate ownership. A failure that must be contained could justify a process boundary.
The experience changed what I look for in an architecture diagram. I still care about scalability and reliability, but the number of boxes tells me little by itself. Each box should have a current responsibility and a cost the team has chosen to pay.
The question I carry into design reviews is: “Which problem does this boundary solve today, and what evidence shows that problem exists?”