~12 min
A single database node has a ceiling: one machine's disks, memory and CPU can only absorb so many writes a second, no matter how well-tuned the queries are. Sharding (or horizontal partitioning) gets past that ceiling by splitting one logical table across many physical machines, each holding a slice of the rows, so write throughput scales roughly with the number of shards rather than staying capped at one node's limit. The cost is real: a query that used to hit one machine may now need to fan out to several, and an operation that spans two shards — a join, a multi-row transaction — is no longer a single local operation. Sharding is therefore something you reach for once estimation shows write volume that one node genuinely can't hold, not a default.
The shard key is the whole design: it decides which physical shard a row lands on, and a bad choice creates a hot shard that absorbs a disproportionate share of traffic while the others sit idle. AWS's own guidance on DynamoDB partition keys makes the failure mode concrete: a status code with only a few possible values is a bad partition key because most items pile onto a handful of values, while a well-distributed key like a user ID, where the application has many users, spreads load evenly. The same logic applies to any sharded relational setup. A hash of a well-distributed key (user ID, not signup date rounded to the day) spreads writes evenly but makes range queries across shards expensive; a range-based key (sort by date) keeps ranges cheap but concentrates today's writes on whichever shard holds today's range.
Every write for "today" lands on the same shard, creating a hot shard, since the key has very few active values at once.