The first answer to a slow database is almost always a bigger one. Vertical scaling — more CPU, more memory, faster disks — is fast to do and buys real headroom. But it has a ceiling and a cost curve that bends the wrong way, and leaning on it too long hides the work that actually makes a system scale.
Exhaust the cheap wins first
Most databases under load are not short on hardware — they are short on discipline. Before sharding anything, the highest-leverage work is usually unglamorous:
- Query optimization. The slow query log is the most honest document in your system. Missing indexes, N+1 patterns, and full-table scans on hot paths routinely cost more than any hardware tier.
- Rate limiting.Protecting the database from stampedes — abusive clients, retry storms, runaway jobs — keeps a healthy system healthy. It's cheaper to shed load at the edge than to absorb it at the core.
- Caching.A read that never reaches the database is the fastest read there is. The hard part isn't the cache — it's invalidation, so design for it deliberately.
- Read replicas. Most workloads are read-heavy. Offloading reads to replicas relieves the primary, with the tradeoff of replication lag you have to design around.
When sharding earns its complexity
Eventually a single primary genuinely can't hold the write volume or the data size. Sharding — partitioning the database so data is distributed across multiple servers — is the answer, and it is also a real architectural commitment. Each shard owns a slice of the data, keyed by something stable: a tenant ID, a geography, a hash of the primary key.
The benefits are linear write scaling and smaller, faster per-shard working sets. The costs are equally real: cross-shard queries and joins get hard, transactions across shards get harder, and choosing a shard key you'll regret is one of the more expensive mistakes in this space. Rebalancing a poorly chosen key under load is not a place you want to be.
The order that works
Treat scaling as a sequence, not a jump: optimize queries, add caching and rate limiting, offload reads to replicas, and only then partition writes. Each step is cheaper and more reversible than the next, and most systems never need the last one. The teams that get this wrong usually reach for sharding to avoid doing the query work — and inherit the complexity of both.