Saga

Microservices

a microservice architecture decomposes one application into many independently deployable services, each owning its own data, talking over a network. the honest framing: you are trading a code organisation problem for a distributed systems problem. 𐃏 that trade is sometimes worth it. it is not worth it nearly as often as conference talks suggest.

the trade, not the hype

what you actually buy

  • independent deployment: team a ships without waiting for team b’s release train. this is the real prize — everything else is secondary.
  • independent scaling: scale the search service to 40 replicas while billing idles on 2.
  • fault isolation: a memory leak in recommendations does not take down checkout — if you also build the resilience machinery below. isolation is earned, not free.
  • technology heterogeneity: the ml service can be python while the ledger is jvm. (also a curse: n stacks to patch.)
  • organisational scaling: conway’s law working for you — service boundaries that mirror team boundaries let teams own code end to end.

what you actually pay

  • every in-process function call that crosses a new service boundary becomes a network call: it can now fail independently, time out, arrive twice, or arrive late.
  • transactions that were a single BEGIN...COMMIT become sagas (below) — you give up atomicity across boundaries and must design compensation by hand.
  • refactoring across service boundaries is an order of magnitude harder than moving code between modules — the boundary is now an api contract with independent release cadences (Fowler, Martin, 2018).
  • operational surface explodes: per-service ci, dashboards, alerts, on-call, versioned contracts, backwards-compatible migrations.

when a modular monolith wins

  • a modular monolith — one deployable, strictly enforced internal module boundaries, one database with schema-per-module discipline — captures most of the design benefit at a fraction of the operational cost.
  • you get cheap refactoring while the domain boundaries are still wrong (they always start wrong), real stack traces, local transactions, and one thing to deploy.
  • the sane migration path is monolith-first: find the boundaries by living with them in-process, then extract the one or two services that genuinely need independent deployment or scaling — the strangler fig approach of routing traffic incrementally to extracted pieces. 𐃏
  • rule of thumb: if one team can hold the whole system in its head and deploys are not blocked on other teams, microservices solve a problem you do not have.
the same domain twice: one deployable with internal modules and one database, versus independently deployable services each owning its own store, fronted by a gateway.

decomposing a system

bounded contexts (ddd-lite)

the useful sliver of domain-driven design:

Read more >