Skip to content

Commit 92a704a

Browse files
committed
dark
1 parent ffd6dc5 commit 92a704a

8 files changed

Lines changed: 75 additions & 32 deletions

File tree

docs/features/connection-pooler/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ If your application uses `LISTEN`/`NOTIFY`, e.g., [DBOS](https://dbos.dev) or an
3939

4040
This allows applications to use `LISTEN`/`NOTIFY` in [transaction mode](pub_sub.md), just like any other Postgres feature.
4141

42+
### Connection recovery
43+
44+
Unlike other poolers, PgDog takes extra care not to close connections to Postgres unless absolutely necessary. It goes as far as to roll back abandoned transactions and drain abandoned queries. This protects the database against connection storms created by buggy applications.
45+
46+
You can read more about connection recovery methods [here](connection-recovery.md).
47+
4248
## Read more
4349

4450
{{ next_steps_links([

docs/features/load-balancer/healthchecks.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ All databases load balanced by PgDog are regularly checked with health checks. A
99
If a replica database fails a health check, it's temporarily removed from the load balancer, preventing it from serving queries for a configurable period of time.
1010

1111
<center>
12-
<img src="/images/healthchecks.png" width="80%" alt="Healthchecks"/>
12+
<img src="/images/healthchecks.png" width="80%" alt="Healthchecks" class="theme-aware-image" />
13+
<p>Health checks prevent broken databases from serving queries.</p>
1314
</center>
1415

1516
## How it works
@@ -23,8 +24,7 @@ PgDog performs two kinds of health checks to ensure applications don't accidenta
2324

2425
If a connection or database fails a health check, it is **temporarily removed** from the load balancer and cannot serve any more queries. This prevents applications from continuously hitting a broken database until it's restarted by an administrator.
2526

26-
!!! note "99.99% uptime"
27-
This strategy is very effective at reducing error rates in busy applications. If you are operating a large number of databases, hardware failures are relatively common and an effective load balancer is required to maintain 99.99% database uptime.
27+
This strategy is very effective at reducing error rates in busy applications. If you are operating a large number of databases, hardware failures are relatively common and an effective load balancer is required to maintain 99.99% database uptime.
2828

2929
### Connection health check
3030

@@ -85,6 +85,13 @@ When PgDog is first started, it's possible that the database or the network is n
8585

8686
The **default** value for this setting is **5 seconds** (`5_000` milliseconds).
8787

88+
!!! note "Disabling health checks"
89+
If you want to disable database health checks, you can set the `idle_healthcheck_delay` setting to a large number, e.g. 100 years, in milliseconds:
90+
91+
```toml
92+
[general]
93+
idle_healthcheck_delay = 3155760000000
94+
```
8895

8996
### Primary database exception
9097

@@ -108,10 +115,7 @@ The amount of time the database is banned from serving traffic is controlled wit
108115

109116
The **default** value is **5 minutes** (`300_000` milliseconds).
110117

111-
!!! note
112-
A database will not be placed back into the load balancer until it passes a health check again.
113-
114-
Make sure that `idle_healthcheck_interval` is set to a lower value than `ban_timeout`, so health checks have time to run before you expect the database to resume serving traffic.
118+
A database will not be placed back into the load balancer until it passes a health check again. Make sure that `idle_healthcheck_interval` is set to a lower value than `ban_timeout`, so health checks have time to run before you expect the database to resume serving traffic.
115119

116120
### False positives
117121

@@ -170,7 +174,10 @@ This is configurable on startup only and will spin up an HTTP server on `http://
170174

171175
This health check looks at all configured connection pools, and if **at least one** is online, responds with `HTTP/1.1 200 OK`. If _all_ connection pools are down because of failed health checks, PgDog will respond with `HTTP/1.1 502 Bad Gateway`.
172176

173-
!!! note "Handling a lot of requests"
174-
The HTTP health check uses existing internal state to answer requests and doesn't send queries to the connection pools. This makes it very quick and inexpensive, which ensures that massively distributed load balancers (like the AWS NLB) don't cause an unexpected influx of requests to the database.
177+
#### Handling a lot of requests
178+
179+
The HTTP health check uses existing internal state to answer requests and doesn't send queries to the connection pools. This makes it very quick and inexpensive, which ensures that massively distributed load balancers (like the AWS NLB) don't cause an unexpected influx of requests to the database.
180+
181+
#### HTTPS
175182

176183
To make configuration easier, the health check endpoint doesn't support HTTPS, so make sure to configure your load balancer to use plain HTTP only.

docs/features/load-balancer/index.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ icon: material/lan
99

1010
# Load balancer overview
1111

12-
PgDog understands the PostgreSQL wire protocol and uses its SQL parser to understand queries. This allows it to split read queries from write queries and distribute traffic evenly between databases.
12+
PgDog understands the PostgreSQL wire protocol and uses the native PostgreSQL parser to understand queries. This allows it to split read queries from write queries and distribute traffic evenly between databases.
1313

1414
Applications can connect to a single PgDog [endpoint](#single-endpoint), without having to manually manage multiple connection pools.
1515

@@ -18,13 +18,15 @@ Applications can connect to a single PgDog [endpoint](#single-endpoint), without
1818
When a query is received by PgDog, it will inspect it using the native Postgres SQL parser. If the query is a `SELECT` and the [configuration](../../configuration/pgdog.toml/databases.md) contains both primary and replica databases, PgDog will send it to one of the replicas. For all other queries, PgDog will send them to the primary.
1919

2020
<center>
21-
<img src="/images/replicas.png" width="80%" alt="Load balancer" />
21+
<img src="/images/replicas.png" width="95%" alt="Load balancer" class="theme-aware-image" />
22+
<p>Load balancer topology</p>
2223
</center>
2324

2425
Applications don't have to manually route queries between databases or maintain several connection pools internally.
2526

26-
!!! note "SQL compatibility"
27-
PgDog's query parser is powered by the `pg_query` library, which extracts the Postgres native SQL parser directly from its source code. This makes it **100% compatible** with the PostgreSQL query language and allows PgDog to understand all valid PostgreSQL queries.
27+
### SQL compatibility
28+
29+
PgDog's query parser is powered by the `pg_query` library, which extracts the Postgres native SQL parser directly from its source code. This makes it **100% compatible** with the PostgreSQL query language and allows PgDog to understand all valid PostgreSQL queries.
2830

2931
## Load distribution
3032

docs/features/load-balancer/manual-routing.md

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,17 @@ SET LOCAL "pgdog"."role" TO "primary";
139139

140140
In this example, all transaction statements (including the `BEGIN` statement) will be sent to the primary database. Whether the transaction is committed or reverted, the value of `pgdog.role` will be reset to its previous value.
141141

142-
!!! note "Statement ordering"
143-
To make sure PgDog intercepts the routing hint early enough in the transaction flow, you need to send all hints _before_ executing actual queries.
142+
#### Statement ordering
143+
To make sure PgDog intercepts the routing hint early enough in the transaction flow, you need to send all hints _before_ executing DDL/DML statements.
144144

145-
The following flow, for example, _will not_ work:
145+
The following flow, for example, _will not_ work:
146146

147-
```postgresql
148-
BEGIN;
149-
SELECT * FROM users WHERE id = $1;
150-
SET LOCAL pgdog.role TO "primary"; -- The client is already connected to a server.
151-
INSERT INTO users (id) VALUES ($1); -- If connected to a replica, this will fail.
152-
```
147+
```postgresql
148+
BEGIN;
149+
SELECT * FROM users WHERE id = $1;
150+
SET LOCAL pgdog.role TO "primary"; -- The client is already connected to a server.
151+
INSERT INTO users (id) VALUES ($1); -- If connected to a replica, this will fail.
152+
```
153153

154154

155155

@@ -171,6 +171,24 @@ If you've configured the desired database role (and/or shard) for each of your a
171171

172172
Once it's disabled, PgDog will rely solely on the `pgdog.role` and `pgdog.shard` parameters to make its routing decisions.
173173

174-
### Session state & `SET`
174+
### Session state and SET
175175

176176
The query parser is used to intercept and interpret `SET` commands. If the parser is disabled and your application uses `SET` commands to configure the connection, PgDog will not be able to guarantee that all connections have the correct session settings in [transaction mode](../connection-pooler/transaction-mode.md).
177+
178+
You can keep the parser enabled for handling `SET` commands only as follows:
179+
180+
=== "pgdog.toml"
181+
```toml
182+
[general]
183+
query_parser = "session_state"
184+
```
185+
=== "Helm chart"
186+
```yaml
187+
queryParser: session_state
188+
```
189+
190+
The internal implementation is using a very fast Regex to detect `SET` commands and will turn on the query parser for that statement only. The regex supports comments as well, so the following example will be detected:
191+
192+
```postgresql
193+
/* api: users.create */ SET application_name TO 'sidekiq';
194+
```

docs/features/load-balancer/replication-failover.md

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ icon: material/chart-timeline-variant
44

55
# Replication and failover
66

7-
PgDog has built-in functionality for monitoring the state of Postgres replica databases. If configured, it can also automatically detect when a replica is promoted and redirect write queries to the new primary, and ban replicas from serving traffic if they have fallen far behind in the replication stream.
7+
PgDog has built-in functionality for monitoring the state of Postgres replica databases. If configured, it can also automatically detect when a replica is promoted and redirect write queries to the new primary, or block replicas from serving traffic if they have fallen far behind in the replication stream.
88

99
## Replication
1010

@@ -25,15 +25,15 @@ In addition to fetching raw metrics, PgDog can calculate the replication lag (al
2525
| Primary LSN | Get the LSN from the primary using `pg_current_wal_lsn()`. |
2626
| Replica LSN | Get the LSN from each replica using `pg_last_wal_replay_lsn()` or `pg_last_wal_receive_lsn()`. |
2727
| LSN check | If the two LSNs are identical, replication lag is 0. |
28-
| Calculate lag | If the two LSNs are different, replication lag is `now() - pg_last_xact_replay_timestamp()`. |
28+
| Calculate lag | If the two LSNs are different, replication lag is `now() - pg_last_xact_replay_timestamp()` retrieved from the replica. |
2929

3030
This formula assumes that when the replica's LSN is behind the primary, the primary is still receiving write requests. While this is not always the case, it will show replication lag growing over time if the replication stream is falling behind or is broken.
3131

3232
!!! note "Formula accuracy"
3333
It is possible to calculate the exact replication delay in bytes by subtracting a replica LSN from the primary LSN. While this provides an exact measurement,
3434
that metric isn't very useful: it's hard to translate bytes into a measurement of how stale the data on the replica truly is.
3535

36-
Approximating the lag in milliseconds is more informative and will be reasonably accurate the majority of the time.
36+
Approximating the lag in milliseconds is more informative and will be reasonably accurate most of the time.
3737

3838
### Configuration
3939

@@ -66,10 +66,15 @@ Decreasing the value of `lsn_check_interval` will produce more accurate statisti
6666

6767
It's common for PgDog deployments to be serving upwards of 30,000-50,000 queries per second per pooler process, so you can run the LSN check query quite frequently without noticeable impact on system latency.
6868

69+
#### Saturated connection pool
70+
71+
If the connection pool is at capacity, either due to a database incident or an inefficient query, PgDog will create a standalone connection to fetch the LSN from each database in the configuration. This is to make sure that it can't miss
72+
a [failover](#failover) event during a database incident.
73+
6974
### Replica lag ban
7075

71-
!!! note "Experimental feature"
72-
This feature is new and experimental. Please report any issues you encounter.
76+
!!! note "New feature"
77+
This feature is new and experimental. Please report any issues you may encounter.
7378

7479
If a replica has fallen far behind the primary, it may start serving stale data to the application. This can cause hard to debug issues, so it's often best to remove this replica from the load balancer until it's able to catch up.
7580

@@ -98,14 +103,15 @@ Unlike [health check-triggered](healthchecks.md) bans, replica lag ban is not cl
98103

99104
## Failover
100105

101-
<center>
102-
<img src="/images/failover.png" width="95%" alt="Failover" />
103-
</center>
104-
105106
If the `pg_is_in_recovery()` function returns `true`, the database is configured as a standby. It can only serve read queries (e.g. `SELECT`) and is expected to be reasonably up-to-date with the primary database.
106107

107108
Replica databases can be promoted to serve write queries. If that happens, `pg_is_in_recovery()` will start returning `false`. You can read more about this in the [PostgreSQL documentation](https://www.postgresql.org/docs/18/functions-admin.html#FUNCTIONS-RECOVERY-CONTROL).
108109

110+
<center>
111+
<img src="/images/failover.png" width="90%" alt="Failover" class="theme-aware-image" />
112+
<p>Failover event</p>
113+
</center>
114+
109115
!!! warning "Failover trigger"
110116
PgDog does not detect primary failure and **will not** call `pg_promote()`. It is expected that the databases are managed externally by another tool, like Patroni or AWS RDS, which handle replica promotion.
111117

@@ -140,6 +146,10 @@ Failover is disabled by default. To enable it, change all configured databases i
140146

141147
On startup, PgDog will connect to each database, find out if they are in recovery, and automatically reload its configuration with the determined roles.
142148

149+
!!! info "Replication lag monitoring"
150+
In order for PgDog to detect failover events, it needs to query the database for its [replication status](#configuration). Make sure to set
151+
`lsn_check_delay` to a reasonable value (e.g., `0`) before enabling this feature.
152+
143153
### Split brain
144154

145155
If a replica is promoted while the existing primary is alive and serving queries, write queries can be routed to either database, causing data loss. This type of error is called "split brain", indicating that the database cluster no longer has an authoritative source of data it's managing.

docs/images/failover.png

664 Bytes
Loading

docs/images/healthchecks.png

-23.9 KB
Loading

docs/images/replicas.png

-26.3 KB
Loading

0 commit comments

Comments
 (0)