Configuration
SetupConfiguration.json, environment overrides, GUCs, and naming rules.
Two layers, one vocabulary:
| Layer | Case | Example |
|---|---|---|
SetupConfiguration.json |
PascalCase | GatewayListenPort |
| Environment overrides | SCREAMING_SNAKE_CASE | PG_RESP_PORT |
Environment variables override the JSON file when set. Typical Docker installs
ship a config that listens on 0.0.0.0:6379 and connects to Postgres as
redis / redis / pg_resp.
Prefix rules
- Product / RESP endpoint —
PG_RESP_
Settings that belong to the Redis-facing gateway (listen port, storage mode). - PostgreSQL backend —
POSTGRESQL_
Host, port, and database the gateway uses to reach Postgres. - Auth — unprefixed
USERNAME/PASSWORD
Postgres role the gateway uses for SQL. RedisAUTHverifies against the same roles. Wire auth is required by default; setREQUIRE_CLIENT_AUTH=falseto allow unauthenticated clients. See Authentication. - Behavior flags — plain verbs, no product prefix when they are not
product-specific:
REQUIRE_POSTGRES,REQUIRE_CLIENT_AUTH,ALLOW_EXTERNAL_CONNECTIONS,ASYNC_RUNTIME_WORKER_THREADS. - Do not invent aliases. One name per setting.
Environment ↔ JSON map
| Environment | JSON field | Default |
|---|---|---|
PG_RESP_PORT |
GatewayListenPort |
6379 |
PG_RESP_STORAGE_MODE |
StorageMode (unlogged | logged) |
unlogged |
POSTGRESQL_HOST |
PostgresHostName |
127.0.0.1 |
POSTGRESQL_PORT |
PostgresPort |
5432 |
POSTGRESQL_DATABASE |
PostgresDatabase |
pg_resp |
USERNAME |
PostgresSystemUser |
redis |
PASSWORD |
PostgresPassword |
redis |
REQUIRE_POSTGRES |
RequirePostgres |
unset / false |
REQUIRE_CLIENT_AUTH |
RequireClientAuth |
true |
ALLOW_EXTERNAL_CONNECTIONS |
inverts UseLocalHost |
unset |
ASYNC_RUNTIME_WORKER_THREADS |
AsyncRuntimeWorkerThreads |
2 |
Booleans accept 1 / true / yes (and 0 / false / no).
# Example: listen on 6380 and point at a non-default Postgres port
PG_RESP_PORT=6380 POSTGRESQL_PORT=5433
Example config file
{
"GatewayListenPort": 6379,
"UseLocalHost": false,
"PostgresHostName": "127.0.0.1",
"PostgresPort": 5432,
"PostgresDatabase": "pg_resp",
"PostgresSystemUser": "redis",
"PostgresPassword": "redis",
"RequirePostgres": true,
"RequireClientAuth": true,
"StorageMode": "unlogged",
"AsyncRuntimeWorkerThreads": 2
}
Point Postgres at the file with:
shared_preload_libraries = 'pg_cron,pg_resp_gw_host,pg_prewarm'
pg_prewarm.autoprewarm = on
redis_gateway.database = 'pg_resp'
redis_gateway.setup_configuration_file = '/etc/pg_resp/SetupConfiguration.json'
GUCs
In-process host GUCs (require shared_preload_libraries including
pg_resp_gw_host):
redis_gateway.databaseredis_gateway.setup_configuration_filepg_resp.ttl_delete_batch_size(default1000) — SQL TTL sweeper keys/roundpg_resp.ttl_delete_max_rounds(default10) — rounds perdelete_expired_keyscall
Tune the TTL pair with ALTER SYSTEM / postgresql.conf + pg_reload_conf(), or
SET before a manual CALL pgresp.delete_expired_keys().
pg_cron
pg_cron is a Postgres extension that
runs scheduled SQL. PostRESP uses it for active TTL expiry: job
pg_resp_ttl_task calls pgresp.delete_expired_keys() once a minute.
Docker / compose preload pg_cron and set cron.database_name to the product
database. Init creates the extension; CREATE EXTENSION pg_resp schedules the
job when pg_cron is present.
| Setting | Role |
|---|---|
shared_preload_libraries includes pg_cron |
Required for the scheduler |
cron.database_name |
Database where the job runs (must match where you create extensions) |
Lazy expiry on read/write still works without pg_cron; without it, expired
keys are only removed when touched. Batch size for the sweeper is controlled by
the pg_resp.ttl_delete_* settings above — see
Commands › TTL.
pg_prewarm
pg_prewarm ships with a standard PostgreSQL install. Docker / compose
preload it and leave autoprewarm on by default (see
Buffer cache prewarm):
| Setting | Default | Meaning |
|---|---|---|
pg_prewarm.autoprewarm |
on |
Remember and reload recently cached table pages across restarts |
pg_prewarm.autoprewarm_interval |
300s |
How often to save that page list |
Compose convenience (maps to the setting above; not a gateway JSON field):
| Environment | Effect | Default |
|---|---|---|
PG_PREWARM_AUTOPREWARM |
on | off for pg_prewarm.autoprewarm |
on |
Postgres server settings are a separate surface from gateway env/JSON — prefer
the names in postgresql.conf. The compose variable above exists only so
make postgres-up can toggle autoprewarm without editing the command array.
Memory and buffer cache
Keys live in Postgres heaps and indexes (pgresp.*), not in a dedicated
in-process Redis dict. The full keyspace does not need to fit in RAM —
only the hot working set should, via shared_buffers and the OS page cache.
Cold keys stay on disk until read.
| Knob | Where | Guidance |
|---|---|---|
shared_buffers |
postgresql.conf |
Size for the hot set you want resident, not the whole dataset. Default Docker images leave Postgres defaults; raise this when steady-state GET latency matters and the working set is larger than the default. |
| OS page cache | host / VM RAM | Postgres relies on the OS to cache table pages beyond shared_buffers. Leave headroom so the kernel can hold warm pgresp.* pages. |
pg_prewarm.autoprewarm |
see above | Reloads the previous hot set after restart so you are not starting from an empty cache. |
StorageMode |
gateway env/JSON | unlogged vs logged changes WAL and crash behavior (Storage modes); it does not change the dual-table encoding size. |
AsyncRuntimeWorkerThreads |
gateway env/JSON | Caps gateway async workers (default 2). Raise only if CPU is idle under concurrent RESP load; storage still dominates SET cost — see Benchmarks. |
Disk vs Redis RAM. Tiny string keys are stored twice in spirit (registry row in
keys + payload in strings) plus btree indexes, so on-disk bytes per key are
typically higher than Redis/used_memory for the same logical shape. That is
expected: you trade denser always-RAM encoding for SQL visibility and datasets
larger than memory. Do not compare Redis INFO memory to Postgres process
RSS — Postgres always carries shared buffers, catalogs, and backends.
Measure schema size when capacity-planning disk:
SELECT pg_size_pretty(SUM(pg_total_relation_size(c.oid))) AS pgresp_total
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE n.nspname = 'pgresp' AND c.relkind = 'r';
Container / image exceptions
These are not gateway config names; do not reuse them as new public APIs:
POSTGRES_USER/POSTGRES_PASSWORD/POSTGRES_DB— official Postgres image initPGPORT— libpq default port inside the container (set fromPOSTGRESQL_PORT)PG_PREWARM_AUTOPREWARM— compose →pg_prewarm.autoprewarmonly (see above)