Estimated reading time: 8 minutes
Key takeaways:
- Microservices are an organizational decision. Every service boundary creates a boundary people must navigate, an expensive tax on learning for early-stage startups.
- Resilience means different things at different stages. When infrastructure failed, the platform survived but the engineering org didn’t.
- Architecture should solve today’s bottlenecks, not tomorrow’s ambitions.
We thought we were making the responsible engineering decision. We had read the architecture blogs, watched the conference talks, and done everything except ask whether any of those corporate speakers were also trying to close a seed round with four engineers and a prayer.
Like many startups, we looked to organizations we admired and adopted what seemed to be the industry gold standard: independently deployable microservices, isolated databases, asynchronous messaging, and service ownership aligned to bounded contexts.
The playbook promised the same thing every time: build for scale early, and you won’t have to rebuild it later.
The problem was that we were not operating at the scale of a global technology giant. We were a seed-stage startup that was still finding product-market fit. Our primary engineering challenge was not handling millions of concurrent users – it was shipping features fast enough to learn whether customers actually wanted what we were building.
Your inbox, upgraded.
Receive weekly engineering insights to level up your leadership approach.
Instead, we built an architecture optimized for a future we had not yet earned. A simple password reset touched multiple services. Adding a customer-facing feature required coordination across several repositories, deployment pipelines, and engineering owners. Every sprint involved more conversations about interfaces than about customers.
The architecture was not failing because it could not scale – it was failing because it had scaled our coordination costs.
Eventually, we made a decision that felt almost heretical. We deliberately reversed years of conventional industry advice by consolidating services, merging databases, and reorganizing engineering teams around products instead of infrastructure. It remains one of the highest-leverage engineering decisions we have ever made.
The operational tax of distributed systems
Microservices are often presented as a technical architecture decision. In reality, they are an organizational decision. Every service boundary you introduce in software creates another boundary that people must navigate.
A change that once required modifying a single codebase now requires coordinating multiple repositories, deployment pipelines, application programming interfaces (APIs), owners, and release schedules. The problem is that none of it is free.
One feature became our recurring reminder. Changing a customer’s password sounded trivial, the kind of feature a junior engineer should ship during their first week. It was not trivial.
The request passed through an API gateway into an identity service. The identity service emitted an event consumed by an audit service. A notification service generated an email confirming the change, while another service updated customer activity records. Each service maintained its own repository, deployment pipeline, test suite, and engineering owner. No individual step was particularly difficult; the complexity came from everything surrounding the code.
A small product improvement suddenly depended on multiple pull requests, coordinated deployments, contract compatibility, integration testing, and careful sequencing. If one pipeline failed or one service owner was unavailable, the entire feature stalled. What should have taken hours routinely stretched into days or weeks.
We had adopted microservices to increase delivery speed and engineering independence. Instead, we had increased the amount of communication required for even the smallest change. We did not eliminate complexity by adopting microservices. We just moved it into meetings.
Distributed systems do not eliminate complexity – they relocate it. In a monolith, much of the complexity exists inside the codebase. In a distributed architecture, it moves into communication between systems, deployment processes, and ultimately, between people.
For an organization with hundreds of engineers, that tradeoff can make perfect sense. For a seed-stage startup with a lean engineering team, those same boundaries become an expensive tax on learning.
More like this
Architecture always wins. The only question is who pays the bill: the software or the engineers.
Redefining system resilience during regional infrastructure failure
In March 2024, a catastrophic undersea cable failure severely disrupted internet connectivity across much of West Africa. The near-total blackout cost the Nigerian economy over ₦273 billion (more than US $198 million at current exchange rates) in its first four days alone. Banking applications went dark, point-of-sale terminals failed, and major telecommunications networks suffered extreme data degradation.
For us, it was the moment our architecture told the truth.
The platform technically stayed online. Queues absorbed traffic exactly as designed. Individual services continued operating in isolation. On paper, our distributed system was demonstrating precisely the resilience we had built it for. When the networks stabilized, however, we found our data had silently drifted into separate realities.
Orders sat in inconsistent states across multiple databases. Payments had completed while downstream inventory updates were still pending. Reconciliation jobs required manual intervention before we could safely continue processing transactions. Nothing had been permanently lost, but we spent two full days tracing requests across services and reconstructing the state of individual customer orders before we were confident enough to resume normal operations.
That incident forced us to ask a question we had avoided until then: what did resilience actually mean for a company at our stage?
The platform survived, but our engineering organization did not.
Resilience is often discussed in terms of uptime, redundancy, and fault tolerance. Those qualities matter, but for an early-stage company, another form of resilience is even more valuable: the ability to understand the system quickly, recover from incidents confidently, and continue delivering product improvements without organizational friction.
We had optimized for the resilience of the platform. What we actually needed was the resilience of the engineering organization.
The technical logistics of data consolidation
Deciding to simplify the architecture was straightforward, but execution proved significantly more complex. One of the principles we had followed religiously was that every service owned its own database. It was great for enforcing boundaries – until we needed to undo those boundaries. Relationships once enforced by database foreign keys had been replaced by Hypertext Transfer Protocol (HTTP) requests and asynchronous events. The database no longer protected our relationships. We did.
We could not simply export schemas and perform a wholesale import because the definitions had drifted significantly. Columns representing identical business concepts had drifted so far apart that two services had essentially developed their own dialects for the word “customer.” Neither was wrong, exactly. They had simply stopped talking to each other long enough to forget they were describing the same person.
We approached the migration incrementally rather than executing a single cutover, shifting traffic in small cohorts using feature flags, monitoring system telemetry, and maintaining rollback paths throughout.
Despite these safeguards, we still encountered production edge cases. During a key consolidation phase, an overlooked schema drift in a user activity sync script triggered a foreign key constraint violation. As our team lacked unified logging across our legacy relational database service (RDS) instances, identifying the failing query took nearly an hour. The resulting incident caused a two-hour system outage before we stabilized the environment.
The primary difficulty of undoing a distributed system is not deprecating code repositories. It is unearthing the hidden data assumptions that services quietly accumulate over years of independent isolation.
Reorganizing engineering teams around product outcomes
The codebase was not the only asset we consolidated – our teams changed as well. Before the migration, ownership mirrored our distributed architecture. One individual owned identity, another managed payments, and another handled notifications. The boundaries were clear, but every customer-facing feature crossed multiple domains.
That structure worked exactly as Conway’s Law predicts: our software reflected our internal communication patterns. Unfortunately, so did our bottlenecks. Nobody owned the complete customer experience; everyone owned a fragmented piece of it.
We reorganized around products instead of infrastructure. Rather than asking who owned the payment service, we started asking who owned the checkout experience. We reorganized into a focused, cross-functional team responsible for complete customer journeys. The same engineers who designed a feature could implement it, test it, deploy it, and respond to customer feedback without waiting for external handoffs.
The impact was immediate. Conversations became shorter. Design discussions focused less on service boundaries and more on customer outcomes. When an issue affected checkout, there was no debate about whether it belonged to payments, notifications, or customer accounts. The team responsible for checkout owned the problem from beginning to end.
We hadn’t just merged databases. We had eliminated organizational handoffs.

