Shard-Key Colocation
consistency
Definition
When sharding, place every row that must be read or committed together on the same shard, by two coordinated choices: shard the full set of tables that reference each other (not just the big one), and partition them all by the same key — the entity whose boundary matches the application's transaction and query patterns. Transactionality guarantees stop at a single host; colocation is how a sharded system keeps the transactions it actually needs without distributed coordination.
The failure case the pattern prevents is quiet corruption at the seams: a parent row on one shard, its children on another, and a delete that succeeds on one side while the update on the other fails. The design work is choosing the colocation entity — the workspace, the guild, the user — such that real queries stay inside it and load spreads acceptably across instances of it.
When it applies
- Horizontally sharding a relational schema where foreign-key-related tables participate in shared transactions
- Choosing a partition key for a multi-tenant product, where the tenant boundary usually is the transaction boundary
- Any sharded system where cross-shard joins or two-phase commits would otherwise become the common path
Tradeoffs
- The shards inherit the colocation entity's skew: uniform buckets by count are not uniform by weight when one tenant outweighs thousands
- The partition key becomes architectural commitment — a product pivot away from the chosen entity turns colocation into impedance
- Everything transitively related must shard together, dragging small tables into the scheme to protect the transactions of large ones
Seen in
- Figma BlogMar 14, 2024
Sharding Postgres Without Leaving Postgres
Figma's 'colos' are this pattern by another name: related tables grouped so they share the same sharding key and physical sharding layout, and cross-table joins and full transactions are supported inside a colo as long as they restrict to a single value of the sharding key. Most application code already interacted with the database that way, which is exactly what made the abstraction cheap for product developers — the pattern's payoff is the query patterns you were already running staying free.
- Notion BlogOct 6, 2021
Before the Wraparound: Sharding Postgres at Notion
Both halves of the pattern in one post: shard every table transitively reachable from block so rows that must commit together live on one host (transactionality stops at a single database), and partition all of it by workspace ID so a user's queries land on one shard. The block-deleted-but-comments-orphaned example is the pattern's failure case stated plainly.