Building Software

What I've Learned · Dec 28, 2025 · Updated Oct 25, 2026 · 5 min read

Microservices vs Monolith: What Segment's 140 Services Cost

microservices-coordination-tax.jpg
_ □ ×
microservices-coordination-tax.md
_ □ ×

Twilio Segment did everything “right.”

Every destination they sent data to got its own service, its own queue and eventually its own repo, with shared libraries holding it all together.

On paper it looked clean. In practice it was coordination hell.

Three full-time engineers spent most of their time just keeping the system alive. In Segment’s words, “as our velocity plummeted, our defect rate exploded,” and on-call engineers kept getting paged for load spikes.

What sank them was the coordination tax. If you’re deciding between microservices and a monolith, start with a monolith unless several teams need to ship without waiting on each other. Segment shows what a small team pays when it splits early anyway.

The Hidden Cost of Distribution

Every new destination meant:

  • Another service to deploy
  • Another repo to maintain
  • Another version of “shared” libraries drifting out of sync
  • Another scaling profile to tune by hand

Architecture diagrams leave this part out. They look beautiful, and behind them sits a web of dependencies that need constant care and feeding.

The 2018 Segment engineering blog post on this migration is worth reading in full. They added more than 50 destinations over time, “and that meant 50 new repos.” Their own conclusion is damning: their server-side destinations were “a perfect example of how this popular trend can actually hurt productivity and performance.” For a small team, the coordination cost ate the benefits.

They Did the Unpopular Thing

They collapsed more than 140 microservices into a single, well-designed monolith.

The results, in Segment’s own numbers:

  • Shipping a shared-library change: before, it touched 140+ services. After, there was one service, and “one engineer can deploy the service in a matter of minutes.”
  • Shared-library improvements: 32 while the microservices were in place, 46 in the year after the move.
  • Pages for load spikes: “We no longer get paged for destinations that process small amounts of load.”

The test suite changed too. With over 140 destinations hitting real endpoints, it “could take up to an hour to run.” After they recorded the test traffic, tests for all of them ran in milliseconds.

Segment was also honest about what they gave up. Fault isolation got harder: a bug in one destination can now crash the service for every destination. They accepted that trade and leaned on their automated test suite to cover it.

When should you use microservices?

Most teams reach for microservices to scale. The thing they actually buy you is letting multiple teams work without waiting on each other.

They make sense when:

  • You have multiple teams that need to work independently
  • Different services have genuinely different scaling characteristics
  • You’re at a scale where organizational coordination is your bottleneck

They don’t make sense when:

  • A small team owns the entire system
  • Services share more code than they don’t
  • You’re optimizing for hypothetical scale you haven’t hit

Signs You’ve Built a Distributed Monolith

Watch for these in your own architecture:

1. The “Shared Library” Smell When your microservices depend heavily on shared libraries, you’ve just built a distributed monolith with network calls instead of function calls. Worse in every way.

2. The “Three Engineers Keeping It Alive” Pattern If your operational overhead is consuming your best people, something is wrong. Infrastructure should enable building, not consume all the building capacity.

3. The “One Team, Many Services” Anti-Pattern If the same team owns multiple services, you’re paying coordination tax without getting coordination benefits.

4. The “Deploy Everything Together” Test If you have to deploy multiple services together for most changes, you don’t really have microservices. You have a distributed monolith.

Where Microservices Pay Off

I’m not anti-microservices. They’re the right choice in specific situations:

  • Amazon/Netflix scale, when you have thousands of engineers and genuine scale challenges
  • Genuinely independent domains, when services truly don’t share data or logic
  • Different technology needs, when one service needs Python ML and another needs Go for performance
  • Regulatory boundaries, when data must be isolated for compliance reasons

But these situations are rarer than the industry pretends.

The Monolith Renaissance

We’re seeing a monolith renaissance, and it’s healthy. In March 2023 Amazon’s own Prime Video team wrote about moving a stream-monitoring service off distributed microservices built on AWS Step Functions and Lambda. The original design hit “a hard scaling limit at around 5% of the expected load.” Moving it to a monolith “reduced our infrastructure cost by over 90%.” That was one service, and the team was careful to say the choice “has to be made on a case-by-case basis.” But it was Amazon, running on AWS, and the monolith won anyway. Teams are realizing that a well-designed monolith is easier to:

  • Deploy
  • Debug
  • Test
  • Reason about
  • Refactor

DHH wrote How to recover from microservices the day after the Prime Video post went viral, and pointed out that GitHub and Shopify run their main applications as monoliths “with millions of lines of code” and thousands of programmers. He’d made the small-team version of the argument back in 2016 in The Majestic Monolith: Basecamp 3 shipped on the web, iOS, Android, Windows, Mac and email from one monolith, built by 12 programmers.

My Recommendation

For most startups and small teams:

  1. Start with a monolith. Always. You can extract services later when you have data about what actually needs to be separate. Martin Fowler made the same call back in 2015 in MonolithFirst: “Almost all the successful microservice stories have started with a monolith that got too big and was broken up.” My default monolith is Django with HTMX.

  2. Use modular architecture within the monolith. Draw boundaries in code, not in deployment. This gives you the organizational benefits without the operational cost.

  3. Extract only when painful. Wait until you have real pain before adding distribution complexity. Hypothetical scale isn’t a reason to add real complexity. It’s the same question I now ask before automating anything: should this exist yet?

  4. Measure the coordination tax. Track how much engineering time goes to keeping the system alive vs. building features. If the ratio is wrong, simplify.

The lesson from Segment is to pick the architecture that fits your team, and for most teams that means skipping distributed systems complexity.

Don’t let architecture astronauts convince you that your 5-person startup needs microservices. You need to ship. The same trade shows up one level down, in how much craft a piece of code deserves.

If you’re a founder about to split a five-person codebase into services, talk to me first. And if the real bottleneck is that every question about the business still goes through you, the founders page describes what I build for that.

Keep Reading