Docs
Skip to content

PostgreSQL

Connection pooling_

Configure the per-database connection pooler to serve many short-lived clients, with automatic read/write splitting when high availability is enabled.

3 min read

Raw

PostgreSQL creates one backend process per connection, which makes each connection relatively expensive. Serverless functions, edge runtimes, and horizontally scaled application servers can easily exhaust the connection limit of your specification. The connection pooler sits in front of your database and multiplexes many client connections onto a small pool of server connections.

The pooler runs next to your database and is reachable on port 6432 on the same hostname. Your application connects to the pooler exactly like it would connect to PostgreSQL directly, same credentials, same TLS. The pooler runs on every PostgreSQL specification.

Pool modes

ModeBehaviorUse for
transactionA server connection is assigned for the duration of a transaction, then returned to the poolServerless and most applications (default)
sessionA server connection is held for the entire client sessionSession-level features: prepared statements, advisory locks, LISTEN/NOTIFY, temporary tables

Transaction mode gives the highest connection multiplexing but does not support session-level state. If your framework prepares statements at the session level, either switch the driver to unnamed prepared statements or use session mode.

Configure the pooler

Read the current pooler configuration with getPooler, and tune the pool mode and sizes with updatePooler. All parameters are optional; omitted values keep their current setting.

ParameterRangeDescription
modetransaction, sessionHow long a server connection stays assigned to a client
maxConnectionsread-onlyReports the database's advertised connection limit. The PostgreSQL pooler does not cap client connections, so set networkMaxConnections on the database instead
defaultPoolSize1 - 1,000Server connections per user in the pool
readWriteSplittingbooleanRoute SELECTs to replicas, writes and locked reads to the primary. Defaults to on when high availability is enabled

Pooler configuration is API-only. The Console shows the pooled host and port in the Credentials dialog but has no page for changing these settings.

Switching to session mode is refused while the database has high availability replicas. Set replicas to 0 first, or stay on transaction mode.

Connect through the pooler

Take your normal connection string and change the port to 6432:

Bash
postgresql://admin:<password>@db-<hash>.<region>.appwrite.center:6432/db-<hash>?sslmode=require

Point your application's runtime traffic at the pooler port. Keep migrations and long-lived administrative sessions on the direct port 5432, schema changes and tools like pg_dump expect session semantics and can misbehave in transaction mode.

Read/write splitting

When high availability is enabled, the pooler can route read-only statements to replicas and everything else to the primary. SELECT ... FOR UPDATE and statements inside explicit transactions go to the primary. Replicas replicate asynchronously by default, so a read that immediately follows a write can be stale. Synchronous replication does not fix this. It waits for the replica to flush the write to disk, not to replay it, so a replica can still answer a read from before the write. When a read must observe the write that preceded it, send it to the primary on the direct port.

Sizing guidance

Appwrite already sizes the pool for you when the database is provisioned, from your specification's CPU count and connection limit. If you tune it by hand, 4 x CPU cores is a useful starting point. Watch the connection metrics in the Monitor tab and increase the pool only when clients queue for a connection.

When not to use the pooler

The pooler adds a network hop, and transaction mode trades session-level features for connection multiplexing. Connect to the direct port 5432 instead when any of the following applies:

  • A small, fixed fleet. A few long-lived application servers that each maintain a driver-level pool, with a combined connection count that fits in your specification's limit, gain nothing from an extra hop.
  • Session state. Workloads that rely on advisory locks, LISTEN/NOTIFY, session-level prepared statements, or temporary tables break in transaction mode. Use session mode or the direct port.
  • Migrations and administration. Schema changes and tools like pg_dump expect one session for the whole run. Always run them against the direct port.
  • Single latency-sensitive queries. A workload of few, fast queries on an idle database pays the extra hop on every round trip without ever hitting the connection limit the pooler protects against.

Was this page helpful?

Share what worked or what we should fix. Once approved, our agents automatically apply suggested updates to the docs.