In certain cases, you can’t do a full postgres replication to another instance, or you prefer a fine-grained control on what to replicate, pglogical is one way to achieve partial replication, albeit this requires more manual setup.
Below are steps I used to do a pglogical replication from AWS RDS to on-premise database.
Note: If a subscriber (from the above example, the on-premise database) is offline, postgres WAL would balloon up. You’ll have to remove all traces of pglogical extension, including uninstalling pglogical extension, then reinitialize everything again to resolve the problem.
1. ON PROVIDER INSTANCE: Create a role for subscriber to fetch data from provider instance
CREATE USER $SUBSCRIBER_ROLE_NAME WITH ENCRYPTED PASSWORD $SUBSCRIBER_ROLE_PASSWORD;
GRANT rds_superuser TO $SUBSCRIBER_ROLE_NAME; -- RDS specific
GRANT CONNECT ON DATABASE $DATABASE_TO_BE_REPLICATED TO $SUBSCRIBER_ROLE_NAME;
GRANT USAGE ON SCHEMA public TO $SUBSCRIBER_ROLE_NAME;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO $SUBSCRIBER_ROLE_NAME;
GRANT rds_replication TO $SUBSCRIBER_ROLE_NAME; -- RDS specific
2. ON PROVIDER INSTANCE: Init pglogical extension
CREATE EXTENSION pglogical;
GRANT ALL ON SCHEMA pglogical TO $SUBSCRIBER_ROLE_NAME;
3. ON PROVIDER INSTANCE: Define provider node
SELECT pglogical.create_node(
node_name := 'provider',
dsn := 'host=$PROVIDER_INSTANCE_HOSTNAME port=5432 user=$SUBSCRIBER_ROLE_NAME dbname=$DATABASE_TO_BE_REPLICATED password=$SUBSCRIBER_ROLE_PASSWORD'
);
4. ON PROVIDER INSTANCE: Define tables to be replicated
select pglogical.create_replication_set('replication_set');
select pglogical.replication_set_add_table(
set_name := 'replication_set',
relation := '$TABLE_NAME',
synchronize_data := true
);
5. ON SUBSCRIBER INSTANCE: Init pglogical extension
CREATE EXTENSION pglogical;
6. ON SUBSCRIBER INSTANCE: Define table schemas for replicated tables
pglogical does not transmit schema definition. Basically you need to do the equivalent of schema migration.
create table public.$TABLE_NAME
(
subject_id varchar not null,
foo integer,
bar varchar,
primary key (id)
);
-- also define indexes as well,
7. ON SUBSCRIBER INSTANCE: Define subscriber node
$SUBSCRIBER_INSTANCE_HOSTNAME
can be localhost
SELECT pglogical.create_node(
node_name := 'subscriber',
dsn := 'host=$SUBSCRIBER_INSTANCE_HOSTNAME port=5432 user=$SUBSCRIBER_INSTANCE_ROLE_NAME dbname=$DATABASE_TO_BE_REPLICATED password=$SUBSCRIBER_INSTANCE_ROLE_PASSWORD'
);
8. ON SUBSCRIBER INSTANCE: Define subscription
SELECT pglogical.create_subscription(
subscription_name := 'aws_sub',
provider_dsn := 'host=$PROVIDER_INSTANCE_HOSTNAME port=5432 dbname=$DATABASE_TO_BE_REPLICATED user=$SUBSCRIBER_ROLE_NAME password=$SUBSCRIBER_ROLE_PASSWORD',
replication_sets := ARRAY['replication_set']
);
9. ON PROVIDER INSTANCE: Verify that pglogical is working
SELECT subscription_name, status FROM pglogical.show_subscription_status();