“We should switch to a different database” is one of the most common overreactions we see when a MySQL-backed application starts struggling under real growth. Nine times out of ten, the actual answer isn’t a database migration - it’s that MySQL, properly indexed, sharded, and read-replicated, handles far more scale than the app’s current queries suggest, and the real problem is unoptimized queries or a single unscaled instance, not the database engine itself.
Where the pain actually shows up first
Almost universally, the first bottleneck teams hit isn’t write throughput - it’s a single database instance trying to serve both writes and an increasing volume of reads (dashboards, reports, application queries) simultaneously, with no separation between the two. That contention, not MySQL’s fundamental capability, is usually the first real scaling wall.
Read replicas: the first, and often sufficient, fix
Setting up read replicas - copies of the primary database that stay in near-real-time sync and serve read-only queries - lets you route read-heavy traffic (reports, dashboards, most application reads) away from the primary instance, which stays focused on writes. For a large share of applications we’ve scaled, this single change - no sharding required - resolves the immediate performance crisis, because most applications are read-heavy, often by a wide margin, and separating that read load from write contention buys substantial headroom without the complexity sharding introduces.
When you actually need sharding, and what it requires
Sharding - splitting data across multiple database instances based on some key (customer ID, geographic region, tenant ID) - becomes necessary when write volume itself exceeds what a single instance can handle, or when data volume grows large enough that even a well-indexed single instance struggles regardless of read/write split. This is a genuinely bigger architectural commitment than read replicas:
- Choosing the right shard key is the decision that determines whether sharding actually helps - a poorly chosen key concentrates load unevenly across shards (a “hot shard” problem) or makes common queries need to hit every shard anyway, defeating the purpose.
- Cross-shard queries and transactions become genuinely harder - joins across data that lives on different shards, or transactions that need to touch multiple shards atomically, require real application-level handling that doesn’t exist in a single-instance setup.
- Operational complexity multiplies - schema migrations, backups, and monitoring all need to account for multiple shards instead of one instance, which is real ongoing engineering overhead, not a one-time setup cost.
What we actually check before recommending either
Before recommending read replicas or sharding, we look at whether the actual queries hitting the database are well-indexed and reasonably efficient in the first place - a shockingly large share of “MySQL can’t scale” situations we’ve diagnosed turn out to be a handful of genuinely slow, unindexed queries responsible for most of the load, fixable in days rather than requiring weeks of infrastructure work. Scaling infrastructure around inefficient queries just makes the inefficiency more expensive to run, not less present.
The order we actually recommend
- Fix slow queries and missing indexes first - cheapest, fastest, and often solves the immediate problem entirely.
- Add read replicas for read-heavy contention - moderate effort, high impact, no application logic changes required beyond routing reads appropriately.
- Shard only once write volume or data size genuinely exceeds what a well-tuned single instance with replicas can handle - this is the option with the highest ongoing complexity cost, so it should be the last resort, not the first instinct.
We help growing companies work through exactly this sequence as part of our backend and database architecture work - most of the time, the fix is cheaper and faster than the migration a team initially assumed they needed. Get in touch if your MySQL database is starting to strain and you’re not sure whether the fix is a query, an index, or a genuine architecture change.