Scale in stages: read replicas + caching for reads first, then sharding (Vitess) for writes — and add connection pooling before anything else, because it's the cheapest 10x. Reads and writes scale differently, so don't reach for sharding on day one.
┌─▶ Cache (Redis) ── hit ──▶ return
App ─▶ Pool(PgBouncer/ProxySQL) miss ▼
│ ┌─▶ Read replica 1 ┐
├──── reads ─────────┼─▶ Read replica 2 ┼─ (async replication)
│ └─▶ Read replica N ┘
└──── writes ──▶ Primary ──▶ (later) Vitess shards ─▶ Primary A / Primary B
Step 0: connection pooling
Every MySQL connection costs memory and a thread. At 100x traffic you'll exhaust long before CPU. A pooler like or multiplexes thousands of app connections onto a few hundred DB connections. It's a config change, not a rearchitecture — do it first.
