In 2015, microservices were the future of software architecture. Netflix published their journey. Amazon decomposed their monolith. Thoughtworks put microservices on their technology radar as 'adopt'. Engineering conferences were overwhelmed with talks about service meshes, distributed tracing, and event-driven choreography. The monolith was officially dead.
In 2026, Amazon Prime Video publicly documented moving a critical streaming pipeline from microservices back to a monolith — reducing their infrastructure costs by 90% and cutting operational complexity dramatically. Shopify has operated on a Rails monolith for most of its existence and openly credits it for their ability to ship fast. Stack Overflow serves billions of page views per month from a small cluster of .NET servers. The monolith is not dead. The religion around microservices is.
What Went Wrong
Microservices solve real problems — but only at the scale where those problems actually exist. Netflix operates at a scale where independent deployability of 700 services is worth the operational overhead of managing 700 services. The median enterprise does not operate at Netflix scale. They operate at a scale where microservices introduce the complexity of distributed systems without the scale that justifies it.
"The right architecture for your system's current scale is almost never the architecture that would be right if you were 10x bigger. Optimising for the scale you don't have yet is how you build systems that are expensive to operate and slow to change."
The Distributed Systems Tax
Every microservices architecture pays what we call the Distributed Systems Tax: network calls that can fail, partial failure modes that don't exist in a monolith, distributed transactions that require saga patterns or two-phase commit, observability that requires distributed tracing infrastructure, and deployment complexity that requires a platform engineering team just to manage the deployment pipeline.
The Hidden Costs Most Teams Don't Count
- Service mesh operation — Istio or Linkerd require dedicated platform engineering headcount to operate correctly
- Distributed tracing overhead — Jaeger or Tempo add 3-8% latency overhead and significant storage costs
- Schema evolution across service boundaries — changing a shared data model requires coordinated deployment of multiple services
- Integration testing complexity — testing interactions between 20 services requires 20-service test environments
- On-call cognitive load — debugging a production issue that spans 8 services requires 8x the mental model of debugging a monolith
The Modular Monolith
The modular monolith — a single deployable unit with strong internal module boundaries — is not a step backward. It's a more honest architecture. Modules own their data and logic. Interfaces between modules are explicit. The monolith can be deployed to multiple instances for scale. When a specific module genuinely requires independent scaling or deployment, it can be extracted — at which point you have microservices where they're actually justified.
The BITSS Approach
For the enterprise systems we architect at BITSS, the default starting point is a well-structured Next.js application with clear domain boundaries and a single Postgres database. This is not 'beginner architecture'. For most enterprise problems — even at significant scale — it is the correct architecture. We extract to separate services when a module has a genuinely different scaling profile, requires a different technology, or needs independent deployment for security isolation. Not before.