Architecture
How storage, the in-process RESP gateway, and the shared protocol core fit together.
PostRESP makes PostgreSQL speak Redis RESP. The primary product shape is extensions inside Postgres — clients hit RESP on the same host as the database. No separate gateway process is required for the common case.
The same protocol core also ships as a standalone redis_gateway service for
external deployment or when you want to split processes.
Pieces
| Piece | Role |
|---|---|
pg_resp |
SQL storage (schema pgresp) |
pg_resp_gw_host |
Background worker hosting RESP inside Postgres |
Standalone redis_gateway |
Same core, run outside the postmaster |
North star: install the extension(s), preload the host, talk Redis — storage and protocol co-located in PostgreSQL.
Layers
| Layer | Responsibility |
|---|---|
| Storage / semantics | Key/value rules, persistence, and the pgresp.* SQL API |
| Dispatch + encoding | Parse RESP args, call storage/session helpers, encode replies |
| Hosting | Listen for clients and manage sessions — no command business logic |
Redis semantics live in SQL (pgresp.*). The gateway binds parameters and
encodes protocol only. Both the in-process host and the standalone binary share
that core, so behavior stays consistent across deployment shapes.
Extensions
| Extension | Purpose |
|---|---|
pg_resp |
Storage API — schema pgresp |
pg_resp_gw_host |
In-process RESP background worker |
pg_cron |
Schedules active TTL deletion (pg_resp_ttl_task) |
pg_prewarm |
Reloads recently used pgresp.* data into memory after restart |
Keys live in schema pgresp. Product extension names stay pg_resp /
pg_resp_gw_host. Docker / compose also enable pg_cron (TTL sweeper)
and pg_prewarm (autoprewarm on by default). Preload order:
shared_preload_libraries = 'pg_cron,pg_resp_gw_host,pg_prewarm'
See Commands › TTL and Buffer cache prewarm.
Deployment shapes
# In-process (default / recommended)
Client → RESP :6379 → pg_resp_gw_host (BGWorker) → pgresp.* → Postgres tables
# Standalone gateway
Client → RESP :6379 → redis_gateway process → same pgresp.* → Postgres
Use the in-process path unless you have a reason to split the gateway out
(process isolation, running against an existing Postgres that already has
pg_resp installed, etc.). The published Docker image is a single-instance
stack (default unlogged); it is not an HA topology.
HA / multi-node (direction)
Longer-term, replacing Redis in k8s-style deployments means leaning on Postgres HA, not reimplementing Redis Cluster:
- Semantics stay in
pgresp.*so backups, WAL, and operator failover apply. - Use
loggedstorage —unloggedis single-instance only (UNLOGGEDheaps are not replicated). - One primary accepts RESP writes and runs
pg_cronTTL; standbys follow Postgres until promotion. - Pub/Sub is still process-local —
PUBLISHfans out only to subscribers on the same gateway process. Scaling out to multiple RESP gateways needs a cross-process bus (e.g. PostgresLISTEN/NOTIFY); see Commands › Pub/Sub.
Details and the mode matrix: Storage modes › HA and clustering.
Design principles
- Schema name is
pgresp. - Prefer Redis semantics as
pgresp.*SQL; the gateway binds params / protocol only. - In-process and standalone share one protocol core — same commands, same replies.
- Cluster/HA is a Postgres concern; default Docker/
unloggedstays single-instance.