Replicating PostgreSQL Without Touching Production: Why We Chose Bucardo Over AWS DMS
When you're working with production databases, there's one rule you rarely get to break: don't touch what's working. And yet, sooner or later, you'll need to move data around — migrating to new infrastructure, syncing environments, feeding an analytics pipeline — without being able to afford a single second of downtime.
That was exactly the scenario we faced in a recent project. The "obvious" choice was AWS Database Migration Service (DMS), Amazon's managed tool for this kind of job. But once we looked closer at the requirements, we ran into a blocker that matters a lot more in production than it might seem at first glance.
The Problem with AWS DMS: Restarting the Database Isn't Always an Option
For AWS DMS to perform logical replication, PostgreSQL needs several parameters configured beforehand: wal_level, max_replication_slots, max_wal_senders, rds.logical_replication, among others. The inconvenient part is that these parameters can't be changed on the fly — they require an instance restart.
In an environment with strict uptime requirements, that alone rules the option out. On top of that, there's another common wrinkle with managed services: you often don't have root access to tweak instance-level settings, which narrows your options even further.
We needed something that could operate outside those constraints. That's where Bucardo comes in.
What Is Bucardo, and Why It Fits This Kind of Scenario
Bucardo is an open-source asynchronous replication system for PostgreSQL, written in Perl. Unlike native logical replication or services like DMS, Bucardo operates at the application level, using triggers to detect and propagate data changes between databases. That makes it especially useful when:
- You can't restart the source database.
- You don't have instance-level access to modify replication parameters.
- You need something more flexible than simple master-slave replication, such as multi-master setups with custom conflict resolution.
- You want the whole process to be self-managed, with local logs and full control over the infrastructure.
In short: where DMS demands structural changes, Bucardo adapts to the environment as-is.
Getting Hands-On: Installation and Setup on Ubuntu 24.04
Below is the step-by-step process we followed to get Bucardo up and running with an active sync between a source and a destination database. The reference environment is Ubuntu 24.04 (64-bit, x86).
1. Install PostgreSQL and Dependencies
apt-get update
apt-get install -y postgresql
apt-get install -y libdbix-safe-perl libdbd-pg-perl libboolean-perl postgresql-plperl
mkdir -p /var/log/bucardo /var/run/bucardo
chown -R postgres:postgres /var/log/bucardo /var/run/bucardo
apt-get install -y bucardo
It's normal to see this error at this stage — it resolves itself in a later step:
psql: error: connection to server on socket "/var/run/postgresql/.s.PGSQL.5432" failed: FATAL: role "bucardo" does not exist
2. Configure .bucardorc
bash
vi $HOME/.bucardorc
File contents:
dbhost=127.0.0.1
dbname=bucardo
dbport=5432
dbuser=bucardo
3. Create the Bucardo User and Database
bash
sudo su - postgres -c "psql postgres"
Inside the psql prompt:
sql
CREATE USER bucardo WITH LOGIN SUPERUSER ENCRYPTED PASSWORD 'bucardopass';
CREATE DATABASE bucardo;
CREATE EXTENSION plperl;
4. Add Credentials to .pgpass
bash
echo "127.0.0.1:5432:bucardo:bucardo:bucardopass" > $HOME/.pgpass
chmod 0600 $HOME/.pgpass
5. Prepare the Destination Database
If the source database is large, it's best to dump only the schema:
bash
pg_dump "host=source_host port=5432 dbname=source_db_name user=source_db_user" --schema-only | grep -v 'CREATE TRIGGER' | grep -v '^--' | grep -v '^$' | grep -v '^SET' | grep -v 'OWNER TO' > source_schema.sql
And restore it on the destination:
bash
psql "host=destination_host port=5432 dbname=destination_db_name user=destination_db_user" -f source_schema.sql
Then add credentials for both source and destination:
bash
cat >> $HOME/.pgpass <<EOL
destination_host:5432:database_name:db_user:db_pass
source_host:5432:database_name:db_user:db_pass
EOL
6. Install Bucardo Internally
bash
bucardo install --quiet
You can ignore this error if it shows up:
Can't open quiet: No such file or directory
7. Register the Databases
bash
bucardo add db friendly_source_db_name dbhost=source_host_name dbport=5432 dbname=db_name dbuser=db_user dbpass=db_pass
bucardo add db friendly_target_db_name dbhost=target_host_name dbport=5432 dbname=db_name dbuser=db_user dbpass=db_pass
Confirm they were registered:
bash
bucardo list dbs
8. Define the Herd (the Group of Tables to Replicate)
bash
bucardo add all tables --herd=herd1 db=friendly_source_db_name
bucardo add all sequences --herd=herd1 db=friendly_source_db_name
bash
bucardo list herds
9. Configure Sync Options
Enable more detailed logging:
bash
bucardo set quick_delta_check=0
bucardo set log_level=VERBOSE
Option A — Small databases: use onetimecopy so Bucardo handles the initial copy automatically.
bash
bucardo add sync friendly_sync_name herd=herd1 dbs=friendly_source_db_name:source,friendly_target_db_name:target onetimecopy=1
Option B — Large databases: skip onetimecopy and handle the backup/restore manually.
bash
bucardo add sync friendly_sync_name herd=herd1 dbs=friendly_source_db_name:source,friendly_target_db_name:target
After creating the sync (and before starting Bucardo), do a full backup of the source and restore it to the destination. The destination database — which up to this point only had the schema restored — can safely be dropped and recreated from the full backup.
One important detail: this backup/restore must happen after the bucardo add sync command when onetimecopy isn't used. Once the database is restored, drop the Bucardo schema that came along with the backup:
sql
drop schema bucardo cascade;
10. Start the Sync
bash
bucardo list sync
bucardo start
11. Monitoring and Maintenance
bash
tail -f /var/log/bucardo/log.bucardo
bucardo status
bucardo deactivate sync1
bucardo stop
The Result
With these steps in place, you're left with a working asynchronous replication system that runs outside PostgreSQL's core, requires no restarts, and doesn't depend on instance-level permissions. Whether for high availability, real-time analytics, or cross-region syncing, Bucardo shows that sometimes the more "hands-on" open-source tool ends up being the more practical choice over a managed service that demands conditions your production environment simply can't afford to meet.

.png)