Berlin • November 9 & 10, 2026
Engineering leadership has never moved this fast.
See how other leaders are keeping pace at LeadDev Berlin.
Evaluating architectural trade-offs for early-stage growth
None of this means microservices are wrong. They are the correct answer for the right organization at the right moment. Independent scalability, fault isolation, and autonomous team ownership are legitimate engineering advantages when your actual constraint is scale.
Our mistake was not choosing microservices. It was choosing them before scale was our primary constraint.
The architecture was not failing because it was poorly designed. It was failing because it was optimized for a business we had not yet built.
At the seed stage, the ability to rapidly discover product–market fit is an organization’s most critical asset. Every architectural boundary that slows that discovery operates as a direct tax on business survival. If your engineers spend more time negotiating API contracts and coordinating deployment windows than shipping customer-facing features, the architecture has become an active bottleneck to your business goals.
Before adopting the distributed playbooks of larger technology organizations, honestly evaluate the constraints you are solving today. Optimize for your current stage of growth. Build for clarity. Ensure your architecture serves your team’s ability to learn, iterate, and deliver – not a hypothetical future.
We still use microservices today, but only where they have earned the right to exist.
For us, the most resilient engineering decision turned out to be the simplest one: build a system your team can actually understand, change, and recover from – even on a sunny Tuesday afternoon, when four undersea cables have just been cut, the repair ship is still weeks away, and nobody has had coffee yet.
The lesson wasn’t that microservices are wrong. It was that architecture should solve today’s bottlenecks, not tomorrow’s ambitions.
Looking back, our biggest mistake wasn’t choosing the wrong architecture. It was choosing someone else’s.