Database Sharding in 2016: Survival Strategies for When Your Monolith Melts
Let’s be honest. Nobody wants to shard. Sharding is painful. It breaks your joins, complicates your transactions, and turns a peaceful Sunday deployment into a distributed systems nightmare. But here we are. Your SHOW PROCESSLIST is full of locked queries, your master node is swapping, and vertical scaling has hit the physical limit of what a single chassis can handle.
I’ve seen this pattern too many times. A startup builds a monolithic MySQL instance on a standard VPS. It works fine until they hit about 500GB of data. Then, backups take too long. Schema changes lock tables for hours. Suddenly, you aren't a developer anymore; you're a firefighter.
In this guide, we aren't talking about theoretical computer science. We are talking about keeping your infrastructure alive using the tools we have available right now—MySQL 5.7, MongoDB 3.2, and raw compute power.
The "Throw Money at It" Phase vs. The Sharding Cliff
Before you shard, you optimize. You check your my.cnf. You ensure innodb_buffer_pool_size is set to 70-80% of your RAM. You switch from spinning rust to SSDs. But eventually, you hit the wall.
Pro Tip: Before you architect a complex sharding solution, verify your underlying I/O. We’ve seen "database bottlenecks" that were actually just noisy neighbors on a cheap OpenVZ container. This is why we use KVM at CoolVDS. If your disk wait (iowait) is consistently above 10% on a dedicated task, no amount of sharding logic will save you. You need NVMe or enterprise SSDs, and you need isolation.
Strategy 1: Application-Level Sharding (The "Keep It Simple" Approach)
In early 2016, middleware proxies like MySQL Fabric are available, but they introduce complexity. The most robust way to shard is often directly in your application code. This gives you total control.
The logic is simple: Pick a Shard Key (usually user_id or company_id) and route traffic based on that key.
The Modulo Approach
This is the classic method. Shard ID = user_id % number_of_shards.
// PHP Example: Basic Modulo Routing
class ShardManager {
private $shards = [
0 => ['host' => '10.0.0.1', 'db' => 'app_shard_01'],
1 => ['host' => '10.0.0.2', 'db' => 'app_shard_02'],
2 => ['host' => '10.0.0.3', 'db' => 'app_shard_03'],
];
public function getConnection($userId) {
$shardId = $userId % count($this->shards);
$config = $this->shards[$shardId];
return new PDO(
"mysql:host={$config['host']};dbname={$config['db']}",
'user',
'password'
);
}
}
The Trade-off: Resharding is a nightmare. If you go from 3 to 4 servers, the modulo changes, and you have to migrate massive amounts of data. This approach is only viable if you provision way more shards than you need initially (e.g., start with 100 logical shards across 2 physical servers, and move them later).
Strategy 2: Directory-Based Sharding (Lookup Tables)
Instead of calculating the location, you store the location. You maintain a highly available "Lookup Database" that maps a user_id to a specific shard ID.
| Feature | Modulo Sharding | Directory Sharding |
|---|---|---|
| Complexity | Low | High (Requires lookup DB) |
| Data Migration | Difficult (Reshuffling) | Easy (Update lookup table) |
| Single Point of Failure | None (Stateless) | Yes (The Lookup DB) |
To make this work, your Lookup DB must be bulletproof. We recommend a Master-Slave setup with semi-synchronous replication enabled in MySQL 5.7 to ensure you never lose routing data.
The ID Generation Problem
When you split data across multiple servers, you lose the convenience of AUTO_INCREMENT. If Shard A generates ID 100 and Shard B generates ID 100, you have a collision when you try to aggregate analytics.
Solution A: UUIDs
You can generate UUIDs in the app. However, standard UUIDs (36 chars) are terrible for MySQL InnoDB performance because they are not sequential, causing massive fragmentation in the clustered index.
Solution B: Ticket Servers (The Flickr Method)
Use a centralized database devoted solely to generating IDs. It uses REPLACE INTO to atomically increment a counter.
CREATE TABLE `Tickets64` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`stub` char(1) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
UNIQUE KEY `stub` (`stub`)
) ENGINE=MyISAM;
REPLACE INTO Tickets64 (stub) VALUES ('a');
SELECT LAST_INSERT_ID();
This is fast, lightweight, and ensures global uniqueness.
Infrastructure Matters: Latency and The NIX
Sharding introduces network overhead. Your application server now talks to a Lookup DB, then a Shard DB, and potentially a caching layer like Redis. If your servers are scattered across cheap hosting providers with poor peering, your latency compounds.
This is where geography strikes back. If your users are in Oslo or Bergen, hosting your shards in a US data center is suicide for user experience. You need single-digit millisecond latency.
At CoolVDS, we peer directly at NIX (Norwegian Internet Exchange). When your application server in our Oslo data center talks to your database shard, it’s happening over a high-speed local network, not traversing the Atlantic. This is critical for preventing "micro-stalls" in PHP execution.
A Note on Data Sovereignty (The Elephant in the Room)
With the Safe Harbor agreement invalidated last year (Schrems I) and the new General Data Protection Regulation (GDPR) looming on the horizon for final adoption this spring, where you store data is becoming a legal minefield. Datatilsynet is watching.
Sharding allows you to geo-partition data. You can keep Norwegian user data on shards physically located in Norway (like on CoolVDS hardware) while serving German users from Frankfurt. This architectural flexibility might just save your legal team a massive headache in 2018.
Configuration Checklist for MySQL 5.7 Shards
If you are deploying MySQL 5.7 on CoolVDS today, these are the settings you shouldn't ignore in your my.cnf:
[mysqld]
# Each shard MUST have a unique ID
server-id = 101
# GTID is much more stable in 5.7, use it for easier failover
gtid_mode = ON
enforce_gtid_consistency = ON
# Safety for durability
innodb_flush_log_at_trx_commit = 1
sync_binlog = 1
# Connection handling
max_connections = 1000
Conclusion
Sharding is a commitment. It requires disciplined code and robust infrastructure. Don't try to run a distributed database on oversold shared hosting. You need dedicated resources, predictable I/O, and the ability to scale vertically before you scale horizontally.
If you are planning to split your database, start with a solid foundation. Deploy a high-performance KVM instance on CoolVDS today. We offer the low latency and data sovereignty your Norwegian clients demand, with the raw NVMe performance your database craves.