We Deleted 14 Microservices and Went Back to a Monolith. Best Decision We Made
Fourteen microservices. Six engineers. You can do that math — it's more than two services per person, and every one of them had its own repo, pipeline, dashboards, and opinions about being woken up at 3am.
Last year we merged all of it back into one boring deployable, and it's the best engineering decision we've made. Deploys went from 40 minutes to 4. Pages dropped 70%. This is the story, including the part where the microservices were my idea.
What going back to a monolith got us
- ✓Deploys: 40 minutes of orchestrated dread → 4 minutes, any commit, any time
- ✓On-call pages down ~70% — most of ours were the seams between services, not the services
- ✓AWS bill down about a third after killing per-service infrastructure
- ✓A three-week cross-service feature is now a one-afternoon pull request
Should a small team use microservices?
Almost never. Microservices solve an organizational problem — letting many teams deploy independently without stepping on each other. If you don't have many teams, you're paying the full cost of a distributed system (network failures, distributed debugging, duplicated infra, eventual consistency) to solve a problem you don't have. Under roughly 20–30 engineers, a modular monolith gives you clean boundaries with function calls instead of network calls, and one deploy instead of fourteen.

14 services, 6 engineers. The diagram was the only impressive part.
How we got into this mess
In 2022 we did what half the industry did: we read the Netflix and Uber engineering blogs and concluded that's what serious companies do. Never mind that Netflix has thousands of engineers and we had five at the time. We split the product along what felt like clean lines — auth, billing, notifications, search, a half-dozen domain services — and for the first few months it felt great. Small repos. Clear ownership. Diagrams that impressed investors.
The bill came due slowly, then all at once. A typical feature — say, showing a billing warning inside the main product flow — touched three services. That meant three PRs, coordinated across three deploy pipelines, with API version compatibility between each pair, feature-flagged so the middle deploy didn't break production. What would have been an afternoon in one codebase became a three-week project with a rollout plan.
Debugging was worse. When something failed, the stack trace stopped at a network boundary and the truth was smeared across four services' logs. We bought tracing tools. We spent real engineering weeks building correlation IDs through every hop. We were six people, and we had a part-time job just operating the seams between our own code.
The moment it broke
The push came from an outage, because it always does. A routine deploy of the notifications service subtly broke message ordering with the billing service. Customers got payment-failed emails for payments that succeeded. The bug took four days to fully diagnose because it lived in no service — it existed only in the interaction between two of them, in a retry policy on one side meeting an idempotency assumption on the other.
In the postmortem, our newest engineer asked the question everyone senior had been avoiding: "What do we actually get from these being separate?" We went around the room. Independent scaling? Two services had ever needed it, and one of those was a cron job. Independent deploys? We coordinated most deploys anyway because of API coupling. Team autonomy? We were six people who sat in one Slack channel. The honest answer was: a diagram.
💡 The test we should have applied in 2022
How we merged 14 services without stopping feature work
We didn't big-bang it. The migration ran five months alongside normal roadmap work, one service at a time, and the pattern was mechanical enough that it never felt risky:
Move the code, keep the interface
Each service became a module inside the main app — its own folder, its own tables, one public interface file. The code barely changed; only its address did.
Point callers at the in-process version
HTTP calls to the old service became function calls to the module, behind a flag so we could flip back instantly. Same contract, minus the network.
Watch it, then delete the deployment
A week or two of both paths running, then we killed the service, its pipeline, its dashboards, and its line items on the AWS bill. Fourteen small funerals. Nobody cried.
The keyword in what we built is modular monolith. We kept the discipline microservices had forced on us: modules can't touch each other's tables, cross-module calls go through explicit interfaces, and a lint rule fails the build on violations. That's the part worth keeping from the microservices era — the boundaries. It turns out you can have them without the network in the middle. And funnily enough, modern AI coding tools work dramatically better in the merged codebase too — an agent can trace a full feature end to end in one repo, which was hopeless across fourteen. If you're curious what those tools handle now, I compared them in the best AI coding agents of 2026.
We're not special — this is a wave
The famous example is Amazon Prime Video, whose team wrote up how consolidating a serverless microservices workflow into a monolith cut their infrastructure cost by 90%. Since then the case studies have kept coming, and by 2026 "we went back to a monolith" has gone from confession to almost a genre. The pattern in nearly all of them is ours: a small-to-mid team adopted the architecture of a 2,000-engineer company, paid the distributed-systems tax for years, and discovered the benefits were conditional on a scale they never reached.
| Question | Microservices win | Monolith wins |
|---|---|---|
| How many teams deploy independently? | Many teams shipping in parallel | One team, or a handful |
| Do parts scale wildly differently? | Yes, orders of magnitude | Mostly scales together |
| Can you afford dedicated platform work? | Yes, real platform team | Everyone is product engineering |
| Where do your outages come from? | Inside components | The seams between them |
| What does a cross-cutting feature cost? | Acceptable coordination | Three weeks for an afternoon of work |
None of this means microservices are bad. It means they're a payroll-shaped tool: the architecture is a mirror of your org chart, and if the org chart is one pizza, the mirror should be too. The teams that genuinely need service boundaries know it from pain, not from blog posts.
FAQ
Should a small team use microservices?+
What is a modular monolith?+
Why are companies moving back from microservices?+
How do you migrate from microservices back to a monolith?+
The uncomfortable lesson wasn't about architecture at all. It's that we chose our design to look like serious engineering instead of to serve six actual people — and the fix, like most good engineering, was making the system embarrassingly simpler. If the constant firefighting this system caused sounds familiar, the human side of that story is in my piece on what developer burnout actually looks like.
Keep Reading
Try Our Free Tools
Want more guides like this?
Join 50K+ readers getting weekly tips on AI, automation & making money online.
Subscribe Free

