## 1. Project Overview & Quickstart (pgdogdev/pools)

# pools

Open-source repository pgdogdev/pools

### Repository Details
- **Repository:** [pgdogdev/pools](https://github.com/pgdogdev/pools)
- **Primary Language:** Code

*Note: High-volume repository documentation is actively indexed and synchronized by YakaAI.*

## 2. Official Technical Reference & Guides (pgdogdev/docs)

## File: docs/administration/clients.md

---
icon: material/account-multiple
---

# Client connections

PgDog provides real time statistics and information on all client connections. They can be accessed by connecting to the [admin database](index.md) and running the `SHOW CLIENTS` command:

```
SHOW CLIENTS;
```

The following information is returned for each client connection to PgDog:

| Name | Description | Example |
|------|-------------|---------|
| `user` | User name the client is connected as. | `admin` |
| `database` | Database name the client is connected to. | `admin` |
| `addr` | IP address of the client. | `127.0.0.1` |
| `port` | TCP port client is connected from. | `53002` |
| `state` | Real time client state, e.g. `active`, `idle`, etc. | `idle` |
| `replication` | Replication mode if applicable. | `none` |
| `connect_time` | Timestamp when the client connected. | `2025-09-17 19:56:16.981 -07:00` |
| `last_request` | Timestamp of the last request from this client. | `2025-09-17 20:09:49.799 -07:00` |
| `queries` | Number of queries executed. | `2` |
| `transactions` | Number of completed transactions executed. | `2` |
| `transactions_2pc` | Number of two-phase commit transactions. | `0` |
| `wait_time` | How long the client had to wait to get a connection from the pool. This value increases monotonically if the client is waiting for a pool that's too busy to serve transactions. | `0` |
| `query_time` | Total time this client's queries took to run on a server. | `7.334` |
| `transaction_time` | Total time this client's transactions took to execute on the server, including idle in transaction time. | `7.340` |
| `bytes_received` | Number of bytes received over the network from the client. | `36` |
| `bytes_sent` | Number of bytes sent over the network to the client. | `12470` |
| `errors` | Number of errors the client has received, e.g. query syntax errors. | `0` |
| `application_name` | Application name set by the client. | `psql` |
| `memory_used` | Amount of memory used by this client connection (in bytes). | `2397` |
| `locked` | Whether the client connection is locked. | `f` |
| `prepared_statements` | Number of prepared statements created by this client. | `0` |

---

## File: docs/administration/config.md

---
icon: material/cog
---

# Configuration

PgDog provides real time access to its current configuration values. They can be accessed by connecting to the [admin database](index.md) and running the `SHOW CONFIG` command:

```
SHOW CONFIG;
```

The following configuration parameters are available and their current values:

| Name | Example |
|------|---------|
| `auth_type` [:material-link:](../configuration/pgdog.toml/general.md#auth_type) | `scram` |
| `ban_timeout` [:material-link:](../configuration/pgdog.toml/general.md#ban_timeout) | `5m` |
| `checkout_timeout` [:material-link:](../configuration/pgdog.toml/general.md#checkout_timeout) | `1s` |
| `client_idle_timeout` [:material-link:](../configuration/pgdog.toml/general.md#client_idle_timeout) | `18446744073709551615ms` |
| `connect_attempt_delay` [:material-link:](../configuration/pgdog.toml/general.md#connect_attempt_delay) | `0ms` |
| `connect_attempts` [:material-link:](../configuration/pgdog.toml/general.md#connect_attempts) | `1` |
| `connect_timeout` [:material-link:](../configuration/pgdog.toml/general.md#connect_timeout) | `1s` |
| `cross_shard_disabled` | `false` |
| `default_pool_size` [:material-link:](../configuration/pgdog.toml/general.md#default_pool_size) | `10` |
| `dns_ttl` | `default` |
| `dry_run` [:material-link:](../configuration/pgdog.toml/general.md#dry_run) | `false` |
| `healthcheck_interval` [:material-link:](../configuration/pgdog.toml/general.md#healthcheck_interval) | `30s` |
| `healthcheck_timeout` | `5s` |
| `host` [:material-link:](../configuration/pgdog.toml/general.md#host) | `0.0.0.0` |
| `idle_healthcheck_delay` [:material-link:](../configuration/pgdog.toml/general.md#idle_healthcheck_delay) | `5s` |
| `idle_healthcheck_interval` [:material-link:](../configuration/pgdog.toml/general.md#idle_healthcheck_interval) | `30s` |
| `idle_timeout` [:material-link:](../configuration/pgdog.toml/general.md#idle_timeout) | `1m` |
| `load_balancing_strategy` [:material-link:](../configuration/pgdog.toml/general.md#load_balancing_strategy) | `round_robin` |
| `log_connections` [:material-link:](../configuration/pgdog.toml/general.md#log_connections) | `true` |
| `log_disconnections` [:material-link:](../configuration/pgdog.toml/general.md#log_disconnections) | `true` |
| `min_pool_size` [:material-link:](../configuration/pgdog.toml/general.md#min_pool_size) | `1` |
| `mirror_exposure` [:material-link:](../configuration/pgdog.toml/general.md#mirror_exposure) | `1.0` |
| `mirror_queue` [:material-link:](../configuration/pgdog.toml/general.md#mirror_queue) | `128` |
| `openmetrics_namespace` [:material-link:](../configuration/pgdog.toml/general.md#openmetrics_namespace) | `pgdog_` |
| `openmetrics_port` [:material-link:](../configuration/pgdog.toml/general.md#openmetrics_port) | `9090` |
| `passthrough_auth` [:material-link:](../configuration/pgdog.toml/general.md#passthrough_auth) | `disabled` |
| `pooler_mode` [:material-link:](../configuration/pgdog.toml/general.md#pooler_mode) | `transaction` |
| `port` [:material-link:](../configuration/pgdog.toml/general.md#port) | `6432` |
| `prepared_statements` [:material-link:](../configuration/pgdog.toml/general.md#prepared_statements) | `extended` |
| `prepared_statements_limit` [:material-link:](../configuration/pgdog.toml/general.md#prepared_statements_limit) | `500` |
| `pub_sub_channel_size` [:material-link:](../configuration/pgdog.toml/general.md#pub_sub_channel_size) | `4098` |
| `query_cache_limit` | `500` |
| `query_log` | `default` |
| `query_timeout` [:material-link:](../configuration/pgdog.toml/general.md#query_timeout) | `1s` |
| `read_write_split` [:material-link:](../configuration/pgdog.toml/general.md#read_write_split) | `include_primary` |
| `read_write_strategy` | `aggressive` |
| `rollback_timeout` [:material-link:](../configuration/pgdog.toml/general.md#rollback_timeout) | `1s` |
| `shutdown_timeout` [:material-link:](../configuration/pgdog.toml/general.md#shutdown_timeout) | `1m` |
| `tls_certificate` [:material-link:](../configuration/pgdog.toml/general.md#tls_certificate) | `default` |
| `tls_private_key` [:material-link:](../configuration/pgdog.toml/general.md#tls_private_key) | `default` |
| `tls_server_ca_certificate` [:material-link:](../configuration/pgdog.toml/general.md#tls_server_ca_certificate) | `default` |
| `tls_verify` [:material-link:](../configuration/pgdog.toml/general.md#tls_verify) | `prefer` |
| `two_phase_commit` [:material-link:](../configuration/pgdog.toml/general.md#two_phase_commit) | `false` |
| `two_phase_commit_auto` [:material-link:](../configuration/pgdog.toml/general.md#two_phase_commit_auto) | `default` |
| `workers` [:material-link:](../configuration/pgdog.toml/general.md#workers) | `2` |
| `tcp_congestion_control` | `default` |
| `tcp_interval` | `default` |
| `tcp_keepalive` | `true` |
| `tcp_retries` | `default` |
| `tcp_time` | `default` |
| `tcp_user_timeout` | `default` |

---

## File: docs/administration/index.md

---
icon: material/monitor-dashboard
---

# Administration overview

PgDog keeps track of clients, servers and connection pools. It provides real time statistics on its internal operations for system
administrators to keep track of and integrate with monitoring tools like Datadog.

Just like pgbouncer, PgDog has a special "admin" database clients can connect to and run custom SQL commands
to get statistics.

## Admin database

The admin database name is [configurable](../configuration/pgdog.toml/admin.md). By default, the database is called `admin`. It supports a number of commands, documented below.

### Commands

| Command | Description |
|---------|-------------|
| [`SHOW CLIENTS`](clients.md) | Clients connected to PgDog with real time statistics. |
| [`SHOW SERVERS`](servers.md) | Server connections made by PgDog to PostgreSQL. |
| [`SHOW POOLS`](pools.md) | Connection pools used to multiplex clients and servers. |
| [`SHOW CONFIG`](config.md) | Currently loaded values from `pgdog.toml`. |
| `SHOW STATS` | Connection pools statistics. |
| `SHOW PEERS` | List of PgDog processes running on the same network. Requires service discovery to be enabled. |
| `RELOAD` | Reload configuration from disk. See [pgdog.toml](../configuration/pgdog.toml/general.md) and [users.toml](../configuration/users.toml/users.md) for which options can be changed at runtime. |
| `FORCE_RELOAD` | Reload configuration from disk and terminates any in-flight transactions. Guarantees that all transactions following the completion of this command are sent to the new connection pools. |
| `RECONNECT` | Re-create all server connections using existing configuration. |
| `PAUSE` | Pause all pools. Clients will wait for connections until pools are resumed. Can be used for gracefully restarting PostgreSQL servers. |
| `RESUME` | Resume all pools. Clients are able to check out connections again. |
| `SHOW PREPARED` | List prepared statements currently in the cache. |
| `SHOW QUERY_CACHE` | List statements currently in the AST cache used for query routing. |
| [`MAINTENANCE`](maintenance_mode.md) | Pause all queries to synchronize configuration changes across multiple instances of PgDog. |
| [`SHOW REPLICATION`](replication.md) | Show the status of PostgreSQL replication for each database, including replica lag. |
| [`RESHARD`](../features/sharding/resharding/index.md) | Reshard a database online and cut over traffic automatically. Returns a background `task_id`. |
| [`COPY_DATA`](../features/sharding/resharding/move.md) | Copy and reshard data to a destination cluster, then stream changes. Returns a background `task_id`. |
| [`SCHEMA_SYNC`](../features/sharding/resharding/schema.md) | Synchronize schema for a given phase between source and destination. Returns a background `task_id`. |
| `REPLICATE` | Stream changes from source to destination (schema and data must already be synced). Returns a background `task_id`. |
| [`CUTOVER`](../features/sharding/resharding/cutover.md) | Cut traffic over to the destination cluster for a running replication task. |
| [`SHOW TASKS`](tasks.md) | List background tasks (resharding, copy, replication, schema sync) with their status and elapsed time. |
| [`STOP_TASK`](tasks.md#stopping-a-task) | Stop a running background task by its `task_id`. |

## Shutting down PgDog

When you need to shutdown PgDog, e.g. to deploy a new version, you can do so gracefully by issuing `SIGINT` (e.g. Ctrl-C) to the `pgdog` process.
PgDog will stop listening for new connections and give connected clients some time to finish their transactions and disconnect.

The amount of time PgDog will wait is [configurable](../configuration/pgdog.toml/general.md#shutdown_timeout). By default, PgDog will wait 60 seconds.

#### Example

```
$ pkill pgdog -SIGINT
```

---

## File: docs/administration/maintenance_mode.md

---
icon: material/wrench
---

# Maintenance mode

Maintenance mode pauses queries from all clients so you can synchronize configuration changes across multiple instances of PgDog. This is useful if you're changing the [sharding](../features/sharding/index.md) options.

### How it works

You can turn on maintenance mode by connecting to the [admin](index.md) database and running this query:

```
MAINTENANCE ON;
```

Clients that are currently executing a transaction will be allowed to finish, while all others will be immediately paused. Pausing traffic has the effect of holding query requests inside PgDog's network buffer. To the client, this will seem like the proxy isn't responding.

!!! note
    Before enabling maintenance mode, make sure to set the application-level timeouts high enough as to avoid erroring out.

During maintenance mode, you can perform live configuration changes. The following flow is typical and, if performed quickly, won't cause errors or downtime:

1. Make changes to `pgdog.toml` and/or `users.toml`
2. Enable maintenance mode
3. Reload config on all instances of PgDog
4. Disable maintenance mode

#### Turn off maintenance mode

Turning off maintenance mode and resuming all queries can be done with a query:

```
MAINTENANCE OFF;
```

---

## File: docs/administration/pools.md

---
icon: material/pool
---

# Connection pools

PgDog provides real time statistics and information on its connection pools. You can view them by connecting to the [admin database](index.md) and running the `SHOW POOLS` command:

```
SHOW POOLS;
```

The following information is returned for each connection pool (user/database pair) managed by PgDog:

| Name | Description | Example |
|------|-------------|---------|
| `id` | Pool identifier. | `1` |
| `database` | Name of the PostgreSQL database. | `myapp_prod` |
| `user` | User used to connect to the database. | `app_user` |
| `addr` | IP address or DNS name of the PostgreSQL server. | `10.0.1.5` |
| `port` | TCP port of the PostgreSQL server. | `5432` |
| `shard` | Shard identifier. | `0` |
| `role` | Database role. | `primary` |
| `cl_waiting` | Number of clients waiting for a connection from this pool. | `3` |
| `sv_idle` | Number of idle server connections in the pool. | `8` |
| `sv_active` | Number of checked out (used) server connections in the pool. | `12` |
| `sv_idle_xact` | Number of idle-in-transaction server connections in the pool. | `0` |
| `sv_total` | Total number of server connections in the pool. | `20` |
| `maxwait` | How long the first (oldest) client in the queue has waited, in seconds. | `30` |
| `maxwait_us` | Microsecond part of the `maxwait` value. | `30000000` |
| `pool_mode` | Connection pooling mode. | `transaction` |
| `paused` | The pool is paused and won't issue connections until resumed. | `f` |
| `banned` | The pool is blocked from serving more clients. | `f` |
| `errors` | Number of connections returned to the pool in a bad state, e.g. network connectivity broken. | `0` |
| `re_synced` | Number of connections that have been re-synchronized. | `2` |
| `out_of_sync` | Number of connections returned to the pool by clients that left it in a bad state, e.g. by issuing a query and not waiting for the result. | `0` |
| `online` | Whether the pool is online. | `t` |
| `replica_lag` | Replication lag for replica connections. | `0` |
| `schema_admin` | Whether this connection pool is used for schema synchronization. | `f` |

---

## File: docs/administration/replication.md

---
icon: material/content-copy
---

# Replication

PgDog provides a real time view into PostgreSQL replication for the purposes of monitoring [replication delay](../features/load-balancer/replication-failover.md#replication) and performing query traffic [failover](../features/load-balancer/replication-failover.md#failover).

You can view this data by connecting to the [admin](index.md) database and running this query:

```
SHOW REPLICATION;
```

The following information is returned for each database:

| Name | Description | Example |
|------|-------------|---------|
| `id` | Connection pool identifier matching pools in [`SHOW POOLS`](pools.md). | `4` |
| `database` | Name of the PostgreSQL database. | `postgres` |
| `user` | User used to connect to the database. | `postgres` |
| `addr` | IP address or DNS name of the server. | `127.0.0.1` |
| `port` | TCP port of the server. | `45001` |
| `shard` | Shard number of the database. | `0` |
| `role` | Database role, either `primary` or `replica`. | `replica` |
| `replica_lag` | Replication lag in milliseconds. | `0` |
| `pg_lsn` | Current LSN (Log Sequence Number) of the database. | `0/21000168` |
| `lsn_age` | Time since the last transaction in milliseconds. | `2245` |
| `pg_is_in_recovery` | Whether the database is in recovery mode (`t` = true, `f` = false). | `t` |

---

## File: docs/administration/servers.md

---
icon: material/server
---

# Server connections

PgDog provides real time statistics and information on all connections to PostgreSQL databases. They can be accessed by connecting to the [admin database](index.md) and running the `SHOW SERVERS` command:

```
SHOW SERVERS;
```

The following information is returned for each connection from PgDog to a PostgreSQL database:

| Name | Description | Example |
|------|-------------|---------|
| `database` | Name of the PostgreSQL database. | `shard_0` |
| `user` | User used to connect to the database. | `pgdog` |
| `addr` | IP address or DNS name of the server. | `localhost` |
| `port` | TCP port of the server. | `5432` |
| `state` | Server connection state, e.g. `active`, `idle in transaction`, etc. | `receiving data` |
| `connect_time` | Timestamp when the connection was established. | `2025-09-17 19:55:37.958 -07:00` |
| `request_time` | Timestamp of the last request on this connection. | `2025-09-17 19:55:37.965 -07:00` |
| `remote_pid` | Process ID of the PostgreSQL backend process. | `1384` |
| `transactions` | Number of transactions completed by this server connection. | `1` |
| `queries` | Number of queries executed by this server connection. | `1` |
| `rollbacks` | Number of automatic rollbacks executed on this server connection by PgDog to clean up after idle transactions left by clients. | `0` |
| `prepared_statements` | Number of prepared statements created on this server connection. | `0` |
| `healthchecks` | Number of healthchecks executed on this server connection. | `0` |
| `errors` | Number of errors this connection has produced e.g. syntax errors. | `0` |
| `bytes_received` | Number of bytes received over the network. | `60` |
| `bytes_sent` | Number of bytes sent over the network. | `56` |
| `age` | How long ago this connection was created (in ms). | `851` |
| `application_name` | Application name set by the client connection. | `PgDog Pub/Sub Listener` |
| `memory_used` | Amount of memory used by this connection (in bytes). | `1787` |

---

## File: docs/administration/tasks.md

---
icon: material/format-list-checks
---

# Background tasks

Long-running operations like [resharding](../features/sharding/resharding/index.md) don't block the connection that started them. Instead, `RESHARD`, `COPY_DATA`, `REPLICATE`, and `SCHEMA_SYNC` each return a `task_id` and run in the background. `SHOW TASKS` is how you track those tasks: it reports their lifecycle status and progress, lets you find the `task_id` to pass to [`STOP_TASK`](#stopping-a-task) or [`CUTOVER`](../features/sharding/resharding/cutover.md), and surfaces failures.

Run it on the [admin database](index.md):

```
SHOW TASKS;
```

!!! note "Admin database tasks only"
    `SHOW TASKS` lists the background tasks running inside the same PgDog process. The equivalent [CLI commands](../features/sharding/resharding/index.md#running-the-steps-manually) (`pgdog data-sync`, `pgdog schema-sync`) spawn their own process in the foreground instead, and block until they finish or are stopped with `SIGINT` (or `SIGTERM`).

=== "Output"
    ```
    -[ RECORD 1 ]+----------------------------------
     id           | 14
     scope        | root
     type         | reshard prod -> prod_sharded
     status       | running
     inner_status | syncing data
     started_at   | 2026-06-30 18:02:11.004 UTC
     updated_at   | 2026-06-30 18:05:42.119 UTC
     elapsed      | 00:03:31:115
     elapsed_ms   | 211115
    -[ RECORD 2 ]+----------------------------------
     id           |
     scope        | subtask
     type         | copy_data prod -> prod_sharded
     status       | running
     inner_status |
     started_at   | 2026-06-30 18:02:30.550 UTC
     updated_at   | 2026-06-30 18:05:42.119 UTC
     elapsed      | 00:03:11:569
     elapsed_ms   | 191569
    ```

Tasks are ordered by creation date, starting at the oldest.

## Columns

| Column | Description |
|-|-|
| `id` | The task ID. This is the handle you pass to [`STOP_TASK`](#stopping-a-task) and [`CUTOVER`](../features/sharding/resharding/cutover.md). Only root tasks have an ID; subtasks share their parent's ID and leave this column empty. |
| `scope` | `root` for a top-level task, `subtask` for a step it spawned (e.g. the `copy_data` and `replication` steps of a `reshard`). |
| `type` | What the task is, usually with the source and destination databases, e.g., `reshard`, `copy_data`, `replication`, `replication [...] (reverse)`, `schema_sync(pre)`. |
| `status` | The lifecycle status of the task. See [Statuses](#statuses). |
| `inner_status` | Fine-grained progress within the current status. See [Progress](#progress). For a finished or failed task, this shows the last progress it reported. |
| `started_at` | When the task started. |
| `updated_at` | When the task last changed status or progress. For a finished task this is when it finished. |
| `elapsed` / `elapsed_ms` | How long the task ran. For a completed task this is the total run time (measured to `updated_at`). |

## Statuses

The `status` column describes where the task is in its lifecycle:

| Status | Meaning |
|-|-|
| `started` | The task is being set up. |
| `running` | The task is actively working. |
| `cancelling` | A [`STOP_TASK`](#stopping-a-task) was requested and the task is winding down cooperatively. |
| `finished` | The task completed successfully. |
| `cancelled` | The task was stopped before completing. |
| `failed: <error>` | The task errored. The error message is included in the status. |
| `panicked: <error>` | The task hit an unexpected internal error. |

`finished`, `cancelled`, `failed`, and `panicked` are terminal. Terminal tasks stay listed with their final status (and last progress) for a while so you can inspect the outcome, then they're pruned automatically.

## Progress

The `inner_status` column shows what the task is doing within its current `status`. The values depend on the task `type`:

| Task | Progress values |
|-|-|
| `reshard` | `syncing schema` → `syncing data` → `finalizing schema` → `replicating` |
| `copy_data` | (no sub-status; track copy progress with [`SHOW TABLE_COPIES`](../features/sharding/resharding/move.md#monitoring-progress)) |
| `replication` | `replicating` → `cutting over` (or `rolling back` for a reverse stream) / `stopping` |
| `schema_sync` | `loading schema` → `syncing tables` → `creating indexes` (or `syncing cutover schema`) |

## Finding the right ID

`STOP_TASK` and `CUTOVER` always operate on the parent ID:

- A `RESHARD` or `COPY_DATA` shows as a `root` task with its child steps listed as `subtask` rows. Target the root ID, not a subtask; subtask rows have an empty `id` on purpose.
- After a cutover, the [reverse replication](../features/sharding/resharding/cutover.md#after-the-cutover) stream appears as its own `root` task of type `replication ... (reverse)`. Use its ID to [roll back](../features/sharding/resharding/cutover.md#rolling-back) (`CUTOVER `) or to [finalize the migration](../features/sharding/resharding/cutover.md#finalizing-the-migration) (`STOP_TASK `).

## Spotting issues

| Symptom | What to check |
|-|-|
| `status` is `failed: ...` or `panicked: ...` | Read the error message in the `status` column, then check the PgDog logs for the full context. The task is stopped; address the cause and re-run the command. |
| Task stuck at one `inner_status` for a long time | Cross-reference [`SHOW TABLE_COPIES`](../features/sharding/resharding/move.md#monitoring-progress) (during `syncing data`) and [`SHOW REPLICATION_SLOTS`](../features/sharding/resharding/move.md#streaming-updates) (during `replicating`) to see whether data is still flowing. |
| `status` is `cancelling` and not clearing | The task is draining its replication streams. A cutover that has already started runs to completion before the status settles. |
| Terminal task you expected to still be running | It reached a terminal state (`finished`/`cancelled`/`failed`). Check `inner_status` and `updated_at` to see where and when it stopped. |

## Stopping a task

Stop any running task by its root `id`:

```
STOP_TASK <task_id>;
```

This requests cancellation; the task winds down gracefully and stops appearing as `running` once it has actually stopped. For replication and copy tasks, a graceful stop also drops the replication slot the task created. See [finalizing the migration](../features/sharding/resharding/cutover.md#finalizing-the-migration) for how this is used after a cutover.

---

## File: docs/architecture/benchmarks.md

---
icon: material/chart-bar
---

# Benchmarks

PgDog does its best to minimize its impact on database performance. Great care is taken to make sure as few operations as possible are performed
when passing data between clients and servers.

All benchmarks listed below were done on my local system (AMD Ryzen 7 5800X). Real world performance is impacted by factors like network speed, query complexity and especially by hardware used for running PgDog and PostgreSQL servers.

## pgbench

The simplest way to test PostgreSQL performance is with `pgbench`. It comes standard with all PostgreSQL installations (Mac and Linux):

```
$ pgbench --version
pgbench (PostgreSQL) 16.4 (Postgres.app)
```

A standard pgBench benchmark will run `INSERT`, `UPDATE`, `SELECT` and `DELETE` queries to get an overall view of database performance. Since we are only testing the performance of PgDog, we are going to run `SELECT` queries only and minimize the impact of hard disk I/O on this test.

This benchmark can be reproduced by passing the `-S` flag to `pgbench`. The results below were performed using the configuration found in [`pgdog.toml`](https://github.com/levkk/pgdog/blob/main/pgdog.toml).

## Results

### Multi-threaded

Numbers below are for a single database benchmark in transaction mode. `workers` are set to `4`, so PgDog is running 4 threads and using async I/O.

#### Protocol

The protocol column indicates what kind of communication protocol
pgbench is using to talk to PgDog/Postgres.

`simple` protocol is sending
queries with parameters included in query text. This requires Postgres
to receive only one message but has parsing overhead inside PgDog.

`extended` protocol separates parameters from query text. This prevents
SQL injection attacks, but PgDog is able to deduplicate statements and most parsing overhead.

`prepared` protocol is the fastest since pgbench is re-using the same
statements and only sends different parameters. This removes the need to parse
statements inside PgDog and Postgres.

#### The numbers

| Protocol | Clients | TPS | Latency |
|---------|-------|----|------------|
| simple | 1 | 10,790.06 | 0.093 ms |
| simple | 10 | 70,661.18 | 0.137 ms |
| simple | 100 | 78,232.15 | 1.266 ms |
| extended | 1 | 11,634.29 | 0.086 ms |
| extended | 10 | 74,529.28 | 0.128 ms |
| extended | 100 | 94,584.0 | 1.045 ms |
| prepared | 1 | 17,468.19 | 0.057 ms |
| prepared | 10 | 110,942.87 | 0.084 ms |
| prepared | 100 | 119,273.2 | 0.825 ms |

### Single-threaded

This benchmark ran with `workers` set to 0. This makes PgDog run in single-threaded mode, but still uses async I/O.

| Protocol | Clients | TPS | Latency |
|---------|-------|----|------------|
| simple | 1 | 11,042.68 | 0.090 ms |
| simple | 10 | 30,209.56 | 0.331 ms |
| simple | 100 | 28,931.41 | 3.349 ms |
| extended | 1 | 11,702.49 | 0.085 ms |
| extended | 10 | 49,920.91 | 0.200 ms |
| extended | 100 | 47,108.79 | 2.075 ms |
| prepared | 1 | 18,222.30 | 0.055 ms |
| prepared | 10 | 53,468.63 | 0.187 ms |
| prepared | 100 | 50,441.38| 1.943 ms |

### Interpretation

#### 1 client

Benchmarks with `-c 1` (1 client) are a good baseline for what's possible under the best possible circumstances. There is no contention on resources
and PgDog effectively receives data in one socket and pushes it out the other.

#### 10 clients

With 10 clients actively querying the database, the connection pool is at full capacity (`default_pool_size` is set to `10`). While there are no clients waiting for connections, the pool has to serve clients without any slack in the system.

#### 100 clients

With over 10x more clients connected than available servers, connections are fighting for resources and PgDog has to make sure everyone gets served in a fair way. Consistent throughput in this benchmark demonstrates our ability to timeshare server connections effectively.

### Parser overhead

PgDog parses statements to figure out where they should go. When using `simple` protocol, PgDog can't cache statements (since they include parameters), so the overhead of the parser is noticeable. When using `extended` and `prepared` protocols, the cache is doing its job and the parser overhead is almost entirely eliminated.

### In the real world

In production, PostgreSQL clients are expected to be mostly idle. For example, web applications spend a lot of their time parsing HTTP requests, running code and waiting on network I/O. This leaves plenty of time for PgDog (and PostgreSQL) to serve queries for thousands of clients.

#### Hardware impact

Benchmark results will vary widely with hardware. For example, these numbers will be better on new Apple M chips and slower on older Intel CPUs. This benchmark was ran on AMD Ryzen 7 5800X. Expect yours to vary, but the overall trend to be directionally similar.

### pgbench configuration

```bash
export PGPASSWORD=pgdog

pgbench -P 1 -h 127.0.0.1 -p 6432 \
    -U pgdog pgdog -c 10 -t 100000 -S \
    --protocol prepared
```

---

## File: docs/architecture/comparison.md

---
icon: material/scale-balance
---

# Comparison to other poolers

PgDog aims to be the de facto PostgreSQL proxy and pooler. Below is a feature comparison between PgDog and a few popular alternatives.

## Basics

| Feature | PgBouncer | PgCat | PgDog |
|-|-|-|-|
| [Connection pooler](../features/connection-pooler/transaction-mode.md) | :material-check-circle-outline: | :material-check-circle-outline: | :material-check-circle-outline: |
| Load balancer | Requires external TCP proxy | :material-check-circle-outline: | :material-check-circle-outline: |
| [Read/write separation](../features/load-balancer/index.md) | No | Basic support | Advanced support handling edge cases |
| [Failover](../features/load-balancer/healthchecks.md) | No | :material-check-circle-outline: | :material-check-circle-outline: |
| [Health checks](../features/load-balancer/healthchecks.md) | No | :material-check-circle-outline:  | :material-check-circle-outline: |
| [Authentication](../features/auth/index.md) | :material-check-circle-outline: | `md5`, `plain` | `scram-sha-256`, `md5`, `plain` |
| [Metrics](../features/metrics.md) | Admin database only | OpenMetrics & admin database | OpenMetrics & admin database |
| [Mirroring](../features/mirroring.md) | No | Partial support | :material-check-circle-outline: |
| TLS | :material-check-circle-outline: | :material-check-circle-outline: | :material-check-circle-outline: |
| [Prepared statements](../features/connection-pooler/prepared-statements.md) | :material-check-circle-outline: | Partial support | :material-check-circle-outline: |
| [Plugins](../features/plugins/index.md) | No | Hardcoded in core | :material-check-circle-outline: |
| Session evariables in transaction mode | Partial support | Partial support | :material-check-circle-outline: |

## Sharding

[Sharding](../features/sharding/index.md) is not supported in PgBouncer, so it will be excluded from this section.

| Feature | PgCat | PgDog |
|-|-|-|
| [Manual routing](../features/sharding/manual-routing.md) | Only using comments (regex), doesn't work with prepared statements | :material-check-circle-outline: |
| [Automatic routing](../features/sharding/query-routing.md) | No | :material-check-circle-outline: |
| [Primary key generation](../features/sharding/sequences.md) | No | :material-check-circle-outline: |
| [Cross-shard queries](../features/sharding/cross-shard-queries/index.md) | No | Partial support |
| [COPY](../features/sharding/cross-shard-queries/copy.md) | No | :material-check-circle-outline: |
| [Postgres-compatible sharding functions](../features/sharding/sharding-functions.md) | No | Same functions as declarative partitioning |
| Two-Phase Commit  | No | :material-check-circle-outline: |

---

## File: docs/architecture/index.md

---
icon: material/cube-outline
---

# Architecture overview

PgDog is written in the [Rust](https://rust-lang.org) programming language. It is also asynchronous, powered by the [Tokio](https://tokio.rs) runtime. This allows PgDog to serve hundreds of thousands of connections on one machine and to take advantage of multiple CPUs.

## Plugins

[Plugins](../features/plugins/index.md) are shared libraries (`.so` on Linux, `.dylib` on Mac, `.dll` on Windows) loaded at startup. This allows to
change many aspects of PgDog functionality without altering or recompiling internal source code.

## PostgreSQL protocol

PgDog speaks the PostgreSQL [frontend/backend](https://www.postgresql.org/docs/current/protocol.html) protocol. This allows it to act as an
application layer (OSI Level 7) proxy and multiplex client/server connections. It can also alter connection state
to suit operational needs, e.g. rolling back unfinished transactions, changing server settings, clearing session variables.


## Learn more

- [Features](../features/index.md)
- [Configuration](../configuration/index.md)
- [Benchmarks](benchmarks.md)

---

## File: docs/configuration/pgdog.toml/admin.md

---
icon: material/security
---

# Admin database settings

Admin database settings control access to the [admin](../../administration/index.md) database which contains real time statistics about internal operations
of PgDog. For example:

=== "pgdog.toml"
    ```toml
    [admin]
    password = "hunter2"
    ```
=== "Helm chart"
    ```yaml
    adminPassword: "hunter2"
    ```

### `name`

Admin database name.

Default: **`admin`**

### `user`

User allowed to connect to the admin database. This user doesn't have
to be configured in `users.toml`.

Default: **`admin`**

### `password`

Password the user needs to provide when connecting to the admin database. By default, this is randomly
generated so the admin database is locked out unless this value is set.

!!! note
    If this value is not set, admin database access will be restricted.

Default: **random**