pgtimewarp provides time travel for primary-key lookups on explicitly tracked tables, backed by WAL-derived row versions.
The Rust agent consumes WAL changes via logical replication (wal2json for MVP). It:
- Creates and maintains a logical replication slot on the source database
- Consumes WAL changes and filters for tracked tables
- Transforms changes into row versions with validity intervals
- Writes row versions to the store database
- Maintains LSN to timestamp mappings for as-of query resolution
- Updates checkpoints for safe resume
A dedicated PostgreSQL database containing:
nodes: Agent instance registrytracked_relations: Explicit allowlist of tracked tables with primary key (node_id, schema_name, table_name)row_versions: Historical row states with LSN-based validity intervalslsn_time_map: Timestamp to LSN mappingswal_checkpoints: WAL consumption statehealth_events: Diagnostic events
PostgreSQL C extension providing SQL functions:
pgtimewarp_asof_pk: Get row version at timestamppgtimewarp_diff_pk: Get change timeline between timestamps
The extension uses postgres_fdw to read from the store database. It resolves schema_name/table_name from regclass in the source database, then queries the store by (node_id, schema_name, table_name) to avoid trusting source OIDs.
Rust CLI for management:
track: Register a table for trackinguntrack: Stop tracking a tablestatus: List tracked tables and nodesasof: Query row at timestampdiff: Show change timelinedoctor: Health diagnostics
- Source database changes are written to WAL
- Agent consumes WAL via logical replication slot
- Agent filters changes for tracked tables
- Agent transforms changes into row versions with validity intervals
- Agent writes row versions to store database
- Agent maintains LSN to timestamp mappings
- Extension/CLI queries store database for time travel queries
By default, source_db (observed) and store_db (storage) are separate databases. This provides:
- Isolation of time travel data from production
- Independent scaling and backup strategies
- Security separation
The extension uses postgres_fdw to access the store database from the source database.
PostgreSQL WAL ordering is LSN-based, not timestamp-based. Timestamps can skew across transactions. pgtimewarp uses:
valid_from_lsn/valid_to_lsn: Authoritative orderingvalid_from_ts/valid_to_ts: Best-effort wall timelsn_time_map: Periodic mappings for timestamp → LSN conversion
As-of queries convert the requested timestamp to an LSN using lsn_time_map, then query by LSN ordering.
tracked_relations uses PRIMARY KEY (node_id, schema_name, table_name) for stability across dumps/restores. The relid OID is a nullable cache field updated by the agent at runtime.