postgres
watcher

PostgreSQL Setup

CDC Watcher uses PostgreSQL logical replication (WAL). No triggers, no extensions — just configure wal_level.

Requirements

-- postgresql.conf
wal_level = logical
max_replication_slots = 5
max_wal_senders = 5
-- Restart PostgreSQL after changing these

The provided docker-compose.yml already has this pre-configured.

Verify

SHOW wal_level;
-- Should return: logical

Auto-created resources

On first run, the library automatically creates:

  • A replication slot (cdc_slot by default)
  • A publication (cdc_publication FOR ALL TABLES)

Configurable:

app.cdc.postgres.slot-name=my_slot
app.cdc.postgres.publication-name=my_publication
app.cdc.postgres.create-slot-if-not-exists=true
app.cdc.postgres.create-publication-if-not-exists=true

REPLICA IDENTITY

Controls how much data appears in UPDATE/DELETE events:

SettingINSERTUPDATEDELETE
DEFAULTfull rownew values onlyprimary key only
FULLfull rowold + new valuesfull deleted row
-- Required for full before/after data in UPDATE and DELETE
ALTER TABLE orders REPLICA IDENTITY FULL;

Recommendation: use REPLICA IDENTITY FULL for any table where consumers need the complete row on DELETE or need to diff old vs new on UPDATE.

Column Names

PostgreSQL WAL uses the RELATION message from the pgoutput protocol to resolve real column names. Excalibase Watcher reads these automatically — no manual mapping required. Events include actual column names (id, product, qty) for both INSERT, UPDATE, and DELETE.

DDL Capture

Capture schema changes (CREATE TABLE, ALTER TABLE, DROP TABLE) as CDC events:

app.cdc.postgres.capture-ddl=true

DDL events are published to cdc.{schema}.{table} with type: "DDL" and the DDL statement in the data field.

Snapshot Mode

On first startup, you may want to capture all existing rows before streaming live changes:

# Options: none (default), initial, schema_only
app.cdc.postgres.snapshot-mode=initial
ModeBehavior
noneOnly capture changes from now on
initialSnapshot all existing rows on first start, then stream changes
schema_onlyCapture schema structure only, then stream changes

Table Filtering

Watch specific tables instead of all:

# Comma-separated list (empty = all tables)
app.cdc.postgres.tables=orders,products,customers

This creates a publication for only the specified tables.

Full Application Config

# Database connection
app.cdc.postgres.url=jdbc:postgresql://localhost:5432/mydb
app.cdc.postgres.username=postgres
app.cdc.postgres.password=postgres

# CDC settings
app.cdc.postgres.enabled=true
app.cdc.postgres.slot-name=cdc_slot
app.cdc.postgres.publication-name=cdc_publication
app.cdc.postgres.capture-ddl=true
app.cdc.postgres.snapshot-mode=none
app.cdc.postgres.tables=

# NATS
app.cdc.nats.url=nats://localhost:4222
app.cdc.nats.stream-name=cdc-stream