Parameter · Resource Usage / Memory
subtransaction_buffers
Sets the size of the dedicated buffer pool used for the subtransaction cache. 0 means use a fraction of "shared_buffers".
- Default:
0 - Type: integer (8kB)
- Range: 0 … 1GB
- Applies: Restart required
In plain words
Savepoints and PL/pgSQL EXCEPTION blocks create subtransactions. PostgreSQL records each one's parent in pg_subtrans. When a session has more than 64 open subtransactions, other sessions have to look parents up there a lot; this cache keeps those pages in memory.
For DBAs and operators
New in PostgreSQL 17. Default 0 = shared_buffers/512, between 16 and 1024 buffers; multiple of 16. The classic problem it softens is subtransaction overflow: each backend can advertise only 64 subxact IDs in shared memory; beyond that its entry is marked overflowed, snapshots become overflowed, and visibility checks by every session may need pg_subtrans lookups. Symptoms: many sessions waiting on SubtransSLRU / SubtransBuffer, often on hot standbys, CPU spikes, throughput collapse while one long transaction uses many savepoints.
-- PG16+: subtransactions per backend
SELECT pg_stat_get_backend_pid(b) AS pid,
s.subxact_count, s.subxact_overflowed
FROM pg_stat_get_backend_idset() AS b,
pg_stat_get_backend_subxact(b) AS s;The simpler check is pg_stat_slru (name = 'subtransaction', rising blks_read) plus wait events. Bigger buffers help, but the real fix is fewer savepoints per transaction (ORMs that wrap every statement in a savepoint, exception blocks in loops).
How to change it
Change in postgresql.conf or ALTER SYSTEM, then restart the server.
See it in context
SLRU caches Snapshots and visibility Hot standby and recovery conflicts Commit log, hint bits and subtransactions