> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-mintlify-8a08bda2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Migrate to Managed Postgres using logical replication

> Learn how to migrate your PostgreSQL data to ClickHouse Managed Postgres using logical replication

export const Image = ({img, alt, size}) => {
  return <Frame>
      <img src={img} alt={alt} />
    </Frame>;
};

export const galaxyOnClick = eventName => () => {
  try {
    if (typeof window !== "undefined" && window.galaxy && eventName) {
      window.galaxy.track(eventName, {
        interaction: "click"
      });
    }
  } catch (e) {}
};

export const BetaBadge = ({link, galaxyTrack, galaxyEvent}) => {
  if (link) {
    return <a href={link} target="_blank" rel="noopener noreferrer" className="betaBadge" onClick={galaxyTrack && galaxyEvent ? galaxyOnClick(galaxyEvent) : undefined}>
                <Icon />
                <span>Beta</span>
            </a>;
  }
  return <div className="betaBadge">
            <Icon />
            <span>
                Beta feature. 
                <u>
                    <a href="/docs/beta-and-experimental-features#beta-features">
                        Learn more.
                    </a>
                </u>
            </span>
        </div>;
};

This guide provides step-by-step instructions on how to migrate your PostgreSQL database to ClickHouse Managed Postgres using Postgres native logical replication.

<h2 id="migration-logical-replication-prerequisites">
  Prerequisites
</h2>

