Learn how Sequin ensures loss-free, strictly ordered change data capture from Postgres using backfills and real-time logical replication.
Guarantee | What it means | Why it matters |
---|---|---|
Consistency | Every row‑level event (insert, update, delete) that happens in Postgres is delivered downstream at least once. | No data loss. |
Strict ordering | Events arrive in the exact order Postgres committed them. | Avoids stale state & race conditions in the destination. |
High throughput | Sequin parallelises work whenever order guarantees allow it. | Keeps up with high‑volume workloads without lag. |
Resilience | A single “poison pill” message cannot halt the pipeline; it is isolated and retried or parked. | Keeps good data flowing even when individual records are bad. |
SELECT
crawl that copies rows that already exist in the table.select ... order by ...
). This allows you to run backfills at any time safely, and without pausing real-time replication.
The backfill worker uses keyset cursors to paginate the table, ensuring no row is ever skipped, even if the table is being written to during the backfill.
Sequin dynamically sizes backfill batches to the fastest sustained pages/second the primary can handle.
Sequin eliminates race conditions that can occur if you’re running backfills and real-time replication at the same time. If Sequin reads a row from the table while the replication stream has a concurrent change event for the same row, Sequin drops the stale read and relies on the change event. That’s because there’s no safe way to order a message that’s been read from the table and a message that’s been read from the replication stream.
Therefore, Sequin may not produce a read message for every row during a backfill. However, every row will be represented by some event (read or change). Nothing is missed.
INSERT
, UPDATE
, and DELETE
that occurs in the database. These changes remain in the slot until a connected client both reads and acknowledges them. This gives the client time to safely process each message–such as delivering it to another system–before confirming receipt. However, it’s crucial that the client processes and acknowledges messages promptly: until it does, Postgres keeps the changes in the slot, and the replication slot’s storage can grow without bound.
Sequin buffers messages from the slot into memory and sends them to your sinks. When a batch of messages have been delivered to the sink, it’s safe for Sequin to acknowledge the batch to Postgres, and for Postgres to evict them from the slot.
If a message can’t be delivered to the sink right away (e.g. the sink is rejecting the message for some reason), Sequin will store the message in its internal persistent buffer (Postgres) and retry delivery. This gives Sequin some fault tolerance to “poison pill” messages, and allows the flow to continue: because the failed message is written to Sequin’s internal persistent buffer, Sequin can still acknowledge the batch to Postgres.
In this way, Sequin is able to continuously progress through the replication slot and acknowledge messages to Postgres, even if some messages fail to deliver to the sink right away. And because Sequin does not acknowledge messages to Postgres until they’ve been delivered or stored internally, Sequin ensures that every message is captured.
message_grouping
configuration option when setting up a sink:
message_grouping: true
(default): Enable message grouping for ordered delivery within groupsmessage_grouping: false
: Disable message grouping for maximum throughput without ordering guaranteesid=1
in order”). You can also specify custom grouping columns at the table level. For example, you can group messages by a single column like account_id
to ensure all messages pertaining to the same account are delivered in order.
When message grouping is disabled, messages are delivered without considering groups. This may permit higher throughput for some sinks.