50%

الدرس 1 من 2

Independent Deployability, and What It Costs

A microservice is defined by one property, and everything difficult about the style follows from it. The prerequisites are organisational as much as technical.

قراءة 10 دقيقة

Definitions of microservices usually involve size, and size is the least useful attribute. A service is not small or large; it is independently deployable. If you can release it without releasing anything else, it is a service. If you cannot, it is a module that happens to have a network interface, and you are paying for distribution without receiving it.

Independent deployability requires several things at once, and each of them is where the cost lives. The service must own its data, or a shared schema forces coordinated releases. It must tolerate its dependencies being unavailable or an old version, or the deployment order returns. Its interface must be versioned so consumers are not broken. And someone must be able to operate it in production, which is where the organisational cost appears.

CapabilityWhy it becomes necessaryTypical cost
Independent deployment pipelineThe service must release without the othersTemplated after the first, but each has its own failures
Distributed tracingA request now crosses several processes and no single stack trace existsA tracing backend, plus propagation in every service and client
Centralised structured loggingCorrelating an incident across services is otherwise impossibleLog aggregation, retention cost, and a correlation identifier everywhere
Contract versioning and testingA consumer must not break when a provider deploysConsumer-driven contract tests and a deprecation policy
Resilience at every call siteAny dependency can be slow, down, or return twiceTimeouts, retries, idempotency keys, circuit breakers, fallbacks
Service-level ownership and on-callA service without an owner degrades and nobody noticesA rotation per service or per team, which is a staffing decision
Data consistency without transactionsA business operation now spans several storesSagas, compensations, and eventual consistency in the product design
What each service now needs, and roughly what it costs to provide. These are the entries teams leave out of the estimate.

The distributed monolith, in more detail

Chapter 1 introduced this as a failure mode. It deserves a second look here because it is the outcome of most unsuccessful splits, and because it is recognisable early — usually within the first two extractions, long before anyone admits it.

  1. 1**A required deployment order.** The single clearest symptom. If a runbook says which service goes first, they are not independently deployable and the whole cost is being paid for nothing.
  2. 2**A shared database.** Two services writing the same tables cannot change schema independently, which removes independent deployment mechanically rather than culturally.
  3. 3**Synchronous call chains.** A request that traverses four services synchronously has the availability of the product of all four and the latency of their sum, and the failure of any one fails the request.
  4. 4**Shared libraries carrying business rules.** A rule change now means releasing the library and every service that uses it, in order. Shared *technical* libraries are fine; shared *domain* libraries recreate the coupling.
  5. 5**Cross-service transactions attempted with two-phase commit.** Usually a sign the boundary is in the wrong place: the operation is one unit of work and the split cut through it.

In practice

Buying independence that was actually needed

A payments company had one modular monolith and a genuine problem: its card-authorisation path had a 99.99% availability commitment written into merchant contracts, while the rest of the system — reporting, merchant onboarding, dispute handling — had no such requirement and was deployed several times a day.

Constraints

  • Authorisation must survive the failure of every other component
  • Contractual 99.99% availability on authorisation only
  • Other components deploy 5 to 10 times a day
  • Team of 45 across six squads, with an existing platform team

Decision

Extract card authorisation into its own service with its own datastore, its own deployment pipeline and its own on-call rotation. Leave everything else in the modular monolith.

Why

The justification was a differing availability requirement, which is one of the four strong signals: frequent deployments of unrelated features were a standing risk to a contractual guarantee. Isolating the authorisation path meant a bad reporting release could no longer affect it, and the authorisation service could adopt a slower, more careful release process appropriate to its risk.

What it cost

Authorisation can no longer read merchant configuration in the same transaction, so it keeps a locally cached projection updated by events — which is up to a few seconds stale, and the team had to design what happens when a merchant is disabled during that window. They chose to fail closed on the authorisation side, accepting a small number of incorrectly declined transactions over any risk of authorising for a disabled merchant, and documented that choice where the support team could find it.

Estimating a microservices migration

As a developer

Estimates the work: splitting the code, defining the interfaces, setting up pipelines, migrating the data. That estimate is usually reasonable for the work it covers.

As an architect

Adds the permanent costs that are not in the estimate because they are not a project: an ongoing platform capability, on-call rotations, contract testing, tracing, and the product work of designing for eventual consistency in specific flows. Those typically consume between 5% and 15% of engineering capacity forever, and leaving them out is what makes migrations arrive late and disappoint. Saying it plainly at the start is far better received than discovering it in month nine.

A team has extracted three services. Each has its own repository, its own pipeline and its own team, but all three read and write the same PostgreSQL schema. Do they have microservices?Reveal

No. They have three deployables and one system. Any schema change requires all three to be updated and released together, so the defining property — deploying one without coordinating with the others — does not hold, and they are paying network latency, serialisation, distributed debugging and three pipelines to receive nothing in return. The repositories, pipelines and teams are all real and all beside the point. The path forward is to decide which service owns which tables and give the others an interface — an API, events, or a maintained read model — and it is worth being honest that this is the expensive half of the work they thought they had finished.

Key takeaways

  • A microservice is defined by independent deployability; size, repository count and team structure are consequences.
  • The property requires owned data, tolerant dependencies, versioned contracts and an owner who can operate it.
  • The prerequisites are organisational as much as technical, and are the part most often left out of estimates.
  • A required deployment order or a shared database means you have a distributed monolith regardless of the diagram.
  • The remedy for a distributed monolith is usually to merge and re-split along contexts, not to split further.