Architecture Patterns · lesson 2 of 7 · about 28 min
Microservices
Splitting a system, what you gain, and the new problems you buy: how a request through a chain of services compounds latency and failure, how pages are composed when data lives in many places, the distributed monolith, the per-service operations bill, boundaries that talk too much, and why a shared database cancels the benefit. Tap any for a plain-language card.
Each service is simple. The request that visits eight of them is not.
Chain several synchronous calls and the effects compound. Availability multiplies: eight services at 99.9% give 99.2%, about six hours of downtime a month. Latency adds, and so does the tail: the p99 of the chain is dominated by whichever hop was slow that time. Nothing here is a reason not to use services; it is why each hop must have a timeout, a fallback and a reason to exist. Set the chain.
Go from 1 to 8 services at 99.9%: availability drops by 0.8 points, and the p99 more than quadruples.
One service: p99
32 ms
6 services in a row: p99
109 ms
Request succeeds99.40%
Downtime a month4.3 h
Median latency66 ms
99th percentile109 ms
A request through 6 services that are each 99.9% available succeeds 99.40% of the time (4.3 hours of downtime a month) and takes 66 ms at the median and 109 ms at p99, against 32 ms for one service.
Availability = a^hops; latency is the sum of log-normal calls (σ = 0.5) around the median, 20,000 seeded requests.
Data lives elsewhere
The product page needs the product, the price, the stock, the reviews, the recommendations and the seller.
That is the same tail-latency effect as scatter-gather: with 8 parallel calls you meet the 99th percentile of a single call in about 8% of requests. Design responses: cache aggressively, return partial pages when a non-essential service is slow (the reviews can load later), set short timeouts, hedge requests, and keep the number of services behind one page small. Compare sequential and parallel composition.
Eight services at 30 ms each take about 280 ms in sequence and about 70 ms in parallel; the parallel p99 is still more than double the median.
1 sequential: p99
120 ms
1 parallel: p99
120 ms
2 sequential: p99
183 ms
2 parallel: p99
138 ms
4 sequential: p99
293 ms
4 parallel: p99
161 ms
8 sequential: p99
478 ms
8 parallel: p99
180 ms
16 sequential: p99
824 ms
16 parallel: p99
211 ms
Median69 ms
99th percentile187 ms
p99 ÷ median2.7×
Composing a page from 8 services in parallel takes 69 ms at the median and 187 ms at p99. Parallel is much better than the sum, but the more services you wait for the more often one of them is slow.
20,000 seeded requests; each call is log-normal (σ = 0.6) around the median. Sequential = sum; parallel = maximum.
Independence is the point
Twelve services that must be deployed together are not twelve services. They are one program with network calls.
The cures are contracts and discipline: backward-compatible changes (add fields, do not rename or remove, as in the events lesson), versioned APIs that run old and new side by side, consumer-driven contract tests, and expand-and-contract migrations. A service with many dependents has to be especially careful: the chance that a change breaks at least one of d callers is 1 − (1 − p)^d.
With 6 dependents and a 15% chance a change breaks any one, 62% of changes need coordination. With compatible, versioned changes it falls to 6%.
1 dependent
15% of changes need coordination
3 dependents
39% of changes need coordination
6 dependents
62% of changes need coordination
12 dependents
86% of changes need coordination
20 dependents
96% of changes need coordination
Changes that force a coordinated release62%
Chance a change breaks a given caller15%
With 6 dependents and a 15% chance that a change breaks any one of them, 62% of changes to this service force a coordinated release. That is a distributed monolith: independent deployment exists only on the diagram.
P(coordination needed) = 1 − (1 − p)^dependents. With backward-compatible, versioned APIs p is assumed to fall to 1%.
The cost nobody puts on the diagram
Every service needs a pipeline, dashboards, alerts, patching, an on-call rota, and someone who understands it.
This is why successful microservice organisations invest in a : shared paved roads (templates, pipelines, observability, service discovery, a service mesh) that cut the per-service cost to a small fraction. The microservice approach only pays when the platform exists. Set the numbers for your organisation.
60 services at 6 hours of upkeep each take 360 hours a week, nearly a quarter of 40 engineers. A platform that halves the upkeep returns about 11% of the team.
10 services
4% of engineering time
30 services
11% of engineering time
60 services
23% of engineering time
120 services
45% of engineering time
250 services
94% of engineering time
Hours of upkeep a week360
Share of the engineering team23%
Engineers equivalent9.0
60 services at 6 hours of weekly upkeep each (after a 0% platform saving) cost 360 hours a week: the equivalent of 9.0 full-time engineers, 23% of a 40-person team. A manageable tax, if the services earn it.
Hours = services × upkeep × (1 − platform saving); team capacity = engineers × 40 hours. The upkeep figure is a number to measure in your own organisation.
Boundaries cost
The same call, once inside the program and once across the network, differs by a factor of five thousand.
Good service boundaries follow business capabilities with high cohesion inside and few, coarse-grained calls across (ideally one request per user action), the idea behind domain-driven design's . If two parts must always change together or talk constantly, they belong in the same service. Check what a boundary would cost.
200 calls a request cost 20 microseconds in-process and 100 milliseconds across the network.
In-process (monolith)
0.020 ms
Across the network
100.0 ms
Slower by5,000×
Added latency per request100.0 ms
200 calls cost 0.020 ms inside one process and 100.0 ms across the network, 5,000 times more. A boundary here would make the request unacceptably slow: batch the calls, move the data, or keep both sides together.
Latency = calls × per-call cost. Network figures are typical same-data-centre orders of magnitude; a single hop can be much worse in practice.
Split or not?
Six situations, four calls.
Services pay off for independent teams and independent scaling, and cost heavily in operations and coupling. Each answer is worth 20 XP.
Ask: do these parts change independently, scale differently, talk rarely, and does a team own each?
Question 1 / 6
Two modules that change together in nearly every release and call each other 300 times per request.
Tip: press 1 to 4 to answer, Enter for the next one.
Who lives by this
From Amazon's mandate to Segment's retreat.
Four published stories about services.
The API mandateAmazon (c. 2002)
everything exposed through service interfaces
Widely reported accounts describe an internal mandate at Amazon that all teams expose their data and functionality through service interfaces and communicate only that way. It is often cited as the root of Amazon's service-oriented architecture and later of AWS.
After the outageNetflix
from a monolith to AWS services
Netflix has described how a major database corruption in 2008 led it to leave its data-centre monolith and rebuild as many cloud services over several years, trading simplicity for the ability to scale and to survive failures.
Grouping services into domainsUber's DOMA (2020)
domain-oriented microservice architecture
Uber described its experience of thousands of microservices making the system hard to reason about, and a move to group them into domains with gateways, to reduce the complexity of dependencies.
Going backSegment (2018)
'Goodbye Microservices'
Segment wrote about consolidating well over a hundred microservices, one per destination, back into a single service because the operational burden and the difficulty of making shared changes outweighed the benefit for its team size.
Interview angle
What interviewers actually ask.
Six questions, each worth 20 XP. Microservices questions test whether you know the costs as well as the benefits.
Name the benefit (independent teams and scaling) and the costs (network, data, operations) in the same breath.
Question 1 / 6
What is the main organisational benefit of microservices?
Tip: press 1 to 3 to answer, Enter for the next one.
Break it
Seven services read the same orders table. One team renames a column.
The rule is each service owns its data: only the owner reads and writes its tables, and everyone else goes through its API (or consumes its events). The owner can then reshape its tables freely behind a stable API, and its dependents see nothing change. It makes cross-service queries harder (the earlier scenes), which is the honest price of independence. Compare the two designs for one column rename.
Seven services on a shared table: seven teams must change in lock-step. With owned data, one.
Services that must change together7
Team-days of coordinated work35
Services broken if the rename ships alone6
Renaming one column breaks 6 other services the moment it ships, so all 7 teams must change, test and release together: about 35 team-days and a coordinated deployment. They are separate deployments only on paper.
Services that must change together = services touching the table (shared) or 1 (owned). Effort = services × days per team.