What do you gain and what do you give up when you split a single application into multiple independently deployable microservices, versus keeping it as one monolith?
answer
- in-process call vs network call
- independent deploy & scale
- distributed system tax
- shared DB vs DB-per-service
- distributed monolith trap
basics
~20 sA monolith is one big program deployed as a single unit; microservices split it into many small programs that talk over the network. Microservices let teams work and scale independently, but add network calls, more infrastructure, and coordination overhead.
solid answer
~40 sA monolith packages all business logic into one deployable unit sharing one codebase, one build, and usually one database; microservices decompose that logic into many independently deployable services, each owning its own data, that communicate over the network (HTTP/gRPC/messaging). The appeal is independent deployability (ship one service without redeploying everything), independent scaling (scale only the hot service), and team autonomy (each team owns its service end-to-end). The cost is the 'distributed system tax': what used to be an in-process function call becomes a network call that can time out, fail partially, or arrive twice; you need service discovery, distributed tracing, contract versioning, and eventual consistency across service boundaries. For a small team or unproven product, that tax usually outweighs the benefit, which is why 'monolith-first' is a common heuristic.
go deeper
Should describe the basic shape correctly — one deployable vs many — and name at least one benefit (independent deploy/scale) and one cost (network calls can fail) without needing production war stories.
Should connect the split to team ownership and independent deploy pipelines, and name concrete new failure modes (timeouts, partial failures) rather than just 'more complexity.'
Should discuss data ownership (DB-per-service vs shared DB), idempotency/retries, and be able to say when NOT to split, using team size or deployment cadence as the deciding factor.
Should frame this as an organizational-design decision (Conway's Law) as much as a technical one, and be able to describe how to walk the decision back (recombining services) when it turns out wrong.
## The two shapes A monolith is a **single deployable application**: - one codebase - one build pipeline - one running process (or a small fleet of identical copies behind a load balancer) - typically one shared database All of its internal modules — say, billing, inventory, and notifications — call each other directly, in-process, as ordinary function calls. **Microservices** take those same logical modules and turn each into its own separately deployable service, with its own process, its own deployment pipeline, and usually its own datastore; instead of calling `billing.charge()` as a function, the inventory service now sends an HTTP request or a message over a queue to a separate "billing" service running somewhere else on the network. ## Why teams split This split exists to solve organizational and scaling problems that show up once a system and its team grow past a certain size. - **Deployment.** In a monolith, every deploy ships the entire application, so a one-line change to notifications still requires rebuilding, testing, and redeploying billing and inventory too; every team touching the codebase is coupled to the same release train and the same regression risk. Microservices let each team own a narrow slice of functionality end-to-end — its own repo, its own deploy schedule, sometimes its own language or database technology — so a bug fix in notifications ships in minutes without anyone else's sign-off. - **Scaling** has the same story: in a monolith you typically can only scale the whole process, even if only one module is CPU-hungry; microservices let you scale exactly the hot service and leave the rest alone, saving infrastructure cost. ## The distributed system tax Those benefits are bought with what is often called the "distributed system tax." An in-process function call is synchronous, type-checked at compile time, and either succeeds or throws. A network call between two services can time out, return a partial response, fail without the caller ever finding out whether the operation on the other side actually completed, or (with retries) get executed twice. That single change forces new concerns onto the team: - **retries and idempotency** - **circuit breakers**, so one slow dependency doesn't cascade into an outage everywhere - **distributed tracing**, to reconstruct a single user request across services - **service discovery**, so callers find the current address of an instance - **contract/schema versioning**, since two services can no longer be deployed atomically - and — because each service usually owns its own database — the loss of ACID transactions across service boundaries in favor of **eventual consistency**, sagas, or outbox patterns None of this exists in a monolith with a shared database and in-process calls. ## Failure modes in production In production, the failure modes of this tax show up as things a monolith simply cannot produce: 1. a request that hangs for 30 seconds because a downstream service is degraded and the caller has no timeout configured 2. data that looks inconsistent for a few seconds because an event hasn't yet propagated between services 3. a cascading outage where checkout goes down because a recommendations service it calls synchronously, without a fallback, went down first 4. a debugging session that used to be "read the stack trace" becoming "correlate log lines across a dozen services using a trace ID, if anyone remembered to propagate it." Teams that adopt microservices without building the operational muscle for this — centralized logging, tracing, on-call runbooks per service, automated canary deploys — often end up with a **"distributed monolith,"** where services are still tightly coupled but now pay the full network-call tax on top of that coupling. ## Where it shows up A well-known real example is Amazon's early-2000s move from a large monolithic retail application to a service-oriented architecture, driven by the need to let hundreds of independent teams ship without blocking on each other — a scaling-of-teams problem, not primarily a scaling-of-traffic problem. Conversely, companies like Shopify and Segment have publicly documented pulling services back into a modular monolith after finding that, for their team size and traffic shape, the coordination and infrastructure overhead of many small services cost more than it delivered — evidence that the right answer depends on team size and deployment cadence, not on microservices being unconditionally "more modern."
- If microservices add so much operational overhead, why did Amazon and Netflix adopt them?Both were dealing with thousands of engineers and thousands of deployments per day; the bottleneck wasn't runtime performance but organizational throughput — teams blocking on each other's release trains. Microservices let each team deploy independently, trading a raised operational floor (tracing, on-call, service mesh) for removed coordination overhead at massive scale. For a 10-person startup that trade is usually inverted.
- What's the minimum operational tooling you'd want in place before splitting a monolith into services?Centralized structured logging and distributed tracing with correlation IDs, health checks and automated rollback in CI/CD, a service registry or discovery mechanism, and defined timeout/retry/circuit-breaker policies for every inter-service call. Without these, failures become undebuggable rather than merely more frequent.
- Does splitting into microservices always mean giving each service its own database?Not by rule, but it is the common recommendation, because a shared database re-couples services at the data layer and lets one team's schema change break another team's service silently. Some teams start with logically separate schemas in one physical database as a stepping stone before splitting datastores fully.
A monolith is one big kitchen where every cook can grab any ingredient off the shared counter instantly; microservices are a row of food trucks that must radio each other and hand food through a window — more flexible about who parks where, but every hand-off can get lost, delayed, or dropped.
saying these in an interview costs you the question
- Says microservices are always the 'more scalable' or 'more modern' choice with no caveat
- Doesn't mention that a network call can fail differently than a function call
- Thinks splitting services automatically gives independent deployability without decoupling the database first
- Can't name a single new operational concern (tracing, retries, service discovery) introduced by the split
- Believes microservices solve traffic-scaling problems that a load-balanced monolith couldn't also solve