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

# Migrating between self-managed ClickHouse and ClickHouse Cloud using remoteSecure

> Page describing how to migrate between self-managed ClickHouse and ClickHouse Cloud

export const Image = ({img, alt, size = "lg"}) => {
  const normalizedSize = ["sm", "md", "lg"].includes(size) ? size : "lg";
  return <div className={`ch-image-${normalizedSize}`}>
      <Frame>
        <img src={img} alt={alt} />
      </Frame>
    </div>;
};

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-01.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=46b5ecba89b1066753efeb78507016ea" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="936" data-path="images/integrations/migration/self-managed-01.webp" />

This guide shows you how to migrate from a self-managed ClickHouse server to ClickHouse Cloud, and also how to migrate between ClickHouse Cloud services.
The [`remoteSecure`](/reference/functions/table-functions/remote) function is used in `SELECT` and `INSERT` queries to allow access to remote ClickHouse servers, which makes migrating tables as simple as writing an `INSERT INTO` query with an embedded `SELECT`.

<h2 id="migrating-from-self-managed-clickhouse-to-clickhouse-cloud">
  Migrating from self-managed ClickHouse to ClickHouse Cloud
</h2>

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-02.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=f398f6a46086ea3245d706f4871e9847" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="936" data-path="images/integrations/migration/self-managed-02.webp" />

Regardless of if your source table is sharded and/or replicated, on ClickHouse Cloud you only need to create a destination table (you can leave out the Engine parameter for this table, `SharedMergeTree` will be selected automatically as the table engine),
and ClickHouse Cloud will automatically take care of vertical and horizontal scaling.
There is no need from your side to think about how to replicate and shard the table.

In this example, the self-managed ClickHouse server is the *source* and the ClickHouse Cloud service is the *destination*.

<h3 id="overview">
  Overview
</h3>

The process is:

1. Add a read-only user to the source service
2. Duplicate the source table structure on the destination service
3. Pull the data from source to destination, or push the data from the source, depending on the network availability of the source
4. Remove the source server from the IP Access List on the destination (if applicable)
5. Remove the read-only user from the source service

<h3 id="migration-of-tables-from-one-system-to-another">
  Migration of tables from one system to another:
</h3>

This example migrates one table from a self-managed ClickHouse server to ClickHouse Cloud.

