Skip to main content

PostgreSQL Requirements

This guide covers the requirements for using PostgreSQL as a CDC source with EZ-CDC.

Version Requirements

RequirementMinimumRecommended
PostgreSQL Version1214+
Logical ReplicationRequired-

Configuration Requirements

1. Enable Logical Replication

PostgreSQL must have wal_level = 'logical' to enable CDC:

-- Check current setting
SHOW wal_level;

If not logical, update postgresql.conf:

# postgresql.conf
wal_level = 'logical'
max_replication_slots = 10
max_wal_senders = 10

Restart PostgreSQL after changing these settings.

warning

Changing wal_level requires a PostgreSQL restart.

2. Replication Slots

Ensure you have available replication slots:

-- Check current usage
SELECT slot_name, active FROM pg_replication_slots;

-- Check max slots
SHOW max_replication_slots;

Each CDC job requires one replication slot.

3. WAL Senders

Ensure you have available WAL senders:

-- Check current usage
SELECT * FROM pg_stat_replication;

-- Check max senders
SHOW max_wal_senders;

User Permissions

Create CDC User

Create a dedicated user for CDC:

-- Create user with replication privilege
CREATE USER ezcdc_user WITH
REPLICATION
LOGIN
PASSWORD 'your_secure_password';

-- Grant connect to database
GRANT CONNECT ON DATABASE mydb TO ezcdc_user;

-- Grant usage on schema
GRANT USAGE ON SCHEMA public TO ezcdc_user;

-- Grant select on tables (all current tables)
GRANT SELECT ON ALL TABLES IN SCHEMA public TO ezcdc_user;

-- Grant select on future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO ezcdc_user;

Required Privileges Summary

PrivilegePurpose
REPLICATIONCreate replication slots and read WAL
CONNECTConnect to the database
USAGEAccess the schema
SELECTRead table data for initial snapshot

Network Requirements

Connectivity

Workers must be able to connect to PostgreSQL:

FromToPortProtocol
EZ-CDC WorkerPostgreSQL5432TCP

Firewall Rules

If using security groups or firewalls:

# Allow from EZ-CDC worker security group
resource "aws_security_group_rule" "postgres_from_ezcdc" {
type = "ingress"
from_port = 5432
to_port = 5432
protocol = "tcp"
source_security_group_id = var.ezcdc_worker_sg_id
security_group_id = var.postgres_sg_id
}

AWS RDS / Aurora

For AWS managed databases:

  1. Ensure the parameter group has rds.logical_replication = 1
  2. Verify security group allows worker access
  3. Use the correct endpoint (writer for CDC)
-- Check RDS logical replication
SHOW rds.logical_replication; -- Should be 'on'

For RDS, grant replication via the rds_replication role:

GRANT rds_replication TO ezcdc_user;

GCP Cloud SQL

For Google Cloud SQL for PostgreSQL:

  1. Enable logical replication: In the Cloud SQL instance settings, enable the cloudsql.logical_decoding database flag and set it to on. This sets wal_level = 'logical' internally. The instance will restart.

  2. Grant REPLICATION privilege: The default postgres user in Cloud SQL does not have the REPLICATION privilege by default. Connect as postgres and run:

-- If using a dedicated CDC user
CREATE USER ezcdc_user WITH REPLICATION LOGIN PASSWORD 'your_secure_password';

-- Or if using the default postgres user
ALTER ROLE postgres WITH REPLICATION;
  1. Network access: Cloud SQL instances with private IP only are accessible from within the VPC. Ensure your EZ-CDC workers are deployed in the same VPC or a peered network. If using Cloud SQL Auth Proxy from outside the VPC, enable a public IP temporarily or use IAP tunneling.

  2. Verify configuration:

-- Check WAL level (should be 'logical')
SHOW wal_level;

-- Check replication privilege
SELECT rolname, rolreplication FROM pg_roles WHERE rolname = current_user;

-- Check available replication slots
SHOW max_replication_slots;
tip

Cloud SQL sets max_replication_slots = 10 and max_wal_senders = 10 by default when logical decoding is enabled. You can adjust these via database flags if needed.

Table Requirements

Primary Keys

Tables should have primary keys for proper CDC:

-- Check for tables without primary keys
SELECT t.table_schema, t.table_name
FROM information_schema.tables t
LEFT JOIN information_schema.table_constraints tc
ON t.table_schema = tc.table_schema
AND t.table_name = tc.table_name
AND tc.constraint_type = 'PRIMARY KEY'
WHERE t.table_type = 'BASE TABLE'
AND t.table_schema = 'public'
AND tc.constraint_name IS NULL;
tip

Tables without primary keys can still be replicated, but UPDATE and DELETE operations will include all columns to identify rows.

REPLICA IDENTITY

For tables without primary keys, set REPLICA IDENTITY:

-- Use FULL for tables without PK (includes all columns in updates)
ALTER TABLE my_table REPLICA IDENTITY FULL;

-- Check current setting
SELECT relname, relreplident
FROM pg_class
WHERE relname = 'my_table';
-- 'd' = default, 'f' = full, 'i' = index, 'n' = nothing

Verification Script

Run this script to verify your PostgreSQL is ready:

-- 1. Check WAL level
SELECT
CASE WHEN current_setting('wal_level') = 'logical'
THEN '✓ WAL level is logical'
ELSE '✗ WAL level is ' || current_setting('wal_level')
END AS wal_check;

-- 2. Check available replication slots
SELECT
current_setting('max_replication_slots')::int - COUNT(*) AS available_slots
FROM pg_replication_slots;

-- 3. Check available WAL senders
SELECT
current_setting('max_wal_senders')::int - COUNT(*) AS available_senders
FROM pg_stat_replication;

-- 4. Check user permissions
SELECT
rolreplication AS has_replication,
rolcanlogin AS can_login
FROM pg_roles
WHERE rolname = 'ezcdc_user';

-- 5. Check tables without primary keys
SELECT COUNT(*) AS tables_without_pk
FROM information_schema.tables t
LEFT JOIN information_schema.table_constraints tc
ON t.table_schema = tc.table_schema
AND t.table_name = tc.table_name
AND tc.constraint_type = 'PRIMARY KEY'
WHERE t.table_type = 'BASE TABLE'
AND t.table_schema = 'public'
AND tc.constraint_name IS NULL;

Common Issues

"cannot create replication slot"

Cause: wal_level is not logical or no available slots.

Solution:

  1. Set wal_level = 'logical' and restart
  2. Increase max_replication_slots

"permission denied for replication"

Cause: User doesn't have REPLICATION privilege.

Solution:

ALTER USER ezcdc_user WITH REPLICATION;

"could not connect to server"

Cause: Network connectivity issue.

Solution:

  1. Check security groups allow port 5432
  2. Verify PostgreSQL is listening on correct interface
  3. Check pg_hba.conf allows the connection

Next Steps