PostgreSQL 1,289 writes every change to its write-ahead log (WAL). With wal_level = logical (set once by cdc/up.sh, with a restart) it logs enough to rebuild row changes, and logical decoding turns the WAL into inserts, updates and deletes through an output plugin; the built-in pgoutput needs no extension. A publication names the tables to decode, and a replication slot remembers how far one consumer has confirmed, so the server keeps every WAL segment that consumer still needs. BookNest's side of the setup:
CREATE ROLE debezium WITH LOGIN REPLICATION PASSWORD 'cdc-sample-password';
GRANT SELECT ON orders TO debezium; -- for the initial snapshot
CREATE PUBLICATION booknest_cdc FOR TABLE orders; -- what pgoutput may decodeThe connector creates its slot itself. That slot is also the main operational risk: it holds WAL for the whole server, not only for published tables. cdc/c4.sh paused the connector, wrote 1 million rows to an unrelated table, resumed it, and measured how far the slot's confirmed position trailed the current WAL position:
02:53:46 start 100 kB 02:53:55 paused, 1M rows written 92 MB 02:55:25 resumed, 90 s later 93 MB 02:56:31 heartbeat on, caught up 440 bytes
Resuming did not help: with no change to orders, Debezium 317,608 had no position to confirm, so on a busy server with a quiet captured table the retained WAL grows until the disk fills. The fix is a heartbeat: heartbeat.interval.ms=10000 with a heartbeat.action.query that updates a one-row table in the publication gives the connector a fresh position every 10 seconds; the slot caught up within about a minute, after Kafka Connect 129 's next offset commit. Also set max_slot_wal_keep_size (PostgreSQL 13+) so a forgotten slot is invalidated before it fills the disk, and monitor pg_replication_slots.