Operations
Day-to-day commands for monitoring, inspecting, and managing pg-cdc.
Status
Show replication health:
pg-cdc status --config pg-cdc.ymlpg-cdc status
Slot: pg_cdc_slot (streaming) Confirmed LSN: 0/16B8920 Restart LSN: 0/16B3740 Init LSN: 0/16B3740 Source: pg_cdc_slot
Tables: 14 active, 3 excluded Latest epoch: 42 Storage: /var/lib/pg-cdc/output/ Last compacted: 2026-04-12 10:00:00 Role profiles: 3Discover
List all tables with tags and policies:
pg-cdc discover --config pg-cdc.ymlPreview changes without applying:
pg-cdc discover --dry-run --config pg-cdc.ymlShow PostgreSQL ACL-based role profiles:
pg-cdc discover --acl --config pg-cdc.ymlTeardown
Drop the publication and replication slot:
pg-cdc teardown --config pg-cdc.ymlThis is required before re-running pg-cdc init (slots cannot be re-created while active).
When to teardown:
- Changing the table scope (new tags/policies)
- Changing the replication slot or publication name
- Decommissioning pg-cdc
Recovery
Stream stopped unexpectedly
# Check statuspg-cdc status --config pg-cdc.yml
# Restart — streaming resumes from the last confirmed LSNpg-cdc start --config pg-cdc.ymlManifest corrupted
If manifest.json is lost or corrupted, the safest recovery is:
pg-cdc teardown --config pg-cdc.yml# Delete output directory contentsrm -rf /var/lib/pg-cdc/output/*pg-cdc init --config pg-cdc.ymlDownstream consumers will detect the gap (their local epoch < new base_epoch) and do a full re-pull automatically.
PostgreSQL WAL accumulation
If WAL files are growing, check that pg-cdc is running and confirming LSNs:
# On the PostgreSQL serverSELECT slot_name, active, restart_lsn, confirmed_flush_lsn, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lagFROM pg_replication_slotsWHERE slot_name = 'pg_cdc_slot';If pg-cdc is stopped and WAL is growing, either start pg-cdc or drop the slot:
pg-cdc teardown --config pg-cdc.ymlRunning as a systemd Service
[Unit]Description=pg-cdc CDC ServerAfter=postgresql.service
[Service]Type=simpleUser=pgcdcExecStart=/usr/local/bin/pg-cdc start --config /etc/pg-cdc/pg-cdc.ymlRestart=on-failureRestartSec=10
[Install]WantedBy=multi-user.targetsudo systemctl enable pg-cdcsudo systemctl start pg-cdcsudo journalctl -u pg-cdc -fCron-Based Compaction
# Compact hourly0 * * * * /usr/local/bin/pg-cdc compact --config /etc/pg-cdc/pg-cdc.yml >> /var/log/pg-cdc-compact.log 2>&1catalog subcommand
The catalog subcommand manages catalog (Glue) registration for an existing deployment. Use it when you’ve enabled catalog.type on a deployment that was previously snapshotted without it.
| Command | What it does |
|---|---|
pg-cdc catalog register | Reads the existing manifest from storage and registers every active table in the configured Glue database. No Postgres work, no re-snapshot. Safe to re-run — registration is upsert semantics (CreateTable → UpdateTable fallback). |
When to use this vs. init:
- Fresh deployment →
pg-cdc init(handles slot creation, snapshot, and catalog registration together). - Already-initialized deployment, now wiring Glue →
pg-cdc catalog register(metadata-only; ~seconds vs. re-snapshotting GB from Postgres). - Changed storage bucket/prefix and need Glue
Locationfields refreshed →pg-cdc catalog registerafter updatingpg-cdc.yml. - New table added via
ALTER PUBLICATION→pg-cdc catalog registerpicks it up from the manifest afterinitre-discovers it.
pg-cdc catalog register --config pg-cdc.yml# Glue catalog: <database> (<N> tables)mcp subcommand
pg-cdc mcp serves a local MCP endpoint over stdio so that Claude Desktop, Cursor, and other MCP clients can query the Parquet output. It is normally launched as a subprocess of the MCP client, not as a long-running daemon — the client manages the lifecycle.
pg-cdc mcp --config /etc/pg-cdc/pg-cdc.ymlFor full reference (tools, client wiring, troubleshooting, security model), see 06-mcp.md.
Should I run pg-cdc mcp under systemd?
Usually no. The stdio transport assumes the parent process owns it — Claude Desktop launches it, terminates it on quit, and restarts it next session. Running it under systemd would create a process with no peer to talk to.
The legitimate cases for managing pg-cdc mcp directly:
- Local network bridge — wrapping it behind a stdio-to-TCP shim if you want a remote client to connect to a workstation. (Out of scope for the open core. Consider whether you actually need the commercial edition’s authenticated multi-user MCP server before going down this path.)
- CI / smoke testing —
printf '<json-rpc>\n' | pg-cdc mcp --config …to verify a deployment.
Quick health check
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' \ | pg-cdc mcp --config /etc/pg-cdc/pg-cdc.ymlYou should see a JSON response carrying protocolVersion, serverInfo.name=pg-cdc, and serverInfo.version. If the call hangs or errors, see the troubleshooting section in 06-mcp.md.
acl subcommand
The acl subcommand group (Layer-2 tag intent in DynamoDB, Lake Formation reconciliation) is part of the commercial edition. It is not present in this binary.