advanced 2 min answer

A workspace product stores every document as a tree of small "block" rows in one enormous table. Growth makes the table unmanageable. Design the sharding strategy - and identify the choice that is effectively irreversible.

shardingshard-keyworkspacesnotiondesign
Show the full answer Hide the answer

The irreversible choice

The shard key. Everything else — shard count, routing, rebalancing, tooling — can be changed later with effort. The shard key determines which queries are possible without a scatter-gather, and changing it means rewriting the entire dataset while the product is live.

Choosing it

The candidates for a block-structured workspace product:

By block id. Perfectly even distribution, and useless. The dominant query is "load this page", which means fetching a tree of blocks — under this key, every page load is a scatter-gather across every shard. Even distribution is the least important property of a shard key.

By page or document id. Keeps a document's blocks together, so page load is single-shard. But documents vary enormously in size, blocks move between pages, and the workspace-level queries — search, permissions, export, trash — still fan out.

By workspace id — the right answer. It matches the natural isolation boundary of the product:

  • Every meaningful query is workspace-scoped. Page loads, search, permission checks, exports, activity feeds all filter by workspace already.
  • Permissions are workspace-rooted, so authorisation does not cross shards.
  • It gives per-tenant operations for free: export, delete, restore, and migrating one customer to dedicated infrastructure.
  • It bounds blast radius — a shard problem affects a set of workspaces, not a random slice of every customer.

The trade is uneven distribution: workspaces range from one person to tens of thousands. That is manageable with a routing table rather than hash-based placement.

The rest of the design

  • A lookup-based router, mapping workspace → shard in a small, cached, highly-available table. Unlike modular hashing, it allows moving a single large workspace without touching anything else — the property that makes uneven distribution survivable.
  • More logical shards than physical databases. Start with, say, hundreds of logical shards mapped onto a handful of machines; growth becomes remapping rather than resharding.
  • Double-write migration. Write to old and new, backfill history, verify by comparison, cut reads over per-workspace, then stop the old write. Per-workspace cutover means the blast radius of a mistake is one customer.
  • A verification phase that is not optional. Compare row counts and checksums per workspace before cutting reads over. Most migration disasters are discovered after the old data is gone.

What gets harder afterwards

  • Cross-workspace features — global search, platform analytics, admin tooling — need a separate aggregated store fed asynchronously.
  • Schema migrations run N times with partial-failure states, so migration tooling becomes infrastructure rather than a script.
  • Transactions do not span shards. Anything crossing workspaces needs a saga or must be redesigned not to cross.
  • Very large single workspaces eventually exceed one shard, requiring a second-level split — which is why the routing table matters more than the hash function.

The principle

Pick the shard key that matches the access pattern and the isolation boundary, not the one with the best distribution. Uneven distribution is an operational problem you can solve with routing and rebalancing. A shard key that fights your queries is a problem you can only solve by starting again.