Monthly Summary: Problems with toast.* reloptions (May 2026)
Overview
This thread reached a critical juncture in May 2026, with Nathan Bossart's investigation revealing that toast.* reloptions — which allow independent tuning of VACUUM/autovacuum behavior for TOAST side-tables — are fundamentally broken across multiple code paths. The documented inheritance contract ("if a table parameter is set and the equivalent toast. parameter is not, the TOAST table will use the table's parameter value") is violated in essentially every interesting scenario. The discussion converged on a radical but pragmatic solution: removing toast.* reloptions entirely.
Defects Identified
Defect 1: vacuum_rel() ignores parent reloptions when recursing into TOAST
When processing VACUUM foo, the recursion into foo's TOAST table only reads the TOAST relation's own reloptions — the parent's reloptions are out of scope. A prior VacuumParams-scribbling bug had accidentally masked this by overriding parameters in-place before recursion.
Defect 2: Autovacuum treats TOAST options as all-or-nothing
The main table's reloptions are consulted for TOAST only when the TOAST table has no reloptions whatsoever. Setting even one unrelated toast.* option causes all other inheritable parameters to silently revert to global defaults, because TOAST reloptions are parsed as a monolithic StdRdOptions struct with no per-field "is this set?" tracking (on back branches).
Defect 3: Some parameters left uninitialized
Parameters like vacuum_truncate are never populated by autovacuum — it relies on vacuum_rel() to fill them from reloptions. But since vacuum_rel() doesn't consult parent reloptions (Defect 1), TOAST tables silently use global defaults.
Design Alternatives Evaluated
| Option | Approach | Outcome |
|---|---|---|
| A | Resolve at VACUUM time with helper functions | Preserves storage model but requires touching every TOAST reloption consumer; unfixable on back branches without isset_offset |
| B | Materialize inheritance at DDL time | Fatal flaw: RESET becomes ambiguous — no provenance tracking to distinguish inherited vs. explicitly-set values |
| C | Resolve only in vacuum_rel() |
Localized and back-patchable but doesn't address autovacuum threshold computation (Defect 2) |
| D | Remove toast.* reloptions entirely |
Preferred direction — Nathan wrote a removal patch; eliminates complexity; justified by apparent zero real-world usage |
Patch Progress
Nathan posted v4 of the removal patch during May, fixing a bug in the pg_upgrade precheck query introduced in v3. The precheck detects pre-upgrade clusters that have toast.* reloptions set (necessary because removing the options means old clusters carrying them would fail to restore). No reviewer feedback was received on the removal patch during this month.
Back-Patching Decision
Consensus settled on HEAD-only fixes. Michael Paquier argued conservatively that the bug has existed for years without complaints. Nathan initially wanted back-patches but conceded after confronting the isset_offset availability gap on v13–v17. Shayon Mukherjee pushed back from a user perspective (documentation promises inheritance), but the practical difficulties dominated.
Testing
No clean testing strategy emerged. Michael suggested DEBUG1 log scraping with aggressive autovacuum spawn rates; Nathan dismissed this as flaky-test-prone. The lack of a testable interface is itself a signal about the area's architectural awkwardness.
Current Status
The thread is in a holding pattern awaiting community feedback on the removal proposal (Option D). Nathan has solicited objections but received none of substance. A newcomer (solai.cdac@gmail.com) confirmed the bugs are reproducible on HEAD but added no new technical information.