Distributed Monolith
A distributed monolith splits an application into separately deployed services while retaining strong runtime and organizational coupling. The result can combine the operational complexity of microservices with many of the coordination and change-management constraints of a monolith.
A distributed monolith often appears when service boundaries are created around deployment units rather than meaningful business capabilities. Services may have independent processes and deployments, but a single request can require many synchronous calls across them, making the system behave like one tightly coupled application at runtime.
A key warning sign is that changing one business capability routinely requires coordinated changes and releases in several services. Shared databases, shared domain models, chatty APIs, synchronized deployments, and cross-service transactions can reinforce this coupling. In Java systems, this can be especially visible when Spring Boot services call each other synchronously through REST or RPC for operations that could have remained within one module.
The architecture is not inherently bad merely because services communicate. Distributed systems normally require communication. The problem is excessive coupling: services cannot evolve, deploy, scale, or fail independently enough to justify the additional network, observability, deployment, and operational complexity.
A senior engineer should first identify the coupling mechanism before proposing a rewrite. Possible remedies include consolidating tightly coupled services, defining stronger module boundaries, removing unnecessary synchronous calls, assigning clear ownership of data, introducing asynchronous messaging where appropriate, and designing APIs around stable business capabilities rather than internal implementation details.
Key points
- Separate deployment does not guarantee independent architecture.
- Synchronous call chains, shared databases, and coordinated releases are common coupling signals.
- Distributed monoliths inherit network and operational failure modes without obtaining proportional autonomy.
- Service boundaries should reflect cohesive business capabilities and ownership.
- Consolidation can be a valid fix; not every service needs to remain independently deployed.
Interview questions
What is a distributed monolith, and how would you recognize one?
A distributed monolith is a set of separately deployed services that remain tightly coupled in how they change or execute. Typical indicators include long synchronous call chains, shared databases, synchronized releases, and changes that routinely span multiple services. I would examine dependency graphs, deployment history, database ownership, and failure propagation rather than judging the architecture from the number of services alone.
Why can a distributed monolith be more difficult to operate than a monolith?
It adds network boundaries, partial failures, distributed tracing, service discovery, deployment coordination, and additional monitoring requirements. If the services remain tightly coupled, those costs exist even though the architecture has not gained much independent scalability or evolution. A single logical operation can also fail because a downstream service is unavailable or slow.
How would you refactor a distributed monolith?
I would first map business capabilities, runtime dependencies, data ownership, and change dependencies. Then I would identify boundaries where responsibilities are cohesive and dependencies are limited. Depending on the findings, I might consolidate services, split a capability more cleanly, move toward asynchronous integration, or establish explicit data ownership rather than performing a wholesale rewrite.
Are synchronous calls between microservices always a sign of a distributed monolith?
No. Synchronous communication can be appropriate when a request genuinely requires an immediate response from another capability. The concern is excessive or cascading synchronous dependency, especially when services cannot operate or evolve independently without coordinating with one another. I would evaluate the business dependency, call-chain depth, ownership, failure behavior, and deployment coupling.
How do shared databases contribute to distributed-monolith behavior?
A shared database can make service boundaries mostly organizational rather than architectural because multiple services depend on the same schema and data structures. A schema change may therefore require several teams or services to change together. Strong ownership boundaries, APIs, or events can reduce that coupling when independent evolution is actually required.