Use AWS DMS to replicate data from RDS PostgreSQL to CedarDB
Overview
- Set up a CedarDB instance in EC2 using whichever approach suits you. I prefer CloudFormation templates, for their repeatability.
- When the CedarDB instance is running, note its VPC and deploy the remaining components into that same VPC.
- Deploy an RDS Postgres instance, or enable logical replication for your existing instance.
- Create a schema in RDS and load it with some data.
- Verify that schema and data gets replicated from RDS Postgres to CedarDB.
Deploy your CedarDB instance
Here, I’ve used two CloudFormation templates:
Note the following values for the CedarDB instance:
- Private IPv4 addresses and VPC ID values from the EC2 dashboard view for the resulting instance (see below)
- The values shown in the Outputs tab in the CloudFormation UI


Create the DMS Replication instance


Finally, click the “Create replication instance” button. This process will take a while, so you can continue and check on the replication instance later.
Configure an RDS parameter group
This RDS parameter group which will enable logical replication to DMS.





Deploy a new RDS Postgres instance
If you want to use your existing RDS Postgres instance, skip this section and head down to Configure your existing RDS Postgres instance.











Now, wait a while for the RDS Postgres instance to come up.
Configure your existing RDS Postgres instance




(optional) Load a data set into the RDS instance
If this is just an exercise or demo, you will need some data to migrate. I chose this data set.
pg_restore -d postgres://postgres:pr3deb1tAmUSement@rds-pg.cfyqge68kqxu.us-east-1.rds.amazonaws.com/postgres \
-Fc employees.sql.gz -c -v --no-owner --no-privilegesVerify the tables have been created and loaded:
$ psql "postgres://postgres:pr3deb1tAmUSement@rds-pg.cfyqge68kqxu.us-east-1.rds.amazonaws.com/postgres"
Timing is on.
psql (17.4, server 16.3)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: none)
Type "help" for help.postgres=> \dn List of schemas
Name | Owner
-----------+-------------------
employees | postgres
public | pg_database_owner
(2 rows)postgres=> \dt employees.* List of relations
Schema | Name | Type | Owner
-----------+---------------------+-------+----------
employees | department | table | postgres
employees | department_employee | table | postgres
employees | department_manager | table | postgres
employees | employee | table | postgres
employees | salary | table | postgres
employees | title | table | postgres
(6 rows)postgres=> select count(*) from employees.department; count
-------
9
(1 row)
Time: 15.528 mspostgres=> select count(*) from employees.department_employee; count
--------
331603
(1 row)
Time: 26.052 mspostgres=> select count(*) from employees.department_manager; count
-------
24
(1 row)
Time: 18.947 mspostgres=> select count(*) from employees.employee; count
--------
300024
(1 row)
Time: 23.509 ms
```sql
postgres=> select count(*) from employees.salary; count
---------
2844047
(1 row)
Time: 82.885 mspostgres=> select count(*) from employees.title; count
--------
443308
(1 row)
Time: 27.676 msCreate the DMS source endpoint



Create the DMS target endpoint




Create the DMS migration task





Monitor DMS migration



Verify tables and row counts on the CedarDB target
$ psql "postgresql://postgres:pr3deb1tAmUSement@ec2-100-26-195-182.compute-1.amazonaws.com:5432/postgres"
Timing is on.
psql (17.4, server 16.3 cedar v2025-06-20)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: none)
Type "help" for help.postgres=# \dn List of schemas
Name | Owner
-----------+----------
employees | postgres
public | postgres
(2 rows)postgres=# \dt employees.* List of relations
Schema | Name | Type | Owner
-----------+---------------------+-------+----------
employees | department | table | postgres
employees | department_employee | table | postgres
employees | department_manager | table | postgres
employees | employee | table | postgres
employees | salary | table | postgres
employees | title | table | postgres
(6 rows)postgres=# select count(*) from employees.department; count
-------
9
(1 row)
Time: 17.725 mspostgres=# select count(*) from employees.department_employee; count
--------
331603
(1 row)
Time: 15.559 mspostgres=# select count(*) from employees.department_manager; count
-------
24
(1 row)
Time: 14.472 mspostgres=# select count(*) from employees.employee; count
--------
300024
(1 row)
Time: 21.151 mspostgres=# select count(*) from employees.salary; count
---------
2844047
(1 row)
Time: 15.671 mspostgres=# select count(*) from employees.title; count
--------
443308
(1 row)
Time: 18.557 msIf you intend to follow the next procedure, keep that CedarDB client connection open; otherwise, you can close it.
Verify that an UPDATE on the RDS Postgres instance is replicated to the CedarDB target
Log into the RDS Postgres instance.
$ psql "postgresql://postgres:g3n0A3aRApaimA@rds-pg.ctkkwgwc2jnl.us-east-2.rds.amazonaws.com:5432/postgres?sslmode=require"
Timing is on.
psql (18.1, server 17.6)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off, ALPN: postgresql)
Type "help" for help.
postgres=>Using the employees.salary table, validate the initial state agrees both here on the source and on the CedarDB target.
On the RDS Postgres instance:
postgres=> select * from employees.salary where employee_id = 10004 order by from_date, to_date; employee_id | amount | from_date | to_date
-------------+--------+------------+------------
10004 | 40054 | 1986-12-01 | 1987-12-01
10004 | 42283 | 1987-12-01 | 1988-11-30
10004 | 42542 | 1988-11-30 | 1989-11-30
10004 | 46065 | 1989-11-30 | 1990-11-30
10004 | 48271 | 1990-11-30 | 1991-11-30
10004 | 50594 | 1991-11-30 | 1992-11-29
10004 | 52119 | 1992-11-29 | 1993-11-29
10004 | 54693 | 1993-11-29 | 1994-11-29
10004 | 58326 | 1994-11-29 | 1995-11-29
10004 | 60770 | 1995-11-29 | 1996-11-28
10004 | 62566 | 1996-11-28 | 1997-11-28
10004 | 64340 | 1997-11-28 | 1998-11-28
10004 | 67096 | 1998-11-28 | 1999-11-28
10004 | 69722 | 1999-11-28 | 2000-11-27
10004 | 70698 | 2000-11-27 | 2001-11-27
10004 | 74057 | 2001-11-27 | 9999-01-01
(16 rows)
Time: 33.390 msOn the CedarDB instance:
postgres=# select * from employees.salary where employee_id = 10004 order by from_date, to_date; employee_id | amount | from_date | to_date
-------------+--------+------------+------------
10004 | 40054 | 1986-12-01 | 1987-12-01
10004 | 42283 | 1987-12-01 | 1988-11-30
10004 | 42542 | 1988-11-30 | 1989-11-30
10004 | 46065 | 1989-11-30 | 1990-11-30
10004 | 48271 | 1990-11-30 | 1991-11-30
10004 | 50594 | 1991-11-30 | 1992-11-29
10004 | 52119 | 1992-11-29 | 1993-11-29
10004 | 54693 | 1993-11-29 | 1994-11-29
10004 | 58326 | 1994-11-29 | 1995-11-29
10004 | 60770 | 1995-11-29 | 1996-11-28
10004 | 62566 | 1996-11-28 | 1997-11-28
10004 | 64340 | 1997-11-28 | 1998-11-28
10004 | 67096 | 1998-11-28 | 1999-11-28
10004 | 69722 | 1999-11-28 | 2000-11-27
10004 | 70698 | 2000-11-27 | 2001-11-27
10004 | 74057 | 2001-11-27 | 9999-01-01
(16 rows)
Time: 31.985 msOn the RDS Postgres instance, give the employee with ID 10004 a raise.
postgres=> begin;
BEGIN
Time: 28.403 ms
postgres=*> update employees.salary set to_date = now()::date where employee_id = 10004 and to_date = '9999-01-01'::date;
UPDATE 1
Time: 29.223 ms
postgres=*> insert into employees.salary (employee_id, amount, from_date, to_date) values (10004, 74057 + 5000, now()::date, '9999-01-01'::date);
INSERT 0 1
Time: 28.012 ms
postgres=*> commit;
COMMIT
Time: 113.268 msVerify that raise:
postgres=> select * from employees.salary where employee_id = 10004 and amount >= 74057 order by from_date; employee_id | amount | from_date | to_date
-------------+--------+------------+------------
10004 | 74057 | 2001-11-27 | 2026-03-23
10004 | 79057 | 2026-03-23 | 9999-01-01
(2 rows)
Time: 34.304 msBack on the CedarDB instance, verify that transaction was replicated
postgres=# select * from employees.salary where employee_id = 10004 and amount >= 74057 order by from_date; employee_id | amount | from_date | to_date
-------------+--------+------------+------------
10004 | 74057 | 2001-11-27 | 2026-03-23
10004 | 79057 | 2026-03-23 | 9999-01-01
(2 rows)
Time: 26.653 ms