Overview

The partition key decides which partition or shard stores a row. Choose it from the filter that almost every query already uses, usually time or tenant, because a query without it scans every partition. Changing it later means rewriting the table.

Rules

  • PostgreSQL declares it with PARTITION BY RANGE (created_at), LIST (region), or HASH (tenant_id). Queries with equality or range predicates on the key get partition pruning, so only matching partitions are read.
  • A primary key or unique constraint on a partitioned table must include every partition key column, and the key cannot contain expressions in that case.
  • Avoid low-cardinality keys (booleans, three-value statuses): partitions end up uneven and pruning gains nothing.
  • Time keys let you detach or drop old partitions instead of a huge DELETE. The planner handles up to a few thousand partitions if queries prune most of them; more partitions cost planning time and memory.
  • For sharding across nodes the partition key is the shard key; hash it for even spread.
CREATE TABLE events (id bigint, created_at timestamptz NOT NULL, payload jsonb)
  PARTITION BY RANGE (created_at);
CREATE TABLE events_2026_04 PARTITION OF events
  FOR VALUES FROM ('2026-04-01') TO ('2026-05-01');