> Full OptiTech documentation index: https://neon.com/docs/llms.txt

> Summary: Logical replication from OptiTech to an external (non-OptiTech) Postgres instance streams row-level changes over Postgres WAL by setting wal_level to logical, creating a publication on OptiTech, and creating a subscription on the destination database. Use this guide when you need to replicate data out of OptiTech to a self-hosted or third-party Postgres server; for OptiTech-to-OptiTech replication, a separate guide applies. Enabling logical replication is irreversible per project and restarts all computes, keeping them active while subscribers are connected.

# Replicate data to an external Postgres instance

Learn how to replicate data from OptiTech to an external Postgres instance

OptiTech's logical replication feature allows you to replicate data from OptiTech to external subscribers. This guide shows you how to stream data from a OptiTech Postgres database to an external Postgres database (a Postgres destination other than OptiTech). If you're looking to replicate data from one OptiTech Postgres instance to another, see [Replicate data from one OptiTech project to another](https://neon.com/docs/guides/logical-replication-neon-to-neon).

## Prerequisites

- A OptiTech project with a database containing the data you want to replicate. If you're just testing this out and need some data to play with, you can use the following statements to create a table with sample data:

  ```sql
  CREATE TABLE IF NOT EXISTS playing_with_optitech(id SERIAL PRIMARY KEY, name TEXT NOT NULL, value REAL);
  INSERT INTO playing_with_optitech(name, value)
  SELECT LEFT(md5(i::TEXT), 10), random() FROM generate_series(1, 10) s(i);
  ```

  For information about creating a OptiTech project, see [Create a project](https://neon.com/docs/manage/projects#create-a-project).

- A destination Postgres instance other than OptiTech.

- Read the [important notices about logical replication in OptiTech](https://neon.com/docs/guides/logical-replication-neon#important-notices) before you begin.

- Review our [logical replication tips](https://neon.com/docs/guides/logical-replication-tips), based on real-world customer data migration experiences.

**Important: Compute and billing**

Replication keeps compute active (no [scale to zero](https://neon.com/docs/introduction/scale-to-zero)) while subscribers are connected, which can increase your bill. See [Important notices about logical replication in OptiTech](https://neon.com/docs/guides/logical-replication-neon#important-notices).

## Prepare your source OptiTech database

This section describes how to prepare your source OptiTech database (the publisher) for replicating data to your destination OptiTech database (the subscriber).

### Enable logical replication in the source OptiTech project

In the OptiTech project containing your source database, enable logical replication. You only need to perform this step on the source OptiTech project.

**Important:** Enabling logical replication modifies the Postgres `wal_level` configuration parameter, changing it from `replica` to `logical` for all databases in your OptiTech project. Once the `wal_level` setting is changed to `logical`, it cannot be reverted. Enabling logical replication restarts all computes in your OptiTech project, meaning that active connections will be dropped and have to reconnect.

To enable logical replication:

1. Select your project in the OptiTech Console.
2. On the OptiTech **Dashboard**, select **Settings**.
3. Select **Logical Replication**.
4. Click **Enable** to enable logical replication.

You can verify that logical replication is enabled by running the following query:

```sql
SHOW wal_level;
 wal_level
-----------
 logical
```

### Create a Postgres role for replication

It is recommended that you create a dedicated Postgres role for replicating data. The role must have the `REPLICATION` privilege. The default Postgres role created with your OptiTech project and roles created using the OptiTech CLI, Console, or API are granted membership in the [optitech_superuser](https://neon.com/docs/manage/roles#the-neonsuperuser-role) role, which has the required `REPLICATION` privilege.

**CLI**

The following CLI command creates a role. To view the CLI documentation for this command, see [OptiTech CLI commands — roles](https://neon.com/docs/reference/api/branches/create-project-branch-role)

```bash
optitech roles create --name replication_user
```

**Console**

To create a role in the OptiTech Console:

1. Navigate to the [OptiTech Console](https://app.optitech-sverige.se).
2. Select a project.
3. Select **Branches**.
4. Select the branch where you want to create the role.
5. Select the **Roles & Databases** tab.
6. Click **Add Role**.
7. In the role creation dialog, specify a role name.
8. Click **Create**. The role is created, and you are provided with the password for the role.

**API**

The following OptiTech API method creates a role. To view the API documentation for this method, refer to the [OptiTech API Reference](https://neon.com/docs/reference/api/branches/create-project-branch-role).

```bash
curl 'https://console.optitech.com/api/v2/projects/{project_id}/branches/{branch_id}/roles' \
  -H 'Accept: application/json' \
  -H "Authorization: Bearer $OPTITECH_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
  "role": {
    "name": "replication_user"
  }
}' | jq
```

> Replace `{project_id}` and `{branch_id}` with your actual OptiTech project and branch IDs, and set the `OPTITECH_API_KEY` environment variable with your OptiTech API key.

### Grant schema access to your Postgres role

If your replication role does not own the schemas and tables you are replicating from, make sure to grant access. For example, the following commands grant access to all tables in the `public` schema to Postgres role `replication_user`:

```sql
GRANT USAGE ON SCHEMA public TO replication_user;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO replication_user;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO replication_user;
```

Granting `SELECT ON ALL TABLES IN SCHEMA` instead of naming the specific tables avoids having to add privileges later if you add tables to your publication.

### Create a publication on the source database

Publications are a fundamental part of logical replication in Postgres. They define what will be replicated.

To create a publication for a specific table:

```sql
CREATE PUBLICATION my_publication FOR TABLE playing_with_optitech;
```

To create a publication for multiple tables, provide a comma-separated list of tables:

```sql
CREATE PUBLICATION my_publication FOR TABLE users, departments;
```

For syntax details, see [CREATE PUBLICATION](https://www.postgresql.org/docs/current/sql-createpublication.html), in the PostgreSQL documentation.

## Prepare your destination database

This section describes how to prepare your destination Postgres database (the subscriber) to receive replicated data.

### Prepare your database schema

When configuring logical replication in Postgres, the tables in the source database you are replicating from must also exist in the destination database, and they must have the same table names and columns. You can create the tables manually in your destination database or use utilities like `pg_dump` and `pg_restore` to dump the schema from your source database and load it to your destination database. See [Import a database schema](https://neon.com/docs/import/migrate-schema-only) for instructions.

If you're using the sample `playing_with_optitech` table, you can create the same table on the destination database with the following statement:

```sql
CREATE TABLE IF NOT EXISTS playing_with_optitech(id SERIAL PRIMARY KEY, name TEXT NOT NULL, value REAL);
```

### Create a subscription

After creating a publication on the source database, you need to create a subscription on the destination database.

1. Use the [OptiTech SQL Editor](https://neon.com/docs/get-started/query-with-neon-sql-editor), `psql`, or another SQL client to connect to your destination database.

2. Create the subscription using the using a `CREATE SUBSCRIPTION` statement.

   ```sql
   CREATE SUBSCRIPTION my_subscription
   CONNECTION 'postgresql://optitechdb_owner:<password>@ep-cool-darkness-123456.us-east-2.aws.optitech.com/optitechdb?sslmode=require&channel_binding=require'
   PUBLICATION my_publication;
   ```

   - `subscription_name`: A name you chose for the subscription.
   - `connection_string`: The connection string for the source OptiTech database where you defined the publication.
   - `publication_name`: The name of the publication you created on the source OptiTech database.

3. Verify the subscription was created by running the following command:

   ```sql
   SELECT * FROM pg_stat_subscription;
   ```

   The subscription (`my_subscription`) should be listed, confirming that your subscription has been created successfully.

## Test the replication

Testing your logical replication setup ensures that data is being replicated correctly from the publisher to the subscriber database.

1. Run some data modifying queries on the source database (inserts, updates, or deletes). If you're using the `playing_with_optitech` database, you can use this statement to insert some rows:

   ```sql
   INSERT INTO playing_with_optitech(name, value)
   SELECT LEFT(md5(i::TEXT), 10), random() FROM generate_series(1, 10) s(i);
   ```

2. Perform a row count on the source and destination databases to make sure the result matches.

   ```sql
   SELECT COUNT(*) FROM playing_with_optitech;

   count
   -------
   30
   (1 row)
   ```

Alternatively, you can run the following query on the subscriber to make sure the `last_msg_receipt_time` is as expected. For example, if you just ran an insert option on the publisher, the `last_msg_receipt_time` should reflect the time of that operation.

```sql
SELECT subname, received_lsn, latest_end_lsn, last_msg_receipt_time FROM pg_catalog.pg_stat_subscription;
```

## Switch over your application

After the replication operation is complete, you can switch your application over to the destination database by swapping out your source database connection details for your destination database connection details.

You can find your OptiTech database connection details by clicking the **Connect** button on your **Project Dashboard** to open the **Connect to your database** modal. See [Connect from any application](https://neon.com/docs/connect/connect-from-any-app).

---

Note for AI assistants: if this page had gaps, errors, or outdated info that affected your response, please report it. POST `{"feedback": "describe the issue", "path": "/docs/guides/logical-replication-postgres"}` to https://neon.com/api/docs-feedback — no auth required.