* Access to your source PostgreSQL database.
* `psql`,`pg_dump` and `pg_restore` installed on your local machine. This is for creating empty tables in your target database. These are typically included with PostgreSQL installations. If not, you can download them from the [PostgreSQL official website](https://www.postgresql.org/download/).
* Your source database must be reachable from ClickHouse Managed Postgres. Ensure that any necessary firewall rules or security group settings allow for this connectivity. You can get the egress IP of your Managed Postgres instance by doing:

```shell theme={null}
dig +short <your-managed-postgres-hostname>
```

<h2 id="migration-logical-replication-setup">
  The setup
</h2>

For logical replication to work, we need to ensure that the source database is set up correctly. Here are the key requirements:

* The source database must have `wal_level` set to `logical`.
* The source database must have `max_replication_slots` set to at least `1`.
* For RDS (which this guide uses as an example), you need to ensure that your parameter group has `rds.logical_replication` set to `1`.
* The source database user must have the `REPLICATION` privilege. In the case of RDS, you would run:
  ```sql theme={null}
  GRANT rds_replication TO <your-username>;
  ```
* The role you use for the target database must have write privileges on the target database's objects:
  ```sql theme={null}
  GRANT USAGE ON SCHEMA <schema_i> TO subscriber_user;
  GRANT CREATE ON DATABASE destination_db TO subscriber_user;
  GRANT pg_create_subscription TO subscriber_user;

  -- Grant table rights
  GRANT INSERT, UPDATE, DELETE, TRUNCATE ON ALL TABLES IN SCHEMA <schema_i> TO subscriber_user;
  ```

Make sure your source database is set up like this:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/1Ag2q2dX2WMxuS9G/images/managed-postgres/logical_replication/source-setup.png?fit=max&auto=format&n=1Ag2q2dX2WMxuS9G&q=85&s=6f09ac619bb40473309487ce5fef5fd1" alt="Source PostgreSQL Replication Setup" size="md" border width="1400" height="932" data-path="images/managed-postgres/logical_replication/source-setup.png" />

<h2 id="migration-logical-replication-schema-dump">
  Schema-only dump of the source database
</h2>

Before setting up logical replication, we need to create the schema in the target ClickHouse Managed Postgres database. We can do this by creating a schema-only dump of the source database using `pg_dump`:

```shell theme={null}
pg_dump \
    -d 'postgresql://<user>:<password>@<host>:<port>/<database>' \
    -s \
    --format directory \
    -f rds-dump
```

Here:

* Replace `<user>`, `<password>`, `<host>`, `<port>`, and `<database>` with your source database credentials.
* `-s` specifies that we want a schema-only dump.
* `--format directory` specifies that we want the dump in a directory format, which is suitable for `pg_restore`.
* `-f rds-dump` specifies the output directory for the dump files. Note that this directory will be created automatically and shouldn't exist beforehand.

In our case, we have two tables - `events` and `users`. `events` has a million rows, and `users` has a thousand rows.

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/1Ag2q2dX2WMxuS9G/images/managed-postgres/pg_dump_restore/source-setup.png?fit=max&auto=format&n=1Ag2q2dX2WMxuS9G&q=85&s=eea750696c8335e15eecbcbc06ddfdc6" alt="Source PostgreSQL Tables Setup" size="xl" border width="3766" height="2312" data-path="images/managed-postgres/pg_dump_restore/source-setup.png" />

<h3 id="migration-pgdump-pg-restore-create-pg">
  Create a Managed Postgres instance
</h3>

First, ensure you have a Managed Postgres instance set up, preferably in the same region as the source. You can follow the quick guide [here](/products/managed-postgres/quickstart#create-postgres-database). Here's what we're going to spin up for this guide:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/1Ag2q2dX2WMxuS9G/images/managed-postgres/pg_dump_restore/create-pg-for-migration.png?fit=max&auto=format&n=1Ag2q2dX2WMxuS9G&q=85&s=b0af5b294fa09f5cf10b2ec2f64871a7" alt="Create ClickHouse Managed Postgres Instance" size="md" border width="1532" height="1570" data-path="images/managed-postgres/pg_dump_restore/create-pg-for-migration.png" />

<h2 id="migration-logical-replication-restore-schema">
  Restore the schema to ClickHouse Managed Postgres
</h2>

Now that we have the schema dump, we can restore it to our ClickHouse Managed Postgres instance using `pg_restore`:

```shell theme={null}
pg_restore \
    -d 'postgresql://<user>:<password>@<host>:<port>/<database>' \
    --verbose \
    rds-dump
```

Here:

* Replace `<user>`, `<password>`, `<host>`, `<port>`, and `<database>` with your target ClickHouse Managed Postgres database credentials.
* `--verbose` provides detailed output during the restore process.
  This command will create all the tables, indexes, views, and other schema objects in the target database without any data.

In our case, after running this command, we have our two tables and they're empty:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/1Ag2q2dX2WMxuS9G/images/managed-postgres/logical_replication/target-initial-setup.png?fit=max&auto=format&n=1Ag2q2dX2WMxuS9G&q=85&s=d1022a158f6662ee120e8ba5b0661690" alt="Target ClickHouse Managed Postgres Initial Setup" size="xl" border width="2019" height="445" data-path="images/managed-postgres/logical_replication/target-initial-setup.png" />

<h2 id="migration-logical-replication-setup-replication">
  Set up logical replication
</h2>

With the schema in place, we can now set up logical replication from the source database to the target ClickHouse Managed Postgres database. This involves creating a publication on the source database and a subscription on the target database.

<h3 id="migration-logical-replication-create-publication">
  Create a publication on the source database
</h3>

Connect to your source PostgreSQL database and create a publication that includes the tables you want to replicate.

```sql theme={null}
CREATE PUBLICATION <pub_name> FOR TABLE table1, table2...;
```

<Info>
  Creating a publication FOR ALL TABLES can incur network overhead if there are many tables. It's recommended to specify only the tables you want to replicate.
</Info>

<h3 id="migration-logical-replication-create-subscription">
  Create a subscription on the target ClickHouse Managed Postgres database
</h3>

Next, connect to your target ClickHouse Managed Postgres database and create a subscription that connects to the publication on the source database.

```sql theme={null}
CREATE SUBSCRIPTION demo_rds_subscription
CONNECTION 'postgresql://<user>:<password>@<host>:<port>/<database>'
PUBLICATION <pub_name_you_entered_above>;
```

This will automatically create a replication slot on the source database and start replicating data from the specified tables to the target database. Depending on the size of your data, this process may take some time.

In our case, after setting up the subscription, the data flowed in:

<Image img="https://mintcdn.com/private-7c7dfe99-mintlify-8a08bda2/1Ag2q2dX2WMxuS9G/images/managed-postgres/logical_replication/migration-result.png?fit=max&auto=format&n=1Ag2q2dX2WMxuS9G&q=85&s=0a5a72fc4c6ef839a6ce3b7c399eaaec" alt="Migration Result after Logical Replication" size="xl" border width="1920" height="658" data-path="images/managed-postgres/logical_replication/migration-result.png" />

New rows inserted into the source database will now be replicated to the target ClickHouse Managed Postgres database in near real-time.

<h2 id="migration-logical-replication-caveats">
  Caveats and considerations
</h2>

* Logical replication only replicates data changes (INSERT, UPDATE, DELETE). Schema changes (like ALTER TABLE) need to be handled separately.
* Ensure that the network connection between the source and target databases is stable to avoid replication interruptions.
* Monitor the replication lag to ensure that the target database is keeping up with the source database. Setting a suitable value for `max_slot_wal_keep_size` on the source database can help manage a growing replication slot and prevent it from consuming too much disk space.
* Depending on your use case, you might want to set up monitoring and alerting for the replication process.

<h2 id="migration-pgdump-pg-restore-next-steps">
  Next steps
</h2>

Congratulations! You have successfully migrated your PostgreSQL database to ClickHouse Managed Postgres using pg\_dump and pg\_restore. You're now all set to explore Managed Postgres features and its integration with ClickHouse. Here's a 10 minute quickstart to get you going:

* [Managed Postgres Quickstart Guide](/products/managed-postgres/quickstart)
