Sharding means splitting one logical table across multiple database nodes, each holding a disjoint subset of rows. It's the last lever: you shard when one node — its CPU, its I/O, its connection count — is saturated and everything cheaper has failed. The interviewer wants to know you understand sharding as a tax on application code, not a scale-up trick.
The only design decision that matters is the shard key: the column the data is partitioned on. Hash partitioning (shard = hash(key) mod N) spreads writes evenly but scatters related rows; range partitioning keeps regions together but creates hot shards. The key must match how you query: every query that filters on the shard key routes to exactly one shard — a scatter query that doesn't touch the key has to fan out to every node and merge results, and that's where the pain lives.
What breaks, concretely. Joins: a join between two tables works only if both are sharded on the same key with co-located rows — otherwise it becomes a scatter-gather across N servers with the merge in your application. Transactions: a transaction touching rows on two shards needs distributed coordination (2PC, which is slow and fragile, or sagas, which aren't transactions) — so the discipline is "one transaction, one shard," which reshapes your schema: orders and their items shard together on customer ID so checkout touches one node. Uniqueness: a unique constraint is now per-shard — two shards can each happily insert the same email — so global uniqueness needs a coordinator or keys designed to embed the shard. IDs: auto-increment counters collide across shards; the fix is snowflake-style IDs (timestamp + machine ID + sequence), which also embed the shard for routing. Secondary indexes: an index on a non-shard-key column doesn't exist globally — queries on it scan every shard, which is why sharded systems add denormalized lookup tables. Resharding: changing N later means rebalancing live traffic — virtual buckets (e.g. 2^16 logical slots mapped to physical shards, as Vitess and Cassandra use) let you move slots without rewriting routing logic.
The operational half: every shard needs its own connection pool, its own replica set, its own failover — your operations surface multiplies by N. And you lose global primitives: ORDER BY over the whole table, global aggregates, and LIMIT semantics all require app-side merge logic.
The answer that closes well is the reframing: the only sharding that doesn't hurt is the one you never need. Design for it — pick the key early, keep transactions single-shard — then defer it until the single node is genuinely the bottleneck. Sharding isn't how you scale; it's what you do when scaling runs out of cheaper options.