RTS questionnaire · Q48 · Database scaling proof

Have you worked with database scaling strategies such as read replicas, horizontal partitioning/sharding, and caching?

The scaling ladder in the order it gets climbed: measure the constraint, then the reversible levers — cache, replicas, offload — and sharding last, because it is the one that cannot be undone.

Status: reviewed Live scaling-ladder workflow Replicas · Caching · Offload · Sharding last Jump to live proof ↓

48. Database scaling strategies

Answer as submitted

“Yes — I apply these scaling strategies together, choosing based on measured bottlenecks rather than preference.”
Technical decision: expand. The submitted line names the strategies and the method. This page is the separate, detailed version, and its organising idea is the order: measure first, then climb the reversible rungs — caching, read replicas, offload — and shard last, because it is the only one that cannot be undone. Every rung carries the number that justifies it and the cost it adds.

Expanded answer

Yes, and the discipline is in the order rather than in the list. Measure first: the p95 and p99 of the endpoints that matter, the hit ratio of every cache layer, the replication lag, and the wait types consuming the database's time — with the constraint written down before anything changes, because a scaling change with no baseline is a change nobody can attribute a result to. Read replicas take the read-heavy traffic that genuinely tolerates a stale answer: listings, reports, analytics. Every read path declares its lag tolerance, a read that follows the caller's own write is pinned to the primary for a short window, and the replication lag is a monitored number with a budget and an automatic fallback — a replica beyond its budget is not used, because serving a slightly slower answer from the primary is better than serving a stale one and letting the user find out. Caching is layered so a hit at the cheapest layer costs nothing beyond it: in-process memoisation for the hottest immutable data, Redis with cache-aside for shared state and write-through where staleness is unacceptable, HTTP caching with validators, and a CDN for anonymous traffic. Every entry declares its TTL, its invalidation contract and its stampede protection; the invalidation contract is written before the cache is added, and the hit ratio is measured per layer rather than assumed. Offload before splitting: a read model for the expensive aggregation, a materialised view refreshed on a schedule, cold data archived by partition switch, pooling and batching to remove round trips, and search or analytics moved to an engine built for it — which together frequently remove the need to shard at all. Sharding last, because it is the point of no return: every query becomes shard-local or a scatter-gather, transactions stop spanning shards, and the key choice is effectively permanent. The key is chosen from the access pattern with the cross-shard cost written down and a rebalancing plan agreed before the first shard exists; in DynamoDB or Cassandra the same distribution is expressed directly in the partition key, which makes hot-partition avoidance the same discipline under a different name. And in all cases the new topology is validated by a load test that includes the two unpleasant scenarios — an empty cache and a cache that has failed entirely — before it is released.

RungWhat it is forWhat it costs
Measurenaming the constraint: latency percentiles, hit ratio, replication lag, lock waits, pool saturationthe effort of not guessing, which is where most of the value is
Cacheabsorbing repeated reads at the cheapest possible layera second copy of the truth, an invalidation contract, and a cold-start scenario to test
Read replicasmoving lag-tolerant reads off the primarylag to monitor, read-your-writes to pin, and a fallback path to prove
Offloadremoving the work entirely: read models, materialised views, archival, batching, separate enginesa projection to keep current, and a report that is seconds slower but stops competing with checkout
Shardthe last resort when a single primary's write volume or working set is genuinely the limitcross-shard queries, no cross-shard transactions, and a key choice that is effectively permanent
Validateload-testing the new topology, including an empty and a failed cachetest time, and the discipline of recording the result against the decision

Live scaling-ladder workflow proof

The running component below changes its rung/result view through real event binding. Select a rung to see the decision, the reasoning behind it, and the number that justifies it.

LIVE PREVIEW
RUNNING
SCALING LADDER WORKFLOWRUNNING

Choose a rung of the scaling ladder

Select a rung to inspect the decision, the reasoning and the number behind it.

$ p95 and p99 latency · cache hit ratio per layer · replication lag · lock waits by type · the constraint named before the fix

A scaling change answers a measured constraint rather than a feeling: the p95 and p99 of the endpoints that matter, the hit ratio of every cache layer, the replication lag in seconds, and the wait types holding work up on the database. The bottleneck is written down before anything changes, because a scaling change without a baseline is a change nobody can attribute a result to.

scaling decisions taken with a baseline: 100%
constraint named in writing before the change: yes
"the database is slow" accepted as a diagnosis: never
signals watched: p95, p99, hit ratio, lag, lock waits, pool saturation

What the ladder buys

Rules I apply. Name the constraint before choosing the fix, because "the database is slow" is a symptom and scaling the wrong thing is expensive; prefer the reversible rung, since a cache can be removed and a replica pool can be resized but a shard key cannot be changed; declare the lag tolerance of every read path rather than saying that reads go to a replica; pin read-your-writes to the primary, because a user who cannot see their own change will not believe the change happened; never add a cache without the invalidation contract, and never let a cache be the source of truth; measure the hit ratio per layer, since an in-process cache at 20% is memory held for nothing; try the four cheaper rungs before sharding, and if sharding is genuinely required, choose the key with the access pattern in front of you and agree the rebalancing plan before the first shard exists; and validate the new topology with a load test that includes an empty cache and a failed cache, because those are the two states a deploy will produce.
Boundary for Q48: this page covers the scaling levers. The database design itself — ER modelling, key and constraint design, index design and partition schemes — is on the Q47 proof page; query-level tuning is on Q09; the caching implementation inside the application is on Q05; and the NoSQL access-pattern design is on Q10.

Source files

Select a file to inspect the proof with syntax highlighting and line numbers. The first file is the code running the component above; the others are the read routing with its lag budget and read-your-writes pinning, the cache inventory with its invalidation contracts, and the load test that validates the topology together with the record of every scaling decision.

Acceptance criteria