skip to content

Distributed Monolith Anti-Pattern

The worst of both worlds: services that must be released together, share a database, and call each other synchronously in long chains. You will learn the symptoms and the moves back toward autonomy, and it is a very common interview question.

part ofMicroservices architectureoverview, primer and where to startread it →
on this pageshow

questions

6

In a microservices architecture, what is a 'distributed monolith', and what's usually the first symptom a team notices?

level: juniorimportance: must knowfreq 75%

answer

  1. lockstep deploys
  2. shared DB = shared monolith
  3. network calls, monolith coupling
  4. worst of both worlds
  5. Segment's 2018-2020 consolidation

basics

~20 s

It's when you've split code into separate services but they're still so tightly tied together that you can't deploy or change one without touching the others - you get all the complexity of microservices with none of the independence.

solid answer

~30 s

A distributed monolith is a system split into physically separate, network-connected services that nonetheless behave like a single monolith because of hidden coupling - shared databases, synchronous call chains, or a shared library/schema that forces coordinated releases. The classic tell is lockstep deployment: to ship a change, multiple teams must merge, test, and release their services together in a fixed order, because a change in one breaks contracts in another. You've paid for network latency, partial failures, and operational overhead, but gained none of the independent-deployability benefit that justified going to microservices in the first place.

go deeper

for a junior

Should recognize the term and give the lockstep-deployment symptom as the headline sign; doesn't need to name root causes precisely.

for a middle

Should name at least two concrete causes (shared DB, sync call chains) and connect them to the deployment symptom.

for a senior

Should be able to diagnose it from real symptoms (release calendars, incident postmortems) and explain why it erases the ROI of the migration.

for a principal

Should connect the anti-pattern to org design and migration strategy - e.g., how it commonly emerges from strangler-fig migrations stalled halfway, and how to prevent it up front via bounded-context-driven decomposition.

