> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prequel.co/llms.txt
> Use this file to discover all available pages before exploring further.

# PostgreSQL

> Connect your PostgreSQL database as a source

<Note>
  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.
</Note>

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

<Tabs>
  <Tab title="AWS RDS">
    <Steps>
      <Step title="Create the read replica">
        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.

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

      <Step title="Choose an instance size">
        In the **Instance specifications** section, specify the instance type for the read replica. It can be smaller than the main instance.

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

      <Step title="Make the replica reachable">
        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**.

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

      <Step title="Name and create the replica">
        In the **Settings** section, enter a **DB instance identifier**, such as `source-read-replica`, then click **Create read replica**.

        <Frame>
          ![Read replica identifier](https://storage.googleapis.com/prequel_docs/images/rds-read-replica-identifier.png)
        </Frame>
      </Step>
    </Steps>
  </Tab>

  <Tab title="AWS Aurora">
    <Steps>
      <Step title="Add a reader">
        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.

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

      <Step title="Name and size the reader">
        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.
      </Step>

      <Step title="Make the reader reachable">
        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**.

        <Frame>
          ![Publicly accessible setting](https://storage.googleapis.com/prequel_docs/images/postgres-publicly-accessible.png)
        </Frame>
      </Step>
    </Steps>
  </Tab>
</Tabs>

## 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.

<Tabs>
  <Tab title="AWS RDS or Aurora">
    ### Configure the security group

    <Steps>
      <Step title="Note the endpoint and port">
        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.

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

      <Step title="Open the VPC security group">
        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.

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

      <Step title="Add an inbound rule">
        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**.

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

    ### Configure the network ACL

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

    <Steps>
      <Step title="Open the VPC">
        In your RDS dashboard, select the PostgreSQL instance, then click the link to the instance's VPC.

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

      <Step title="Open the main network ACL">
        Click the **VPC ID**. In the **Details** section, click the link under **Main network ACL**, then click the network ACL ID.

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

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

      <Step title="Edit the inbound rules">
        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**.

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

      <Step title="Edit the outbound rules">
        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`.

        <Frame>
          ![Outbound rules](https://storage.googleapis.com/prequel_docs/images/postgres-outbound-rules.png)
        </Frame>
      </Step>
    </Steps>
  </Tab>

  <Tab title="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.
  </Tab>
</Tabs>

## Step 3: create a read-only user

<Steps>
  <Step title="Connect to your database">
    Open a connection to your PostgreSQL database using a SQL client.
  </Step>

  <Step title="Create the user">
    Create a dedicated user by running the following command. Replace `<username>` and `<password>` with values of your choice.

    ```sql title="Create user" icon="database" theme={null}
    CREATE USER <username> PASSWORD '<password>' NOSUPERUSER NOCREATEDB NOCREATEROLE;
    ```
  </Step>

  <Step title="Grant read-only access">
    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 title="Grant table access" icon="database" expandable theme={null}
    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.

    <Note>
      To grant access to every table in a schema instead of listing tables individually, grant `SELECT` on all tables in the schema.

      ```sql title="Grant all tables" icon="database" theme={null}
      GRANT USAGE ON SCHEMA "<schema_name>" TO <username>;
      GRANT SELECT ON ALL TABLES IN SCHEMA "<schema_name>" TO <username>;
      ```
    </Note>
  </Step>
</Steps>

## 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.
