1. Home
  2. Docs
  3. Destinations
  4. NATS JetStream
DESTINATION · QUEUES & STREAMS

Postgres changes on NATS JetStream.

One message per change, acknowledged by the stream, with the idempotency key as Nats-Msg-Id so JetStream drops redeliveries for you.

The NATS sink publishes each change to a subject covered by a JetStream stream and waits for the stream's acknowledgement. The idempotency key becomes the message id, so JetStream's dedupe window discards a retried publish server-side, and the ordering key travels as a header.

How delivery works

AspectBehaviour for NATS JetStream
MessageData = the change JSON; header ordering_key; Nats-Msg-Id = idempotency key.
BatchingPublished one at a time in sequence order, each acknowledged before the next.
OrderingSequential publishes keep commit order on the subject.
IdempotencyServer-side via Nats-Msg-Id within the stream's duplicate window.
On failureA failed request is retried up to 5 times with exponential backoff (30 s, 1, 2, 4 min, with jitter). After the fifth failure the message is parked as undelivered, the console shows it with the last error, and one click replays it — later changes to the same row wait behind it so order is preserved.
Connection checkConnects and resolves the stream that covers the subject.

Set up in three steps

  1. Connect your database

    Paste a connection string and press Test. Waltail checks the version (12+), that wal_level is logical, that the user may replicate, and that a slot is free — and shows the fix for anything that fails. Then it creates its own publication and replication slot. Connection guide →

  2. Add NATS JetStream as a destination

    Pick the tables to stream, choose NATS JetStream, and fill in Server URL, Subject. Press Test — Waltail checks it can reach and write to NATS JetStream before anything is saved.

  3. Change a row

    Insert or update a row. The console shows the first event as it is captured and delivered; from then on, every committed change follows within about a second. Have rows that already exist? Run a backfill — confirm the estimate and they arrive through NATS JetStream as read events.

Configuration

Fields as the console asks for them. Secrets are encrypted at rest and never shown again.

FieldConsole labelRequiredNotes
urlServer URLYesCredentials in the URL, e.g. nats://user:pass@host:4222.
subjectSubjectYesMust be covered by an existing JetStream stream.

Every sink also has two tuning settings: batch size (messages per request, default 100) and rate limit (messages per second, default unlimited). Changes to one row are never in flight twice at once.

Example

Every change is this JSON envelope — data is the row after the change, old the row before it when replica identity provides it, null otherwise:

{
  "op": "update",
  "table": "public.orders",
  "data": { "id": 42, "status": "shipped", "total": 19.99 },
  "old":  { "id": 42, "status": "paid",    "total": 19.99 },
  "seq": 137,
  "idempotency_key": "9f1c3d2e-6b4a-4c7e-9d0f-2a1b3c4d5e6f",
  "commit_lsn": "0/1A2B3C8"
}

Message format reference →

Questions

Does it work with Synadia Cloud?

Yes — any NATS server with JetStream enabled, reachable with the URL you provide.

Why one message at a time?

JetStream's publish acknowledgement is per message; sequential publishes keep order without buffering on our side.

Related

Start streaming to NATS JetStream.