Buffer cache prewarm
Warm pgresp tables into memory after restart with pg_prewarm and autoprewarm.
After a Postgres restart, its in-memory cache of table data starts empty.
Redis-style GET traffic then pays a cold-start cost until recently used keys
are read back from disk. PostRESP uses PostgreSQL’s built-in pg_prewarm
extension to load pgresp.* tables (and their indexes) into that cache
sooner.
Prewarm does not change steady-state latency once data is already cached. It shortens the post-restart ramp-up. It is complementary to the SQL / RESP path — not a substitute for it.
pg_prewarm ships with a normal PostgreSQL install (including the official
Postgres Docker images). You enable it with CREATE EXTENSION and, for
automatic restore across restarts, by listing it in
shared_preload_libraries.
Default (Docker / compose)
make postgres-up and the compose stack enable prewarm by default:
pg_prewarmis listed inshared_preload_libraries(withpg_cronandpg_resp_gw_host).pg_prewarm.autoprewarmis on (PostgreSQL’s default when the library is loaded; compose also sets it explicitly).- Init creates
CREATE EXTENSION pg_prewarmalongside the PostRESP extensions.
With autoprewarm on, Postgres periodically records which table pages were in memory (default interval 300s) and reloads that set after the next restart. That restores the previous hot set without a manual warm step.
Disable autoprewarm
Autoprewarm is a Postgres server setting — not a gateway JSON or env field.
| How | Setting |
|---|---|
Compose / make postgres-up |
PG_PREWARM_AUTOPREWARM=off (maps to the setting below) |
postgresql.conf / -c |
pg_prewarm.autoprewarm = off |
PG_PREWARM_AUTOPREWARM=off make postgres-up
# Extension installs / custom Postgres
shared_preload_libraries = 'pg_cron,pg_resp_gw_host,pg_prewarm'
pg_prewarm.autoprewarm = off
Leave pg_prewarm in shared_preload_libraries if you still want the SQL
pg_prewarm() function and pgresp.prewarm(); only the background save /
reload worker follows autoprewarm. Omitting pg_prewarm from preload
turns off that automatic path (you can still CREATE EXTENSION pg_prewarm
and warm tables manually).
Manual prewarm
Force a full warm of every pgresp table and index:
SELECT pgresp.prewarm(); -- total pages loaded into Postgres memory
Or call pg_prewarm directly:
SELECT pg_prewarm('pgresp.strings');
-- All tables + indexes in schema pgresp:
SELECT pg_prewarm(c.oid)
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'pgresp'
AND c.relkind IN ('r', 'i');
Load modes (buffer is preferred):
| Mode | Effect |
|---|---|
buffer |
Loads pages into Postgres’s main shared memory cache |
read |
Loads into the OS file cache only |
prefetch |
Asks the OS to read ahead; least direct |
Use manual prewarm when autoprewarm is off, after restoring a database dump, or when you want an immediate full warm instead of waiting for the next save interval.
Extension installs
On an existing Postgres (not the compose image):
- Confirm
CREATE EXTENSION pg_prewarmworks (it should on a standard PostgreSQL install). - Append
pg_prewarmtoshared_preload_libraries(do not replace existing entries), setpg_prewarm.autoprewarm = onunless you opt out, and restart. CREATE EXTENSION pg_prewarm;in the product database, thenCREATE EXTENSION pg_resp;/pg_resp_gw_hostas usual.
See Postgres Extensions.
Operational notes
- Size Postgres shared memory (
shared_buffers) for the working set you care about. Prewarmed pages can still be evicted if other data competes for the same cache. - UNLOGGED vs LOGGED — prewarm helps after a clean restart when
tables still exist on disk. After a crash,
UNLOGGEDtables may be empty (nothing useful to warm). Preferloggedwhen crash recovery and cache restore both matter. - TTL churn — expired keys and vacuum free space over time; keep autovacuum healthy on aggressive TTL workloads.
- Replication — each Postgres node has its own memory cache. Standbys need their own prewarm/autoprewarm after promotion or restart.
- What is cached — prewarm loads table pages from disk into memory. A GET still has to look up the key and read the row; it just avoids waiting on disk for those pages.