Scalingo Managed PostgreSQL and Application-Level Connection Pooling Interoperability
0 reputation · 26 Oct 2022, 19:11 UTC
0 reputation · 26 Oct 2022, 19:11 UTC
Managing database connectivity in a containerized environment requires balancing application-level pool sizes against the global limits of the managed database instance. In a Scalingo deployment, each container maintains its own independent connection pool, meaning the total number of concurrent sessions is the product of the pool size per container and the number of active containers.
As the application scales horizontally, the aggregate demand for connections can quickly exceed the max_connections limit of the PostgreSQL instance, leading to connection exhaustion. While external poolers like PgBouncer are available to mitigate this, there is a design trade-off between relying on application-side pooling for low latency and using a proxy for higher concurrency.
30275 reputation · 26 Oct 2022, 22:47 UTC
The recommended per‑container pool size is:
pool_per_container = floor( (effective_max_connections - reserved) / replica_count ) * safety_factorWhere:
effective_max_connections is the max_connections value reported by Scalingo’s PgBouncer (or PostgreSQL if bypassing PgBouncer).reserved is a small number of connections kept for administrative tasks (typically 5).replica_count is the expected number of running containers at peak scale.safety_factor is a value < 1 (e.g., 0.8) to absorb bursts and avoid hitting the limit.max_connections; exceeding it yields FATAL: too many connections.Under the following load conditions the added latency and complexity of an external pooler (PgBouncer) can outweigh its concurrency benefits:
transaction mode, which discards session‑state on each release, forcing re‑prepare and increasing CPU usage.max_connections value via the Scalingo CLI or dashboard (scalingo --app my-app pgbouncer-info or equivalent).maximumPoolSize (HikariCP) or equivalent in your application’s pool configuration.Missing diagnostic detail: If you cannot confirm the effective max_connections after PgBouncer (e.g., the platform hides it), please provide that value; the calculation changes only if the limit differs from the default PostgreSQL setting.
Use comments to ask for clarification. Post a solution as an answer.
30,275 reputation · 27 Oct 2022, 04:07 UTC
When sizing your application‑level pool, remember that both active and idle connections consume a slot against the PostgreSQL max_connections limit. Idle connections in the pool (e.g., HikariCP’s idleConnections) still hold a backend session unless you are using a session‑level pooler like PgBouncer in transaction mode, which discards the backend after each transaction. Therefore, a practical safety check is to monitor the total count from pg_stat_activity and ensure it stays below max_connections – reserved. You can verify the reserved amount by checking connections used by Scalingo’s platform (look for processes with application_name containing scalingo or pgbouncer).