databases-storage

PostgreSQL documentation drops 13-year SSD tuning advice for random_page_cost

Key Takeaway

PostgreSQL's documentation no longer recommends lowering random_page_cost for SSDs, after new measurements showed the 4.0 default may actually be too low rather than too high.

Summary

Bruce Momjian removed the long-standing documentation explanation for PostgreSQL's random_page_cost=4.0 default in October 2025, including the 2020 recommendation that SSD users set it to 1.1. New benchmark work by Tomas Vondra on PostgreSQL 19 beta 4 measured actual random-to-sequential read ratios of 20-63 on various storage configurations, suggesting the default underestimates real costs. The parameter's name continues to mislead: it represents random page cost multiplied by cache miss probability, not raw random read speed. Andres Freund disputed the methodology, finding ratios near 4:1 in his own tests using pg_prewarm.

What random_page_cost actually measures

  • Not a hardware benchmark: random_page_cost is random read cost multiplied by cache miss probability, not raw disk performance. The "4.0" name has misled users since PostgreSQL 7.0 (2000).
  • Planner mechanics: The parameter charges per index page based on correlation with heap order—perfectly correlated indexes pay 1× random_page_cost then sequential rates; uncorrelated indexes pay full rate for all heap pages. This creates 80× cost differences for similar row counts.
  • Tomas Vondra's measurements (PostgreSQL 19 beta 4): ~20 on single NVMe, ~21 on 4-drive SATA SSD stripe, ~49 on 4-drive NVMe stripe, ~63 on Azure standard HDD with direct I/O.
  • Andres Freund's objection: Vondra's method charges index scan's higher per-row CPU to page cost; Freund's pg_prewarm comparison found ~4:1 ratio.
  • Confirmed behavior through 19 beta 4: Plain index scans still issue synchronous heap page requests with no prefetching, while sequential scans and bitmap heap scans benefit from PostgreSQL 18 AIO streaming.
  • Tablespace overrides (since 9.0) only affect table/index access, not temp file operations for sorts/hashes.

Why it matters

The documentation change removes a widely-copied tuning "rule" that may have caused suboptimal query plans on SSD-backed systems. Administrators now need to measure their own cache hit rates via pg_stat_io or EXPLAIN (ANALYZE, BUFFERS) rather than applying blanket 1.1 values.

Original reference: postgr.es →