HackerTrans
TopNewTrendsCommentsPastAskShowJobs

sacs0ni

no profile record

Submissions

Show HN: pgwire-replication - pure rust client for Postgres CDC

github.com
46 points·by sacs0ni·6 mesi fa·8 comments

Can ChatGPT Land an Airplane?

youtube.com
1 points·by sacs0ni·7 mesi fa·0 comments

comments

sacs0ni
·6 mesi fa·discuss
Good catch, you are correct. I did mix a few things there and the statements were incorrect or at least very misleading.

To demo your point I created a gist, for myself and others to see the (commit-LSN, event-LSN) ordering in action:

https://gist.github.com/vnvo/a8cf59fc3cd8719dbea56d3bb5201f9...

I'll update the readme to reflect this more accurately. Appreciate you taking the time to point it out.
sacs0ni
·6 mesi fa·discuss
I agree. pgwire-replication is useful when you need to build a customized and closely controlled pipeline. In fact, it will give you the first part of handling the data (reading from the source), you still need to implement the rest yourself.
sacs0ni
·6 mesi fa·discuss
nice! would appreciate any feedback.
sacs0ni
·6 mesi fa·discuss
I built this to have a dedicated wire-protocol client for postgres logical replication. General-purpose SQL clients either don't implement the replication protocol at all, or bury it behind abstractions designed for other use cases. Replication has a bit different mechanics - it's a stateful binary stream requiring LSN tracking, standby heartbeats, and feedback to prevent WAL bloat. Bolting that onto a query-focused client has its own challenges.

This is just the transport - raw XLogData frames and LSNs. Use pg_replicate, as an example, if you need "replicate to BigQuery." Use this if you're building replication infrastructure.

What it does:

- Explicit LSN control - start/stop at specific WAL positions for deterministic recovery

- Automatic standby feedback - no more forgotten heartbeats filling your disk with WAL

- Bounded channels - backpressure propagates to Postgres naturally

- Pure Rust, no libpq

What it doesn't do: pgoutput decoding (intentionally). That belongs in a higher layer. Simplest way of using this:

while let Some(event) = client.recv().await? { match event { ReplicationEvent::XLogData { wal_end, data, .. } => { process(&data); client.update_applied_lsn(wal_end); } _ => {} } }