The pendulum swings back: how the industry matured past “microservices for everything” toward pragmatic architecture decisions
For nearly a decade, microservices reigned as the unquestioned pinnacle of software architecture. Conference talks proclaimed them the solution to every scaling problem. Engineering blogs from Netflix, Amazon, and Uber made them seem inevitable. Resumes without “microservices experience” felt incomplete. The message was clear: monoliths were legacy, microservices were the future.
Then something unexpected happened. In 2023, Amazon Prime Video published a bombshell: they had migrated a critical service from microservices back to a monolith and reduced costs by over 90%. Not a typo—ninety percent. The tech world reacted with shock, denial, and ultimately, recognition. Maybe we’d overcomplicated things.
This isn’t about declaring microservices dead or monoliths superior. It’s about recognizing that architecture decisions should be driven by actual needs, not hype cycles. The industry is maturing, and with maturity comes nuance. Let’s examine what we’ve learned.
1. The Hidden Costs Nobody Talks About
Microservices architecture promises beautiful things: independent deployment, technology diversity, fault isolation, infinite scalability. What the conference talks don’t emphasize are the costs—not just financial, but cognitive, operational, and organizational.
1.1 Network Reliability: The Fallacies Return
In a monolith, function calls are reliable. They either work or they throw exceptions you can handle immediately. In microservices, every function call becomes a network request. According to real-world migration experiences, this introduces cascading complexity:
The Eight Fallacies of Distributed Computing: Engineers assume the network is reliable, has zero latency, infinite bandwidth, is secure, topology doesn’t change, there’s one administrator, transport cost is zero, and the network is homogeneous. Every single assumption is false. Microservices force you to design around all eight failures simultaneously.
A simple operation that was three method calls in a monolith becomes three HTTP requests in microservices. Each request can timeout. Each connection can fail. Each service can be temporarily unavailable. You need retry logic, circuit breakers, fallback strategies, and distributed tracing just to achieve what you had for free before.
1.2 Observability Complexity
Debugging a monolith: set a breakpoint, step through the code, examine the stack trace. Done.
Debugging microservices: correlate logs across 47 services, stitch together distributed traces spanning multiple message queues, hunt through Kubernetes pod logs, check service mesh metrics, verify API gateway configurations, and hope your correlation IDs propagated correctly. That notification service that used to be 200 lines of code in your monolith? Now it’s a full deployment with load balancers, health checks, distributed logging, and monitoring dashboards.
# Debugging a failed request in microservices kubectl logs service-a-pod-abc123 --since=10m | grep request-id-xyz kubectl logs service-b-pod-def456 --since=10m | grep request-id-xyz kubectl logs service-c-pod-ghi789 --since=10m | grep request-id-xyz # Check if message made it to queue rabbitmqctl list_queues | grep payment-events # Verify service mesh sidecar isn't blocking traffic istioctl proxy-config routes service-b-pod-def456 # Meanwhile, the customer is still waiting...
As one developer candidly shared, “We went from a $500/month cloud bill to $3,000/month after our microservices migration. Same features, same traffic. Just more overhead.” The CFO showing up six months later asking why costs tripled isn’t a conversation anyone wants.
1.3 Deployment Overhead
Each microservice needs its own:
- Container image and registry storage
- CI/CD pipeline configuration
- Kubernetes deployment manifests
- Service discovery registration
- Load balancer and ingress rules
- Monitoring, logging, and alerting setup
- Security scanning and compliance checks
- Database migration scripts
According to DORA metrics research, 90% of microservices teams still batch deploy like monoliths, negating the main architectural benefit. If you’re deploying everything together anyway, you’ve achieved maximum complexity with minimum benefit—the dreaded “distributed monolith.”
2. Case Study: Amazon Prime Video’s 90% Cost Reduction
Let’s examine what actually happened at Amazon Prime Video in detail, because the story contains crucial lessons.
2.1 The Bottlenecks
The distributed architecture hit scaling limits at just 5% of expected load. Two problems dominated:
1. Orchestration Costs: AWS Step Functions charges per state transition. With multiple transitions per second per stream across thousands of concurrent streams, the costs exploded. They hit account limits before hitting technical limits.
2. Data Transfer Overhead: Every frame had to be serialized, uploaded to S3, then downloaded by the next service. This Tier-1 S3 operation—writing and reading millions of intermediate objects—became the single largest cost driver.
2.2 The Monolith Solution
The team consolidated everything into a single process running on Amazon ECS:
// Conceptual simplified flow - before and after // BEFORE: Distributed with network hops Frame frame = mediaConverter.convert(stream); // Lambda 1 s3.upload(frame); // Network + Storage Frame stored = s3.download(frameId); // Network + Storage Defects defects = detector.analyze(stored); // Lambda 2 s3.upload(defects); // Network + Storage // ... more services, more network, more costs // AFTER: Monolithic in-memory Frame frame = mediaConverter.convert(stream); Defects defects = detector.analyze(frame); // Direct in-memory aggregator.store(defects); // Single final write // No intermediate storage, no network hops
By running the media converter and defect detector in the same process, they eliminated S3 intermediate storage entirely. Data passed through memory instead of over the network. The orchestration became simple in-process logic instead of expensive Step Functions.
Results: 90% infrastructure cost reduction, increased scaling capability to handle thousands of concurrent streams, and improved reliability by eliminating network failure points. The service now handles peak load with headroom to spare.
As Amazon CTO Werner Vogels commented: “Building evolvable software systems is a strategy, not a religion. And revisiting your architectures with an open mind is a must.”
3. Case Study: Segment’s Return to the Monolith
Another instructive example comes from Segment, the customer data platform. At QCon London, engineering leader Alexandra Noonan shared their journey from monolith to microservices and back again—a cautionary tale about premature optimization.
The key insight from Noonan: “If microservices are implemented incorrectly or used as a band-aid without addressing root flaws in your system, you’ll be unable to do new product development because you’re drowning in complexity.”
The Auto-Scaling Trap: Segment applied one auto-scaling rule across all services despite vastly different load patterns and resource needs. True isolation would have required 10,000+ microservices (one per queue per customer). The operational overhead would have been impossible to manage.
4. When Microservices Actually Make Sense
So are microservices always wrong? Absolutely not. But they solve specific problems under specific conditions. Here’s when the complexity is justified:
4.1 Team Size and Conway’s Law
According to validated research, microservices benefits only appear with teams exceeding 10-15 developers. Below that threshold, monoliths perform better. Why? Conway’s Law: systems mirror the communication structure of organizations.
With a team of 5 developers, coordinating on a monolith is straightforward. With 50 developers across 8 time zones, a monolith becomes a bottleneck. Microservices allow teams to work independently, own services end-to-end, and deploy without coordinating with 49 other people.
4.2 Genuinely Independent Scaling Needs
Netflix is the canonical example. Their video encoding service needs massive compute resources. Their recommendation engine needs different hardware profiles. Their billing service has completely different scaling characteristics. Each service scales independently based on actual demand.
But be honest: does your application really have these characteristics? Or are you optimizing for a scale you might never reach?
4.3 True Fault Isolation Requirements
If one component failing must not impact others, microservices provide genuine isolation. Netflix’s experience is instructive: after a 2008 database corruption took their monolith offline for four days, they migrated to nearly 1,000 microservices. Now when a service fails, it fails alone.
But this only matters if failures in one area genuinely shouldn’t impact others. If your checkout flow depends on inventory, payment, and shipping services, and a checkout can’t complete without all three, you haven’t gained isolation—you’ve just made debugging harder.
5. The Modular Monolith: Best of Both Worlds?
Enter the modular monolith—an architecture that’s generating renewed interest. The concept is simple: build your monolith with clear module boundaries from day one. Think microservices principles applied to monolith architecture.
5.1 Key Characteristics
Enforced Boundaries: Modules communicate only through defined interfaces. Use architectural testing tools to prevent violations:
// Example using ArchUnit for Java
@Test
public void paymentModuleShouldNotDependOnInventory() {
noClasses()
.that().resideInPackage("..payment..")
.should().dependOnClassesThat()
.resideInPackage("..inventory..")
.check(importedClasses);
}
Independent Development: Teams own modules like they’d own microservices. Each module has its own data access, business logic, and API. But everything deploys together, runs in the same process, and shares resources efficiently.
Evolutionary Architecture: The critical advantage: if you later need to extract a module into a microservice, the boundaries already exist. You’re not untangling spaghetti code—you’re moving a well-defined module to a separate deployment.
| Aspect | Traditional Monolith | Modular Monolith | Microservices |
|---|---|---|---|
| Development Speed | Fast initially, slows with size | Fast, stays manageable | Slow initial setup, then parallel |
| Deployment | Single binary, simple | Single binary, simple | Complex, 10-100+ services |
| Operational Overhead | Low | Low to Medium | High to Very High |
| Debugging | Straightforward | Straightforward | Complex, distributed tracing needed |
| Team Structure | Best for <10 developers | Works for 5-30 developers | Required for 15+ developers |
| Independent Scaling | Scale entire app | Scale entire app | Scale components independently |
| Technology Diversity | Single stack | Single stack | Different stack per service |
| Migration Path | Difficult extraction | Easy extraction to microservices | Very difficult to consolidate |
5.2 Real-World Modular Monolith Example
Shopify serves millions of merchants on a modular monolith. Their approach: clear domain boundaries enforced by tooling, isolated database schemas within the same database, and API contracts between modules. When they need to scale something independently, they extract that specific module to a microservice. Not everything—just what actually needs it.
6. Making the Decision
So how do you choose? Start with these questions:
Question 1: What’s your team size?
Fewer than 10 developers? Monolith or modular monolith. The coordination overhead of microservices will slow you down.
10-30 developers? Modular monolith gives you room to grow with an extraction path.
30+ developers across multiple teams? Microservices start making organizational sense.
Question 2: What’s your deployment frequency?
Monthly or quarterly? Your problem isn’t architecture—it’s process. Fix your CI/CD pipeline first.
Weekly? Modular monolith with solid automation works fine.
Multiple times daily? You might benefit from independent service deployment.
Question 3: Do components have genuinely different scaling needs?
Be honest. “Might need to scale differently someday” doesn’t count. Does your video encoding actually need 100x more compute than your API gateway today? If not, optimize for the scale you have, not the scale you imagine.
Question 4: Can you afford the operational complexity?
Do you have dedicated DevOps staff? Mature observability practices? Experience with distributed systems? Or are you a small team trying to ship features? Complexity has a real cost.
6.1 The Pragmatic Path
For most applications, the sensible approach is:
1. Start with a modular monolith. Design clear boundaries from day one. Use tools to enforce separation. This gives you 90% of microservices’ organizational benefits with 10% of the operational cost.
2. Measure actual pain points. Is deployment coordination slowing you down? Are genuine scaling differences emerging? Do you have proof, or just assumptions?
3. Extract services selectively. When you have evidence that a specific component needs independent scaling or deployment, extract just that service. Not everything. Just what actually needs it.
4. Stay humble. Amazon, Netflix, and Google run microservices at massive scale. You are not Amazon, Netflix, or Google. And notably, even they run monoliths for specific use cases.
7. What We’ve Learned
- The pendulum is swinging back from microservices hype as companies like Amazon Prime Video (90% cost reduction) and Segment publicly share their migrations back to monoliths after discovering distributed architecture costs outweighed benefits.
- Hidden costs of microservices are substantial including 3x cloud bill increases, network reliability challenges (every function call becomes an HTTP request), observability complexity requiring distributed tracing across dozens of services, and operational overhead for CI/CD, monitoring, and deployment of each service.
- Team size is the critical decision factor with research showing microservices benefits only appearing with teams exceeding 10-15 developers; smaller teams experience net productivity losses from coordination overhead and infrastructure complexity.
- Modular monoliths offer a pragmatic middle ground by enforcing module boundaries and clear interfaces within a single deployment, providing 90% of microservices’ organizational benefits with 10% of the operational cost while maintaining an evolutionary path to extract services when genuinely needed.
- The distributed monolith anti-pattern is common with 90% of microservices teams batch deploying everything together, achieving maximum complexity without the benefits—all the network calls, none of the independent deployment.
- Context matters more than architecture religion with Werner Vogels (Amazon CTO) emphasizing that “building evolvable software systems is a strategy, not a religion”—the best architecture depends on actual team size, deployment frequency, scaling needs, and operational capability, not conference talk hype.
Thank you!
We will contact you soon.
Eleftheria DrosopoulouFebruary 17th, 2026Last Updated: February 13th, 2026

This site uses Akismet to reduce spam. Learn how your comment data is processed.