How Figma, Notion and Slack handled sharding
Horizontal sharding is the move every team hopes to put off. You take one database, split its rows across many, and suddenly every query, migration and on-call runbook has to know where the data lives.
I've been collecting first-hand scaling write-ups, and five of them are tagged horizontal sharding: Figma, Notion, Slack, Shopify and PlanetScale. Figma, Notion and Slack are the most useful to compare, because they took noticeably different routes. Shopify and PlanetScale fill in the rest of the picture.
Figma: buy time first, then shard logically
Figma's story is really two posts.
The first, The growing pains of database architecture (2023), is the "put it off" chapter. Figma moved from one Postgres instance to multiple databases by vertically partitioning table groups, using read replicas and connection pooling along the way. No sharding yet, just moving whole groups of tables to their own databases.
The second, How Figma's Databases Team Lived to Tell the Scale (2024), is the real thing: a nine-month effort to horizontally shard its Postgres stack on AWS RDS. Two ideas stand out:
- A custom query proxy. The application talks to a proxy, and the proxy works out which shard a query belongs to. That keeps routing logic out of every service.
- Logical sharding before physical splits. Figma first made the system behave as if it were sharded, then moved data onto separate physical databases afterwards.
That second point is the one I'd copy. It splits a terrifying project into two smaller ones. You prove your routing and query patterns work while all the data still sits in one place, and only then do the risky data move.
Notion: shard by workspace, then do it again
Notion's Herding elephants: Lessons learned from sharding Postgres at Notion (2021) is a classic for a reason. Notion split its Postgres monolith into a fleet of logical shards keyed by workspace.
The workspace is a natural shard key for a product like Notion: most reads and writes stay inside one workspace, so most queries only ever touch one shard.
To move the data, Notion used double writes and backfills: write new data to both the old and new locations, copy the historical data over, then switch reads once the two match.
Then the sequel. In The Great Re-shard: adding Postgres capacity (again) with zero downtime (2023), Notion tripled its Postgres fleet by re-sharding with logical replication and careful PgBouncer cutovers, with no downtime.
The lesson here is that sharding isn't a one-time project. If you pick the right key and use logical shards, adding capacity later becomes "move shards to more machines" rather than "redesign the schema."
Slack: shard by any key, not just workspace
Slack's Scaling Datastores at Slack with Vitess (2020) is the interesting contrast. Slack ran MySQL as active-active pairs and spent several years migrating to Vitess, a sharding layer for MySQL. The post cites 2.3 million QPS.
The key reason: Slack wanted to shard data by any key, not only by workspace.
That's the opposite lesson from Notion, and both are right for their products. Notion's data mostly lives inside a workspace. Slack has data that doesn't fit that model cleanly, so a workspace-only scheme became a limit. Vitess let Slack pick the shard key per table instead of forcing one for everything.
If you're choosing a shard key today, ask: what's the biggest thing in my product that crosses tenant boundaries? If the answer is "not much," shard by tenant. If it's "a lot," plan for more than one key.
What Shopify adds: design the keyspace, then keep rebalancing
Shopify has two sharding posts on MySQL.
- Horizontally scaling the Rails backend of Shop app with Vitess (2024) covers how the Shop app adopted Vitess to shard a Rails backend, including keyspace design and the migration plan.
- Shard Balancing: Moving Shops Confidently with Zero-Downtime at Terabyte-scale (2021) covers the day-two problem: shards get uneven, so Shopify moves individual shops between shards online with its Ghostferry tool, at terabyte scale.
Together they make the same point Notion's re-shard does. Getting sharded is the start. You also need a safe, boring way to move one tenant at a time.
What PlanetScale adds: a ceiling check
One million queries per second with MySQL (2022) is a benchmark, not a production story. PlanetScale load-tested a horizontally sharded Vitess cluster up to one million QPS. It's useful as a sanity check on how far the Slack and Shopify approach can stretch, as long as you read it as a load test.
Five patterns across all five stories
- Delay it honestly. Figma vertically partitioned first. Splitting table groups apart is often enough for a while.
- Put a routing layer in the middle. Figma built a query proxy. Slack, Shopify and PlanetScale use Vitess. Either way, the app shouldn't hard-code where data lives.
- Separate logical from physical. Figma sharded logically before splitting physically, and Notion's logical shards made its re-shard possible.
- Choose the key from your product, not the database. Workspace worked for Notion. Slack needed more flexibility.
- Budget for moving data forever. Double writes and backfills (Notion), logical replication (Notion again), Ghostferry (Shopify). Every team ended up needing a way to move data while the product stayed up.
The honest summary
None of these teams sharded early, and none of them describe it as easy. Figma's took nine months. Slack's took years. What they share is that they made the data move a separate, testable step, and they planned for doing it again.
All five horizontal sharding stories, with stack and scale details, are on one page: Horizontal sharding: real scaling case studies. There's a broader sharding page too, with Discord's guild-sharded Elasticsearch search, Meta's ZippyDB, Stripe's DocDB and Datadog's Husky.
Have you sharded by tenant and regretted it, or gone multi-key and wished you hadn't? I'd love to hear about it in the comments.
Comments
Join the discussionNo comments yet. Be the first to comment.