Every decision here buys something and charges for it, and the charge usually lands where you were not looking. A cache buys read latency and hands you a staleness problem; a second region buys survival and hands you a conflicting-write problem. Nothing here is simply correct, which is why lists of patterns teach little. What follows is the shape of the trades: what changes when a call crosses a network, which numbers settle a design before any diagram, and why most scaling machinery answers a question your traffic has not asked.
Each chapter opens with the short version. Tap one to read the detail.
What changes when the call crosses a network
~2 min
The mistake that breaks systems is treating a remote call as a slower function call. It has a third outcome a local call cannot: silence. A timeout never tells you whether the work happened, so anything you retry has to be safe to run twice.
Count the work, not the requests
~2 min
One mistake in two costumes: sizing a system by average request rate, and balancing traffic by request count. Requests are not units of work — two can differ by a factor of a thousand — so both decisions rest on a misleading number.
Caching is cheap; invalidation is the bill
~2 min
"Add a cache" reads as free performance. A cache without a defined invalidation story is a correctness bug scheduled for later, because every copy raises the question of when it becomes a lie. Below roughly 80% hit rate it is not earning its costs either.
Splitting the data, and choosing where it lives
~2 min
Sharding gets treated as a routing problem, so the key is picked for even distribution. If that key is absent from your commonest query, every read fans out to every shard and waits for the slowest — a write bottleneck traded for a tail-latency one.
Copies, and what you are willing to promise about them
~2 min
"Eventually consistent" gets heard as "a small delay". It means a user can save something and then not see it. Decide what that does to your product before choosing it — and during a partition you keep answering or keep being correct, not both.
Agreement, and why timestamps are not order
~2 min
Two habits cause most of the damage: electing a leader with heartbeats, and ordering events by timestamp. Neither works, because a slow network looks exactly like a dead peer, and two machines' clocks disagree by more than the events you are ordering.
How services talk: call it, or queue it
~2 min
Two beliefs to drop. Splitting the code makes services independent — not while both halves write the same tables. And a queue removes load — it defers it; if the consumer is slower than the producer, the queue is simply where the failure now accumulates.
Retries are how a blip becomes an outage
~2 min
Retrying a failed call without backoff and jitter converts a brief blip into a self-inflicted outage: retries are load, and load makes the dependency slower. The follow-on mistake is trying to recover by restarting servers, when the only cure is taking load away.
Measure what a user feels, not what a server reports
~2 min
Average latency is the reassuring number that hides the problem: a service can average 50 milliseconds while 5% of requests take twenty times that. The second mistake is treating 100% as the goal rather than a budget you are meant to spend.
A procedure you have never run does not work
~2 min
A canary compared against yesterday measures the time of day, not your change. And "we have replication, so we have backups" is the expensive misconception — replication copies your accidental deletion to every replica, usually before anyone notices.
Written by Keentune. We are not affiliated with or endorsed by the organizations whose documentation informs this guide, and any linked sources belong to their respective owners.
All exam, test, and product names and trademarks are the property of their respective owners and are used here for identification and reference only. Keentune is independent study practice — not affiliated with, authorized, or endorsed by any of these organizations.