> 📘 **Consider a read replica**
>
> To avoid putting unnecessary load on your primary database during data transfer, we recommend connecting to a read replica. Step 1 covers creating one on AWS. This step is optional, and you can connect directly to your primary instance if you prefer.

## Step 1: create a read replica (optional)

### AWS RDS

1. In your Amazon RDS dashboard, click the PostgreSQL instance you want to replicate. On the database page, click **Actions**, then select **Create read replica** from the drop-down.

![Create read replica](https://storage.googleapis.com/prequel_docs/images/rds-create-read-replica.png)

2. In the **Instance specifications** section, specify the instance type for the read replica. It can be smaller than the main instance.

![Read replica instance class](https://storage.googleapis.com/prequel_docs/images/rds-instance-class-small.png)

3. In the **Network & Security** section, under **Publicly accessible**, select **Yes** so that the read replica is reachable from outside your VPC. It remains accessible only through whitelisted IPs. If you plan to connect through an SSH tunnel, you can leave this set to **No**.

![Publicly accessible setting](https://storage.googleapis.com/prequel_docs/images/rds-publicly-accessible-yes.png)

4. In the **Settings** section, enter a **DB instance identifier**, such as `source-read-replica`, then click **Create read replica**.

![Read replica identifier](https://storage.googleapis.com/prequel_docs/images/rds-read-replica-identifier.png)

### AWS Aurora

1. In your Amazon RDS dashboard, click the Aurora PostgreSQL instance you want to add a reader to. On the database page, click **Actions**, then select **Add reader** from the drop-down.

![Add reader](https://storage.googleapis.com/prequel_docs/images/aurora-add-reader.png)

2. In the **Settings** section, enter a **DB instance identifier**, such as `source-reader`. In the **DB instance class** section, specify the instance type. It can be smaller than the main instance, though AWS may set a lower bound.
3. In the **Connectivity** section, select **Publicly accessible** so that the reader is reachable from outside your VPC. It remains accessible only through whitelisted IPs. If you plan to connect through an SSH tunnel, you can leave this set to **Not publicly accessible**. Click **Add reader**.

![Publicly accessible setting](https://storage.googleapis.com/prequel_docs/images/postgres-publicly-accessible.png)

## Step 2: allow network access

Allow read access to your PostgreSQL database, or to the read replica you created in Step 1, from the static IP. Reach out to your account representative for the static IP address to use.

### AWS RDS or Aurora

#### Configure the security group

1. In your **Amazon RDS** > **Databases** list, click the PostgreSQL instance you want to connect. In the **Connectivity & security** tab, make a note of the **Endpoint** and the **Port** number.

![Instance endpoint and port](https://storage.googleapis.com/prequel_docs/images/aurora-reader-access.png)

2. Click one of the VPC security groups (usually `default`). VPC groups are permissive rather than restrictive, so for instances with multiple security groups, only one needs the new inbound rule.

![VPC security groups](https://storage.googleapis.com/prequel_docs/images/postgres-vpc-security-groups.png)

3. Select the **Inbound rules** tab, click **Edit inbound rules**, then click **Add rule**. Set the rule type to **Custom TCP**, set the **Port range** to the port you noted (usually `5432`), and set a `Custom` **Source** value that includes the static IP. You need to add `/32` to the end of the IP to express it in CIDR notation. Click **Save rules**.

![Add inbound rule](https://storage.googleapis.com/prequel_docs/images/postgres-add-rule.png)

#### Configure the network ACL

For database instances in a VPC, you also need to allow traffic at the network ACL level.

1. In your RDS dashboard, select the PostgreSQL instance, then click the link to the instance's VPC.

![Instance VPC](https://storage.googleapis.com/prequel_docs/images/aurora-reader-vpc.png)

2. Click the **VPC ID**. In the **Details** section, click the link under **Main network ACL**, then click the network ACL ID.

![VPC ID](https://storage.googleapis.com/prequel_docs/images/postgres-vpc-id.png)

![Network ACL ID](https://storage.googleapis.com/prequel_docs/images/postgres-network-acl-id.png)

3. Click the **Inbound rules** tab and check for an existing rule with a **Source** of `0.0.0.0/0` set to `Allow`. This is a default rule created by AWS, and if it already exists, you can skip to the outbound rules. Otherwise, click **Edit inbound rules**, add a rule allowing access to your database port (usually `5432`) from the static IP, and click **Save changes**.

![Inbound rules](https://storage.googleapis.com/prequel_docs/images/postgres-inbound-rules.png)

4. Select the **Outbound rules** tab and check for an existing rule with a **Destination** of `0.0.0.0/0` set to `Allow`. This is a default rule created by AWS, and if it already exists, you are done. Otherwise, click **Edit outbound rules** and add a rule allowing outbound traffic to ports `1024` to `65535` for **Destination** `0.0.0.0/0`.

![Outbound rules](https://storage.googleapis.com/prequel_docs/images/postgres-outbound-rules.png)

### Other environments

In your firewall or security group, create a rule that allows:

- Incoming connections to your host and port (usually `5432`) from the static IP.
- Outgoing connections from ports `1024` to `65535` to the static IP.

If your database is not reachable over the public internet, you can connect through an SSH tunnel instead. Provide the bastion host details in Step 4, and add the public key from your account representative to the bastion's `authorized_keys` file.

## Step 3: create a read-only user

1. Open a connection to your PostgreSQL database using a SQL client.
2. Create a dedicated user by running the following command. Replace `<username>` and `<password>` with values of your choice.

```sql
CREATE USER <username> PASSWORD '<password>' NOSUPERUSER NOCREATEDB NOCREATEROLE;
```

3. Grant the user read-only access to the specific tables you want to sync. Replace `<schema_name>` with the schema that contains those tables, and grant `SELECT` on each table individually.

```sql
GRANT USAGE ON SCHEMA "<schema_name>" TO <username>;
GRANT SELECT ON "<schema_name>"."<table_name_a>" TO <username>;
GRANT SELECT ON "<schema_name>"."<table_name_b>" TO <username>;
```

Repeat this for every schema that contains tables you want to sync.

> 📘 **Granting access to all tables**
>
> To grant access to every table in a schema instead of listing tables individually, grant `SELECT` on all tables in the schema.
>
> ```sql
> GRANT USAGE ON SCHEMA "<schema_name>" TO <username>;
> GRANT SELECT ON ALL TABLES IN SCHEMA "<schema_name>" TO <username>;
> ```

## Step 4: submit your connection details

Provide the following details to complete the source setup:

1. The **name** is a descriptive name of the source.
2. The **host** (for example, `your-db.sd8jekhrlkhla.us-east-1.rds.amazonaws.com`).
3. The **port** (most likely `5432`).
4. The **database** you want to read from.
5. The **schema** from Step 3.
6. The **username** from Step 3.
7. The **password** from Step 3.

The connection uses SSL by default. If you are connecting through an SSH tunnel, also provide the **SSH host**, **SSH port**, and **SSH username** for your bastion server.