Skip to content

PATTERN Cited by 1 source

Sharded views over unsharded DB

Use database views to represent logical shards against a still-unsharded physical database, so horizontally-sharded read/write semantics can be rolled out — and rolled back in seconds via feature flags — before the risky physical shard-split failover (concepts/logical-vs-physical-sharding).

Shape

For each logical shard i, create a view that exposes only the rows whose shard-key hash falls in that shard's range:

CREATE VIEW table_shard_i AS
  SELECT * FROM table
  WHERE hash(shard_key) >= min_range_i
    AND hash(shard_key) <  max_range_i;

Each view is accessed via its own sharded connection pooler service. Connection poolers still point at the unsharded physical instance, so the behavior is end-to-end sharded — routing, per-shard connection isolation, per-shard query execution — while the data hasn't moved.

What it buys you

  1. Serving-stack confidence without data movement. Reads and writes already behave as in the post-shard world (reliability, latency, consistency all match). Query-engine bugs, topology-lookup bugs, and connection-pool behavior get caught on the still-whole dataset where rollback is cheap.
  2. Percentage-based rollout. The router (e.g. DBProxy) feature-flag-gates whether a given table's traffic goes through the sharded views or the single unsharded table. Rollout can be any percentage; rollback is a config flip taking seconds (Source: sources/2026-04-21-figma-how-figmas-databases-team-lived-to-tell-the-scale).
  3. Physical failover de-risked. When the physical shard split eventually happens, the sharded-semantics code path has already been burned in on real traffic; the only remaining risk is the data movement itself.

The view-performance question

Views add a layer between the planner and the underlying table. Risks:

  • Small overhead from plan rewriting + predicate pushdown (typically single-digit percent).
  • Edge cases where the planner chooses a different plan under a view than against the base table.

Figma mitigated by:

  • Collecting a sanitized production query corpus.
  • Running load tests with and without views → <10% worst-case overhead; most queries minimal.
  • Running a shadow-reads framework that sent live read traffic through both the view and the direct table, comparing performance and correctness.

Result: empirical proof that views are a viable logical-shard representation before committing to physical failover.

Why not separate DBs / separate schemas for logical shards

Figma explored both. Each one would have required the physical data to already be split to make the logical-shard representation well-defined — in other words, the logical-physical decoupling that this pattern is about would be impossible. Views are the only representation that gives per-shard SQL behavior on an unchanged physical layout.

Trade-offs

  • Per-shard views multiply with shard count. Not a problem at Figma scale, but schema management (view DDL, grants, vacuum awareness) scales linearly.
  • Mutation through views requires Postgres to know which base table to hit — trivial for simple hash-range views but more care needed if the logical-shard predicate gets complex.
  • The connection-pooler count multiplies too (per-shard poolers against the same physical host). Worth collapsing into one pooler process once physical sharding is done.

Seen in

Last updated · 200 distilled / 1,178 read