## What the term names A **distributed monolith** is a system decomposed into multiple physically separate deployables — separate processes, separate repositories, separate deploy pipelines — that communicate over a network, yet still cannot be changed, tested, or deployed independently because of coupling left over from (or introduced during) the split. The physical topology says 'microservices'; the runtime behavior says 'monolith.' Common causes include: - a **database shared** by several services - long chains of **synchronous blocking calls** between services - a **shared versioned client library** that embeds business logic and forces every consumer to upgrade together - **cross-service transactions** that must commit or roll back as a unit ## Why teams end up here This pattern exists because decomposing a system is hard, and it's much easier to physically move code into a new process than to properly separate the data and behavioral ownership behind it. Teams under delivery pressure often extract a module into its own service — new repo, new deploy pipeline, new Docker image — while leaving it pointed at the same shared database and the same synchronous call patterns it used as an in-process module. The org gets to say 'we did microservices' while the actual **coupling graph**, which is what determines whether teams can move independently, hasn't changed at all. ## The trade-off The trade-off is stark and almost entirely negative. - **True microservices** trade some complexity (network calls, eventual consistency, more infrastructure) for independent deployability, independent scaling, fault isolation, and the ability for different teams to choose different release cadences or even different tech stacks. - **A distributed monolith** pays the complexity cost — network latency on every call, partial failure modes, harder distributed debugging, more moving infrastructure parts — while keeping the monolith's core liability: you still can't change one part without coordinating everyone touching the coupled parts. It is, in a very real sense, worse than either pure architecture, because it maximizes cost while minimizing benefit. ## What it looks like in production In production this shows up as: - coordinated **release trains** ('every other Tuesday, Team A, B, and C deploy together in this order') - **change-freeze windows** spanning multiple 'independent' services - incidents where a bug in one service requires a synchronized multi-service rollback, because rolling back just one breaks the API/schema contract with the others - **testing environments** that require the whole cluster running, because no service can be meaningfully exercised alone Postmortems for such systems repeatedly contain language like 'root cause in Service X caused cascading errors in Service Y,' even though Y's team made no change that day. ## The documented example A well-known, publicly documented real-world example is Segment's 2018-2020 experience: after aggressively decomposing a monolith into many small services, the engineering team found that a large share of their operational pain came from exactly this pattern — services that looked independent on an architecture diagram but were, in practice, tightly coupled through shared infrastructure, cross-service calls, and shared ownership friction, forcing coordinated changes and complicating on-call. Segment published a well-known account of consolidating some of those services back toward a more monolithic structure specifically to eliminate this **coordination tax**. The lesson generalizes: decomposition without addressing the underlying data and call-graph coupling doesn't buy autonomy, it just relocates the coupling onto a network, and the fix is not 'un-splitting' as a rule but genuinely resolving the data ownership and call-chain issues driving the coupling, of which the Segment consolidation was one team's chosen remedy for their specific context.

  • If two services are always deployed together, does that alone prove it's a distributed monolith?
    Not necessarily - it's a strong signal but you need to check why. If it's because of a genuine, rare, coordinated schema or contract change, that's normal evolution; if every routine change to Service A forces a Service B redeploy, that's structural coupling and a real red flag. The distinguishing question is whether the coupling is incidental (once in the app's history) or systemic (every sprint).
  • Can a system with only one shared database ever be considered proper microservices?
    Generally no in the strict sense - database-per-service is one of the core tenets because a shared schema is a shared contract that any service can silently break for another. Some teams tolerate a shared database temporarily during a strangler-fig migration, but that's explicitly a transitional, not end, state.
  • How is a distributed monolith different from a poorly-modularized regular monolith?
    A poorly modularized monolith has the coupling problem but at least keeps deploys, transactions, and debugging local to one process. A distributed monolith adds network calls, serialization, and partial-failure modes on top of the same coupling, so you get the monolith's coordination cost plus the microservice's operational cost simultaneously.

Like six 'independent' food trucks that all draw ingredients from one shared walk-in fridge parked centrally - they look separate on the street, but if the fridge changes its shelf layout, every truck has to stop serving at the same time.

saying these in an interview costs you the question

  • Says microservices just means 'services running in different processes' without mentioning independent deployability
  • Can't name a symptom beyond 'it's when services talk to each other a lot'
  • Doesn't recognize shared-database or synchronous call chains as causes
  • Thinks splitting a codebase into repos automatically decouples it

context

open as a page

Why does having multiple 'microservices' read and write the same shared database (or even the same tables) recreate the coupling problems of a monolith?

level: middleimportance: must knowfreq 80%

basics

~10 s

The database schema becomes a hidden shared contract - if one service changes a table, every other service touching that table can break, so you can't change or deploy them independently anymore.

open as a page

When Service A calls Service B, which calls Service C, all over blocking synchronous HTTP, what is 'temporal coupling', and how does it turn a single slow dependency into a wider outage?

level: middleimportance: must knowfreq 78%

basics

~20 s

Temporal coupling means all three services must be up and responding fast at the same moment for the request to succeed - if C gets slow, B waits on it, then A waits on B, and the slowdown ripples backward through the whole chain.

open as a page

Without reading any code, what deployment and operational signals would tell you a 'microservices' system is actually a distributed monolith?

level: seniorimportance: should knowfreq 55%

basics

~20 s

Look at the release calendar and incident history: if services almost always deploy together, or one service's outage always drags others down with it, that's the tell - you don't need to read the code to see the coupling.

open as a page

You inherit a 'microservices' system that's really a distributed monolith - shared database, synchronous call chains, lockstep deploys. Walk through a concrete plan to migrate it toward true service autonomy.

level: seniorimportance: should knowfreq 65%

basics

~20 s

Figure out which service should really own each piece of data and behavior, move that ownership over step by step, replace direct cross-service database reads with API calls or events, and only split each piece of data into its own database once nothing else touches it directly anymore.

open as a page

Is a distributed monolith always a mistake to fix immediately? Discuss when it can be a rational, temporary state, and how Conway's Law and team topology influence whether it persists.

level: principalimportance: nice to knowfreq 40%

basics

~20 s

Not always - during a migration, having some temporary shared coupling can be the safer path. It becomes a real problem when it's permanent and when the teams responsible for the coupled services aren't structured to fix it.

open as a page