PgPaw has two loops:
- replication keeps the local pglite database current;
- HTTP requests read from that local database.
Startup path
pgpaw serve does this in order:
- Preflights upstream Postgres.
-
Opens the local pglite replica in
--data-dir. - Starts logical replication from the configured publication and slot.
- Scans the replicated schema.
- Builds the SQL classifier, version index, query cache, CDC bridge, and live hub.
- Binds the HTTP server and logs the listening address.
The startup logs are intentionally explicit. A healthy boot
includes event=http_server_listening and
event=server_ready.
Request path
For public queries, PgPaw returns a redirect to a shared snapshot cursor.
For private queries, PgPaw verifies the bearer token, extracts a Postgres role, runs the query under that role, and returns inline JSON.
Versioning
PgPaw combines a SQL fingerprint with a replication-derived version:
cache key = {query_fingerprint}:{version}
The fingerprint is an implementation detail. Clients should treat
it as an opaque string from the Location header.
The version comes from VersionIndex, which consumes
committed replication transactions. For broad queries, the version
is table-level. For single-table queries with an equality filter
on a primary key, PgPaw can use a narrower row watermark. Tables
using REPLICA IDENTITY FULL can anchor on other
equality filtered columns.
Cache behavior
Public snapshots are stored in an in-process cache. The cache is
bounded by --cache-size-bytes.
When relevant upstream data changes, PgPaw issues a new snapshot
cursor for the same SQL. Old cursors keep working while the
snapshot remains in the cache. If a snapshot is evicted,
GET /q/{hash}/{version} returns 404.
Live behavior
LiveHub keeps the last result for every live
subscription. When CDC reports a commit touching a subscribed
table, PgPaw:
- re-runs the SQL against the local replica;
- maps rows by primary key when possible, otherwise by row hash;
- diffs old rows against new rows;
-
sends
insert,update,delete, thenup-to-dateevents.
If the internal broadcast channel falls behind, PgPaw sends
{"op":"reset"} and clears subscriptions. Clients
should reconnect and request a fresh snapshot.
Privacy behavior
PgPaw reads the replicated catalog to classify touched tables:
- RLS enabled means private.
- Missing
PUBLIC SELECTmeans private. - Any private table makes the whole query private.
This keeps Postgres as the source of truth for access control.
