← Back to search results

Signals That Actually Justify Splitting a Monolith

The most reliable signal that a monolith should split isn't code size or a sense that the architecture 'should' be microservices — it's that multiple teams are regularly blocked on each other's deploys, or that one part of the system has a genuinely different scaling profile (traffic pattern, resource shape, release cadence) than the rest and that mismatch is causing real operational pain. A monolith with clean internal module boundaries and one team owning it usually has lower operational overhead than the same system split into five services, because a split adds network calls where there were function calls, distributed transactions where there were database transactions, and a whole new failure mode (partial failure) that a monolith doesn't have to reason about. Splitting too early, before an org has the on-call maturity and shared infrastructure to operate distributed systems well, tends to produce a 'distributed monolith': multiple services that still deploy together and share a database, carrying all of microservices' operational cost with none of the independence benefit. If you're splitting, split along a genuine bounded context with its own data ownership, not along a technical layer (don't make 'the API layer' one service and 'the database layer' another) — that just relocates the coupling instead of removing it.

Related documents

When a service starts timing out under traffic spikes even though CPU and memory look fine, the culprit is usually a saturated connection pool, not the database itself. Here is how to confirm it and size the pool correctly.

GraphQL solves a real problem — overfetching and underfetching across many client shapes. Most internal, single-client APIs don't have that problem, and adopt the complexity without the benefit.

Rotating a database password or API key is simple in isolation. Doing it without an outage across every process holding the old credential in memory is the actual hard part.