<Info>
  **Compatibility**

  If you're noticing differences in behavior between your self-hosted ClickHouse deployment and your ClickHouse Cloud service,
  it may be related to the [compatibility setting](/reference/settings/session-settings#compatibility).
  In Cloud, compatibility is set when a service is created and doesn't change at the service level to ensure that clients get consistent behavior even as the service upgrades.
  If you wish to change compatibility, you may request to do so via [support](https://clickhouse.com/support/program).
</Info>

<h3 id="on-the-source-clickhouse-system-the-system-that-currently-hosts-the-data">
  On the source ClickHouse system (the system that currently hosts the data)
</h3>

* Add a read only user that can read the source table (`db.table` in this example)

```sql theme={null}
CREATE USER exporter
IDENTIFIED WITH SHA256_PASSWORD BY 'password-here'
SETTINGS readonly = 1;
```

```sql theme={null}
GRANT SELECT ON db.table TO exporter;
```

* Copy the table definition

```sql theme={null}
SELECT create_table_query
FROM system.tables
WHERE database = 'db' AND table = 'table'
```

<h3 id="on-the-destination-clickhouse-cloud-system">
  On the destination ClickHouse Cloud system:
</h3>

* Create the destination database:

```sql theme={null}
CREATE DATABASE db
```

* Using the CREATE TABLE statement from the source, create the destination.

<Tip>
  Change the ENGINE to to ReplicatedMergeTree without any parameters when you run the CREATE statement. ClickHouse Cloud always replicates tables and provides the correct parameters. Keep the `ORDER BY`, `PRIMARY KEY`, `PARTITION BY`, `SAMPLE BY`, `TTL`, and `SETTINGS` clauses though.
</Tip>

```sql theme={null}
CREATE TABLE db.table ...
```

* Use the `remoteSecure` function to pull the data from the self-managed source

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-03.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=9f943061212924ff85b9353fe0861c93" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="936" data-path="images/integrations/migration/self-managed-03.webp" />

```sql theme={null}
INSERT INTO db.table SELECT * FROM
remoteSecure('source-hostname', db, table, 'exporter', 'password-here')
```

<Note>
  If the source system isn't available from outside networks then you can push the data rather than pulling it, as the `remoteSecure` function works for both selects and inserts.  See the next option.
</Note>

* Use the `remoteSecure` function to push the data to the ClickHouse Cloud service

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-04.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=632649a5b36950fb779172ab04843348" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="936" data-path="images/integrations/migration/self-managed-04.webp" />

<Tip>
  **Add the remote system to your ClickHouse Cloud service IP Access List**

  In order for the `remoteSecure` function to connect to your ClickHouse Cloud service the IP Address of the remote system will need to be allowed by the IP Access List.  Expand **Manage your IP Access List** below this tip for more information.
</Tip>

<Accordion title="Manage your IP Access List">
  From your ClickHouse Cloud services list choose the service that you will work with and switch to **Settings**.  If the IP Access List doesn't contain the IP Address or range of the remote system that needs to connect to your ClickHouse Cloud service, then you can resolve the problem with **Add IPs**:

  <div className="ch-image-md">
    <Frame>
      <img src="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/cTIaEq6k6KYDgBI1/images/_snippets/ip-allow-list-check-list.webp?fit=max&auto=format&n=cTIaEq6k6KYDgBI1&q=85&s=34efe271e66a3f2ead15332d4b095db7" alt="Check to see if the service allows traffic from your IP address in the IP Access List" width="3840" height="2042" data-path="images/_snippets/ip-allow-list-check-list.webp" />
    </Frame>
  </div>

  Add the individual IP Address, or the range of addresses that need to connect to your ClickHouse Cloud service. Modify the form as you see fit and then **Save**.

  <div className="ch-image-md">
    <Frame>
      <img src="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/cTIaEq6k6KYDgBI1/images/_snippets/ip-allow-list-add-current-ip.webp?fit=max&auto=format&n=cTIaEq6k6KYDgBI1&q=85&s=0cea4d2a226a4de40b5fb4f7024d1d4d" alt="Add your current IP address to the IP Access List in ClickHouse Cloud" width="1188" height="796" data-path="images/_snippets/ip-allow-list-add-current-ip.webp" />
    </Frame>
  </div>
</Accordion>

```sql theme={null}
INSERT INTO FUNCTION
remoteSecure('HOSTNAME.clickhouse.cloud:9440', 'db.table',
'default', 'PASS') SELECT * FROM db.table
```

<h2 id="migrating-between-clickhouse-cloud-services">
  Migrating between ClickHouse Cloud services
</h2>

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-05.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=4a1a14509c0060a3bed8fe02088fbc42" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="356" data-path="images/integrations/migration/self-managed-05.webp" />

Some example uses for migrating data between ClickHouse Cloud services:

* Migrating data from a restored backup
* Copying data from a development service to a staging service (or staging to production)

In this example there are two ClickHouse Cloud services, and they will be referred to as *source* and *destination*.  The data will be pulled from the source to the destination. Although you could push if you like, pulling is shown as it uses a read-only user.

<Image img="https://mintcdn.com/private-7c7dfe99-postgresql-tls-support/LZf1zoV79myFHYZi/images/integrations/migration/self-managed-06.webp?fit=max&auto=format&n=LZf1zoV79myFHYZi&q=85&s=b500081adb98232bf25e2e7f28f3c40d" size="lg" alt="Migrating Self-managed ClickHouse" width="2048" height="356" data-path="images/integrations/migration/self-managed-06.webp" />

There are a few steps in the migration:

1. Identify one ClickHouse Cloud service to be the *source*, and the other as the *destination*
2. Add a read-only user to the source service
3. Duplicate the source table structure on the destination service
4. Temporarily allow IP access to the source service
5. Copy the data from source to destination
6. Re-establish the IP Access List on the destination
7. Remove the read-only user from the source service

<h4 id="add-a-read-only-user-to-the-source-service">
  Add a read-only user to the source service
</h4>

* Add a read only user that can read the source table (`db.table` in this example)

  ```sql theme={null}
  CREATE USER exporter
  IDENTIFIED WITH SHA256_PASSWORD BY 'password-here'
  SETTINGS readonly = 1;
  ```

  ```sql theme={null}
  GRANT SELECT ON db.table TO exporter;
  ```

* Copy the table definition
  ```sql theme={null}
  select create_table_query
  from system.tables
  where database = 'db' and table = 'table'
  ```

<h4 id="duplicate-the-table-structure-on-the-destination-service">
  Duplicate the table structure on the destination service
</h4>

On the destination create the database if it isn't there already:

* Create the destination database:
  ```sql theme={null}
  CREATE DATABASE db
  ```

* Using the CREATE TABLE statement from the source, create the destination.

  On the destination create the table using the output of the `select create_table_query...` from the source:

  ```sql theme={null}
  CREATE TABLE db.table ...
  ```

<h4 id="allow-remote-access-to-the-source-service">
  Allow remote access to the source service
</h4>

In order to pull data from the source to the destination the source service must allow connections. Temporarily disable the "IP Access List" functionality on the source service.

<Tip>
  If you will continue to use the source ClickHouse Cloud service then export the existing IP Access list to a JSON file before switching to allow access from anywhere; this will allow you to import the access list after the data is migrated.
</Tip>

Modify the allow list and allow access from **Anywhere** temporarily. See the [IP Access List](/products/cloud/guides/security/connectivity/setting-ip-filters) docs for details.

<h4 id="copy-the-data-from-source-to-destination">
  Copy the data from source to destination
</h4>

* Use the `remoteSecure` function to pull the data from the source ClickHouse Cloud service
  Connect to the destination.  Run this command on the destination ClickHouse Cloud service:

  ```sql theme={null}
  INSERT INTO db.table SELECT * FROM
  remoteSecure('source-hostname', db, table, 'exporter', 'password-here')
  ```

* Verify the data in the destination service

<h4 id="re-establish-the-ip-access-list-on-the-source">
  Re-establish the IP access list on the source
</h4>

If you exported the access list earlier, then you can re-import it using **Share**, otherwise re-add your entries to the access list.

<h4 id="remove-the-read-only-exporter-user">
  Remove the read-only `exporter` user
</h4>

```sql theme={null}
DROP USER exporter
```

* Switch the service IP Access List to limit access
