CREATE TABLE events ( id bigserial, tenant_id int NOT NULL, created_at timestamptz NOT NULL, payload jsonb, PRIMARY KEY (id, created_at)) PARTITION BY RANGE (created_at);
2. Using Range Partitioning
CREATE TABLE events_2025_01 PARTITION OF events FOR VALUES FROM ('2025-01-01') TO ('2025-02-01');
3. Using List Partitioning
CREATE TABLE orders (...) PARTITION BY LIST (region);CREATE TABLE orders_us PARTITION OF orders FOR VALUES IN ('US','CA');CREATE TABLE orders_eu PARTITION OF orders FOR VALUES IN ('DE','FR','GB');
4. Using Hash Partitioning
CREATE TABLE users (...) PARTITION BY HASH (id);CREATE TABLE users_p0 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 0);CREATE TABLE users_p1 PARTITION OF users FOR VALUES WITH (MODULUS 4, REMAINDER 1);
Strategy
Best For
RANGE
Time-series, ordinal keys
LIST
Discrete categories (region, tenant)
HASH
Even data spread, multitenancy
5. Creating Partitions
CREATE TABLE events_2025_02 PARTITION OF events FOR VALUES FROM ('2025-02-01') TO ('2025-03-01') TABLESPACE fast_ssd;
6. Setting Range Bounds
FOR VALUES FROM (MINVALUE) TO ('2024-01-01');FOR VALUES FROM ('2025-01-01') TO (MAXVALUE);
7. Setting List Values
FOR VALUES IN ('a','b','c');
8. Creating Default Partition
CREATE TABLE events_default PARTITION OF events DEFAULT;
Warning: Adding a new partition requires scanning the default partition for misplaced rows; keep it empty if possible.
9. Attaching Existing Table
ALTER TABLE events ATTACH PARTITION events_2024 FOR VALUES FROM ('2024-01-01') TO ('2025-01-01');
10. Detaching Partition
ALTER TABLE events DETACH PARTITION events_2023 CONCURRENTLY;-- PG 14+ avoids ACCESS EXCLUSIVE on the parent
11. Dropping Partition
DROP TABLE events_2022; -- after DETACH (fast purge of old data)
12. Creating Indexes on Partitioned Tables
CREATE INDEX events_tenant_created_idx ON events (tenant_id, created_at DESC);-- Cascades to all current/future partitions as partitioned index
13. Using Partition Pruning
SET enable_partition_pruning = on; -- defaultEXPLAIN SELECT * FROM events WHERE created_at >= '2025-02-15' AND created_at < '2025-02-20';-- Plan: Append scans only events_2025_02