Whetstone
0day streak

Services & Boundaries

When splitting a system helps, and what it costs when it does not.

12

Questions

6/1/5

Easy / Med / Hard

Your accuracy

Splitting a system into services buys independent deployment, independent scaling, and clear team ownership. It charges network calls where you used to have function calls, and distributed failure where you used to have a stack trace.

Start with the monolith. A well-modularised monolith is easier to change than a distributed system whose boundaries are wrong, and boundaries drawn before you understand the domain are usually wrong. The strongest signal to split is organisational: separate teams needing to deploy on separate schedules.

Draw boundaries around data ownership. Each service owns its data and nobody else reads it directly. Two services sharing a database table are one service wearing a costume — you get the operational overhead of separation with none of the independence.

Distributed failure. Every call can now be slow, fail, or fail partially. Timeouts are mandatory: without one, a slow dependency exhausts your thread pool and your service dies of someone else's problem. Circuit breakers stop hammering a failing dependency and let it recover. Bulkheads isolate resource pools so one bad dependency cannot consume every connection.

Transactions across services do not exist. The patterns are sagas — a sequence of local transactions with compensating actions for rollback — or the outbox pattern, where you write the event to a table in the same transaction as the data change, then publish it asynchronously. Both trade atomicity for eventual consistency, deliberately.

The contract between services is the hard part. Once a call crosses a network it crosses a team boundary too, so every change to a response shape is a change to somebody else's release schedule. Stay additive, version explicitly when you cannot, and verify with consumer-driven contract tests rather than hoping — a mock both sides trust and neither verifies is how an integration breaks in staging.

Budget for the operational tax. A distributed system needs things a monolith gets for nothing: distributed tracing to answer which hop was slow, correlated logs to reconstruct one request, per-service dashboards and on-call rotas, and a deploy pipeline repeated across every repository. None of it is optional and none of it is interesting, which is why it tends to be discovered rather than planned. A team that cannot absorb that cost has bought a liability rather than a boundary.