# Connection Pooling for Render Postgres


> *Render Postgres now supports integrated connection pooling with PgBouncer.*
>
> Previously, this guide described manually configuring and deploying PgBouncer as a standalone Render service. It has been updated to use integrated connection pooling.

If your Render Postgres database requires more simultaneous connections than its [compute plan](compute-plans?tab=postgres#all-plans) allows, you can enable *connection pooling* for it at no additional cost. When enabled, Render runs [PgBouncer](https://www.pgbouncer.org/) in front of your database to manage its connection volume:

```mermaid
flowchart LR
  clientA[Client A]
  clientB[Client B]
  subgraph "<b>Host machine</b>"
    pgb{{<b>PgBouncer</b>}}
    db[("Render<br/>Postgres")]
  end

  clientA edge1@-->|<code>:6432</code>| pgb;
  clientB edge2@-->|<code>:6432</code>| pgb;

  pgb edge3@==>|<code>:5432</code>| db;

  edge1@{animation: slow}
  edge2@{animation: slow}
  edge3@{animation: slow}

  class pgb success;
```

With this setup, you [update your clients](#2-update-your-client-connections) to connect to PgBouncer instead of connecting directly to your database. PgBouncer maintains a pool of reusable connections to handle queries from thousands of clients.

PgBouncer runs on the same underlying host as the database itself, minimizing the latency introduced by this additional hop. Clients that require session-level state or a dedicated long-lived connection can continue [connecting directly](#when-to-connect-directly).

> *Connection pooling is not available for [free databases](free#free-postgres).*

## Should I enable connection pooling?

*It depends.* A connection pool is most commonly useful in the following cases:

- Your database's connection limit is too low for your number of concurrent clients.
- Your database consistently receives surges of short-lived connections from bursty workloads (such as from Render Workflows).
    - In this case, pooling helps minimize connection management overhead on your database.

Outside of these cases, most databases _don't_ benefit meaningfully from a connection pool.

If you do enable connection pooling, some clients might still need to [connect directly](#when-to-connect-directly) to your database.

### When to connect directly

Render-managed PgBouncer uses *transaction-level pooling* (`pool_mode = transaction`). This means that clients requiring _session-level_ state or a dedicated long-lived connection should continue connecting directly to your database.

*Connect directly if your client uses any of the following:*

- Custom session variables (`SET SESSION …`)
- Temporary tables (`CREATE TEMPORARY TABLE …`)
- `LISTEN`/`NOTIFY`
- Session-level [advisory locks](https://www.postgresql.org/docs/current/explicit-locking.html#ADVISORY-LOCKS)

*If a significant percentage of your clients require the above features, _do not_ enable connection pooling.*

## Setup

### 1. Enable connection pooling

> *This step requires a database restart, unless you've enabled [high availability](postgresql-high-availability).*
>
> - During a restart, your database is unavailable for a few minutes.
> - If you've enabled high availability, your database instead is unavailable for a few seconds (during the failover process).
>
> Schedule activation of this feature accordingly.

Enable connection pooling for your database using any method listed below:

**Tab: Dashboard**

1. In the [Render Dashboard](https://dashboard.render.com), go to your database's *Info* page and scroll down to *General > Connection Pool*:

    [image: Render Postgres Connection Pool Disabled Screenshot]

2. Toggle the switch.

    A confirmation modal appears:

    [image: Render Postgres Connection Pool Enable Modal Screenshot]

3. Confirm your action and click *Enable connection pool*.

Render immediately triggers a database restart or HA failover to initialize the connection pool.

**Tab: Blueprint (render.yaml)**

If you manage your database with [Render Blueprints](infrastructure-as-code), add the following line to its configuration in your Blueprint file:

```yaml
databases:
  - name: my-db
    plan: basic-256mb
    connectionPool: pgbouncer # highlight-line
```

The next time you sync your Blueprint, Render triggers a database restart or HA failover to initialize the connection pool.

**Tab: CLI**

Enable connection pooling using the Render CLI's [`pg update` command](cli-reference#pg-update). Set the `--connection-pool` flag to `pgbouncer`:

```shell
render pg update my-database --connection-pool pgbouncer
```

Render immediately triggers a database restart or HA failover to initialize the connection pool.

**Tab: API**

Using the [Render API](api), enable connection pooling with a request to the [Update Postgres instance](https://api-docs.render.com/reference/update-postgres/) endpoint.

In your request body, set `connectionPool` to `pgbouncer`:

```json
{
  "connectionPool": "pgbouncer"
}
```

Render immediately triggers a database restart or HA failover to initialize the connection pool.

*Existing clients are not yet using the connection pool!* You'll update them next.

### 2. Update your client connections

After your database finishes restarting, it has two new *connection pool URLs*, one for internal connections and one for external connections. You can view these URLs on your database's *Info* page in the [Render Dashboard](https://dashboard.render.com):

[image: Copying a connection pool URL in the Render Dashboard]

These URLs are _almost_ identical to your database's _direct_ connection URLs, with one difference: they use the PgBouncer port `6432` instead of defaulting to the standard PostgreSQL port `5432`.

Update each of your clients with the relevant URL for its connection type. For your other Render services, this almost always involves updating an environment variable. See the most common update methods:

**Tab: Dashboard**

1. In the [Render Dashboard](https://dashboard.render.com), go to your service's *Environment* page and scroll down to *Environment Variables*.
2. Click *Edit*.
3. Find the environment variable containing your database's connection URL (most commonly `DATABASE_URL`).
4. Update the value of the environment variable to the new connection pool URL.

    - Make sure to use the connection URL that corresponds to the existing connection type (internal / external).

5. Click the dropdown arrow next to *Save only* and select *Save and deploy*.

Render redeploys your service with the updated environment variable.

**Tab: Blueprint (render.yaml)**

[Blueprints](infrastructure-as-code) support dynamically setting a service's environment variable to the value of a database's internal connection pool URL:

```yaml
services:
  - type: pserv
    name: pgadmin
    runtime: docker
    plan: 1c-2g
    repo: https://github.com/render-examples/pgadmin
    envVars:
    - key: DATABASE_URL
      fromDatabase:
        name: my-db
        property: connectionPoolString
```

For details on this syntax, see [Blueprint YAML reference](blueprint-spec#referencing-service-properties).

Apply the necessary changes and sync your Blueprint. Render redeploys your service with the updated environment variable.

**Tab: API**

Using the [Render API](api), update the environment variable your client uses for database connections with the [Add or update environment variable](https://api-docs.render.com/reference/update-env-var) endpoint.

In your request body, set `value` to the new connection URL:

```json
{
  "value": "postgresql://USER:PASSWORD@DATABASE_HOST:6432/DATABASE"
}
```

## Default configuration

Render uses the following default configuration for PgBouncer:

> *Does your use case require custom PgBouncer configuration?*
>
> Please reach out to our support team in the [Render Dashboard](https://dashboard.render.com?contact-support).

| Setting | Value | Details |
| --- | --- | --- |
| [`pool_mode`](https://www.pgbouncer.org/config.html#pool_mode) | `transaction` | Because connections are assigned per-transaction, _session_-level features like advisory locks and `LISTEN/NOTIFY` require [connecting directly](#when-to-connect-directly). |
| [`max_client_conn`](https://www.pgbouncer.org/config.html#max_client_conn) | `30000` | This is the maximum number of simultaneous connections PgBouncer accepts from clients, _not_ the number of connections it maintains to your database. |
| [`max_db_connections`](https://www.pgbouncer.org/config.html#max_db_connections) / [`default_pool_size`](https://www.pgbouncer.org/config.html#default_pool_size) | `max_connections` minus 10 | Render Postgres reserves 10 connections for [direct database connections](#when-to-connect-directly) and internal operations. |
| [`client_idle_timeout`](https://www.pgbouncer.org/config.html#client_idle_timeout) | `86400` (1 day in seconds). | PgBouncer closes idle client connections after this duration. |
| [`server_login_retry`](https://www.pgbouncer.org/config.html#server_login_retry) | `2` (seconds) | If PgBouncer fails to connect to your database, it waits this long before retrying. |
| PgBouncer port | `6432` | _Direct_ database connections continue to use port `5432`. Only connections through PgBouncer use this port. |

## Monitoring pool activity

If your workspace [streams metrics](metrics-streams) to an observability provider, Render reports `render.postgres.connection.pool.*` metrics for each database with connection pooling enabled. Use these metrics to detect pool saturation: for example, [`render.postgres.connection.pool.client.waiting`](metrics-streams-reference#render-postgres-connection-pool-client-waiting) reports the number of clients waiting for an available connection.

For the full list of reported metrics, see the [Render OpenTelemetry Metrics Reference](metrics-streams-reference#render-postgres).

## FAQ

###### Can I enable connection pooling for a free database?

No. Connection pooling requires a paid compute plan.

###### Can I enable connection pooling for my database's read replicas?

If you enable connection pooling for a primary database, Render automatically enables it for all of that database's [read replicas](postgresql-read-replicas).

Each read replica has its own independent connection pool. You can't toggle connection pooling for a replica independently of its primary.

###### How does connection pooling work with high availability?

If you enable connection pooling for a primary database, Render automatically enables it for that database's [high availability standby](postgresql-high-availability) (if it has one).

In the event of a failover, the standby becomes the new primary, and clients start using its connection pool immediately upon reconnecting.

###### If I enable connection pooling, are all my database's clients required to use it?

No. Render Postgres reserves a small number of connections for direct database connections and internal operations. Clients with [specific requirements](#when-to-connect-directly) can continue connecting directly using the database's internal or external URL.

If a significant percentage of your clients require a direct connection, do not enable connection pooling.

###### Can I customize my database's PgBouncer configuration?

Not directly. If your use case requires custom PgBouncer configuration, please reach out to our support team in the [Render Dashboard](https://dashboard.render.com?contact-support).


---

##### Appendix: Glossary definitions

###### Render Postgres

Fully managed PostgreSQL databases that support point-in-time recovery, read replicas, high availability, and more.

Related article: https://render.com/docs/postgresql.md

###### Render Workflows

Define collections of long-running *tasks* that execute across distributed compute.

Ideal for agents, ETL pipelines, and background jobs.

Related article: https://render.com/docs/workflows.md

###### failover

The process of swapping a Render Postgres primary database for its high availability standby, most commonly because the primary becomes unavailable.

The failover process completes in a few seconds.

Related article: https://render.com/docs/postgresql-high-availability.md#failover

###### environment variable

Config values you can apply to a service to customize its behavior at build and runtime, such as `NODE_VERSION` or `OPENAI_API_KEY`.

Render sets some environment variables for your service by [default](environment-variables).

Related article: https://render.com/docs/configure-environment-variables.md