Archtin
All articles
ArchitectureSystem DesignMicroservices14 min read

Microservices Architecture: What You Actually Buy and What You Pay

Microservices trade in-process simplicity for independent deployability. Here is how to size services, own data, handle consistency, survive partial failure, and recognise the distributed monolith before you build one.

The actual definition

A microservice is a service that can be changed, tested, deployed and scaled independently of every other service, owning its own data. Everything else — size, line count, "one thing well" — is folklore. If two services must be released together, they are one service with extra latency.

The honest trade
You give up: ACID across the system, one stack trace, one deploy, cheap refactoring across boundaries. You get: independent release cadence per team, per-service scaling, fault isolation, and freedom of runtime. Only the first item on the second list is usually worth the whole bill.

Where to cut

  1. By business capability, not by entity. "Pricing", "Fulfilment", "Identity" — not "UserService", "OrderTableService".
  2. By team ownership. Conway's law is a constraint, not a warning. A service with two owning teams will always be a coordination bottleneck.
  3. By rate of change. Code that changes together should deploy together. Split at the seams where change frequency differs sharply.
  4. By data ownership. If two candidate services need transactional writes to the same table, they are one service.

A useful negative test: if implementing a typical feature requires changing three services in lockstep, your boundaries are wrong. Merge them and try again.

Database per service

This is the non-negotiable part. A shared database recreates the coupling you paid to remove: you cannot change a schema, cannot deploy independently, and any service can violate another's invariants.

Consequences you must design for:

  • No cross-service joins. Compose in the caller, or maintain a read model fed by events.
  • Duplicated data is normal. Orders keeps a copy of the product name and price at purchase time — and that is correct, since it is a historical fact, not a reference.
  • Reporting moves out. Analytics reads a warehouse fed by CDC or events, not the operational stores.

Synchronous vs asynchronous

StyleUse forDanger
Sync request-response (HTTP/gRPC)Queries the caller cannot proceed withoutLatency and failure chains; availability multiplies down
Async events (pub/sub)Reactions: notify, index, settle, auditInvisible control flow, ordering, duplicates
Async commands (queue)Work handed to one ownerBacklog growth, poison messages
checkout -> pricing -> inventory -> tax
each 99.9%  =>  0.999^4 = 99.6%  (~3.5 hours/month of failure)

same chain with events for tax + inventory reservation confirmation:
checkout depends on pricing only  =>  99.8%
Availability compounds across synchronous hops.

Rule: use synchronous calls only when the caller genuinely cannot answer without the reply. Everything else is an event.

Consistency without transactions

  • Saga. A business transaction becomes a sequence of local transactions with compensating actions on failure (refund, release stock). Choreographed via events for simple flows, orchestrated by a coordinator when the flow has real branching.
  • Transactional outbox. Write state and the outgoing event in one local transaction; a relay publishes afterwards. This is how you avoid "saved but never published".
  • Idempotent consumers. Brokers deliver at least once. Every handler needs a dedupe key and must be safe to run twice.
  • Read models. Denormalised projections built from events serve queries that would otherwise be cross-service joins.

Surviving partial failure

In a monolith, a dependency is either there or the process is dead. In a distributed system every call can be slow, duplicated, reordered or lost — and slow is the dangerous one, because it consumes the caller's resources.

  • Timeouts everywhere, shorter than the caller's own budget.
  • Retries with jittered backoff, only for idempotent operations.
  • Circuit breakers so a dead dependency fails fast instead of queueing.
  • Bulkheads so one slow dependency cannot exhaust shared pools.
  • Graceful degradation: serve the page without recommendations rather than not at all.

The platform you now need

This is the cost teams underestimate. Before the second service ships you need: CI/CD per service, service discovery, centralised structured logging, distributed tracing with propagated correlation IDs, per-service metrics and SLOs, secret management, contract testing, a schema registry for events, and a way to run a meaningful subset locally.

Readiness test
If you cannot answer "which service caused this slow request?" in under two minutes today, you are not ready to add another service.

The distributed monolith

Signs you built the worst of both worlds:

  • Services share a database or a schema.
  • A release requires deploying several services in a specific order.
  • A single user request fans out through six synchronous hops.
  • Shared libraries containing domain logic must be version-bumped everywhere at once.
  • Local development requires running the entire estate.

The remedy is usually merging services, not adding more infrastructure. Merging is a legitimate, senior architectural move.

Interview framing

Strong answer

"I'd split by capability along team lines: checkout, pricing, inventory, fulfilment, notifications. Each owns its database. Checkout calls pricing synchronously because it cannot complete without a price; everything else is events with a transactional outbox and idempotent consumers. Order placement is a saga with compensating actions for payment and stock reservation. I'd put timeouts, circuit breakers and per-dependency bulkheads on every remote call, and I would not start until tracing and per-service SLOs exist — otherwise we lose the ability to debug faster than we gain the ability to deploy."

Follow-ups

  • How do you produce a report that spans four services?
  • What happens when the payment event is delivered twice?
  • When would you merge two services back together?

Keep reading

Suggested next articles based on this one.

Design it, don't just read it.

Practise LLD and system design problems with structured rubrics and AI feedback.

Start practising free