Skip to content

Figma: sharding Postgres without leaving it

Organization Figma
Period 2020 to 2023
Problem Database load grew almost 100x; single tables reached terabytes and billions of rows
Architecture Vertical partitioning, then horizontal sharding of Postgres (opens in a new tab) through a custom proxy
Patterns Sharding, incremental and reversible migration

In 2020 Figma ran a single Postgres database on the largest instance AWS (opens in a new tab) offered. Its database load then grew almost 100x. The team first added caching and read replicas and split groups of related tables into their own databases (vertical partitioning); by the end of 2022 there were about a dozen.

That wasn’t enough. Some single tables had grown to several terabytes and billions of rows, causing problems during Postgres maintenance (vacuums), and the busiest tables were approaching the I/O limits of Amazon RDS (opens in a new tab). Vertical partitioning can’t split one table, so they needed horizontal sharding.

  • Colos. Groups of related tables share a sharding key and the same physical layout, so joins and transactions still work within one key.
  • Logical sharding first. Queries are routed as if the data were already sharded while it still lives in one database, using Postgres views. A feature flag controls the rollout and a configuration change rolls it back.
  • Physical sharding second. Once logical sharding is proven, the data is copied onto separate databases and traffic is switched.
  • DBProxy. A new service written in Go sits between the application and the connection pooler. It parses each query, works out which shard it needs, and can send a query to all shards and combine the results.
flowchart LR
    app[Application] --> proxy[DBProxy: parse, plan, route]
    proxy --> pool[Connection pooler]
    pool --> s1[(Shard 1)]
    pool --> s2[(Shard 2)]
    pool --> s3[(Shard ...)]

Figma shipped its first horizontally sharded table in September 2023, about nine months into the project. The switch caused about ten seconds of partial availability on the primary databases and none on replicas, and the team saw no regressions in latency or availability afterwards.

  • They own a query proxy, which must understand enough SQL to route correctly and is now critical infrastructure.
  • Queries must include the sharding key to stay efficient; queries across all shards are possible but costly.
  • Joins and transactions are limited to tables in the same colo and the same sharding key.
  • Exhaust cheaper steps first: caching, read replicas, then splitting tables into separate databases.
  • Prefer migrations you can roll back with a configuration change. Logical sharding before physical sharding gives exactly that.
  • Weigh team expertise and runway, not just features, when choosing between a new database and extending the one you know.

Written and edited by Abhinav Taduka, enterprise software architect.