← Home ← Codex ← DEBT ← Engine
Browse by Category
+ added · updated 7d
← Back to glossary

Connection Pooling

Performance PHP 5.0+ Intermediate
debt(d5/e5/b5/t5)
d5 Detectability Operational debt — how invisible misuse is to your safety net

Closest to 'specialist tool catches' (d5). The term's detection_hints.tools lists mysql-processlist, pgbouncer, proxysql, and datadog — all specialist monitoring/infrastructure tools. Connection pooling issues manifest as 'Too many connections' errors or slow time-to-first-byte, requiring database monitoring or APM tools to diagnose, not standard linters or compilers.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor' (e5). The quick_fix mentions configuring PHP-FPM pm.max_children and introducing PgBouncer or ProxySQL. This isn't a one-line code change — it requires infrastructure configuration, potentially new services (connection pooler), and adjusting application connection strings across the codebase. A meaningful fix spans ops config and application code.

b5 Burden Structural debt — long-term weight of choosing wrong

Closest to 'persistent productivity tax' (b5). Connection pooling strategy applies to web and queue-worker contexts per applies_to, affecting all database-touching code paths. The choice of pooling approach (or lack thereof) creates ongoing operational overhead — pool sizing, timeout tuning, stale connection handling. It's not architectural-level burden (b7+), but it's more than localized since every request's DB behavior depends on this configuration.

t5 Trap Cognitive debt — how counter-intuitive correct behaviour is

Closest to 'notable trap / documented gotcha' (t5). The misconception explicitly states that developers wrongly believe PHP persistent connections (pconnect) are equivalent to proper connection pooling. This is a documented gotcha — pconnect is per-FPM-worker, not a shared pool. Developers familiar with connection pooling from other ecosystems expect shared pools and are surprised by PHP's per-process model.

About DEBT scoring →

Also Known As

DB connection pool database pool persistent connections

TL;DR

Reusing a pool of pre-established database connections rather than opening and closing a new connection on every request.

Explanation

Opening a database connection is expensive — TCP handshake, authentication, and protocol negotiation can add 10–100ms per request. Connection pooling maintains a pool of open connections that are borrowed and returned rather than created and destroyed. In traditional PHP-FPM setups, each PHP process maintains its own persistent connection (PDO with persistent=true or using PgBouncer/ProxySQL as a pool proxy). This is critical at scale — without pooling, databases hit connection limits under moderate load.

Diagram

flowchart LR
    subgraph Without Pool
        REQ1[Request] -->|new connection| DB1[(DB)]
        REQ2[Request] -->|new connection| DB1
        REQ3[Request] -->|new connection| DB1
        INFO1[Each: TCP handshake<br/>auth overhead ~50ms]
    end
    subgraph With Pool
        POOL[(Connection Pool<br/>10 persistent connections)]
        R1[Request] -->|borrow| POOL
        R2[Request] -->|borrow| POOL
        POOL <-->|persistent| DB2[(DB)]
        INFO2[Borrow/return O of 1<br/>no handshake overhead]
    end
    style INFO1 fill:#f85149,color:#fff
    style INFO2 fill:#238636,color:#fff

Common Misconception

PHP persistent connections (pconnect) are equivalent to a proper connection pool. Persistent connections reuse a connection per Apache/FPM process but do not manage a pool across processes. PgBouncer and ProxySQL provide true pooling with configurable pool sizes and idle connection management.

Why It Matters

Connection pooling reuses existing database connections across requests — avoiding the TCP handshake and authentication overhead of creating a new connection for every query.

Common Mistakes

  • PHP-FPM persistent connections are per-worker, not shared — each worker holds its own connection.
  • Not using a dedicated pooler like PgBouncer for PostgreSQL — PHP's built-in pooling is limited.
  • Pool connections that are never validated — stale connections that have been closed by the database cause errors.
  • Setting connection timeout too high — idle connections held open indefinitely consume database server resources.

Code Examples

✗ Vulnerable
// New connection on every request — no pooling:
function getDb(): PDO {
    return new PDO('mysql:host=db;dbname=app', 'user', 'pass');
    // TCP connect + auth on every request — 5-20ms overhead per request
}
// Fix: use persistent connections or a connection pool
✓ Fixed
// PHP-FPM does NOT persist connections between requests by default
// Use a pooler (pgBouncer/ProxySQL) at the infrastructure level

// Point your DSN at the pooler, not the DB directly:
$dsn = 'pgsql:host=pgbouncer;port=6432;dbname=myapp';
$pdo = new PDO($dsn, $user, $pass, [
    PDO::ATTR_PERSISTENT => false, // let pgBouncer manage pooling
]);

// pgBouncer config (pgbouncer.ini)
[databases]
myapp = host=postgres port=5432 dbname=myapp

[pgbouncer]
pool_mode = transaction    ; most efficient
max_client_conn = 1000     ; FPM workers
default_pool_size = 20     ; actual DB connections

Added 15 Mar 2026
Edited 22 Mar 2026
Views 107
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T 0 pings F 1 ping S 1 ping S 1 ping M 0 pings T 1 ping W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 0 pings S 0 pings S 0 pings M 0 pings T 2 pings W 0 pings T 0 pings F
No pings yet today
No pings yesterday
Scrapy 16 Amazonbot 13 Perplexity 9 PetalBot 8 Ahrefs 7 SEMrush 7 Google 6 Unknown AI 2 Applebot 2 Meta AI 1 Bing 1 Twitter/X 1 Brave Search 1
crawler 73 crawler_json 1
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: High
⚡ Quick Fix
Configure PHP-FPM pm.max_children based on available RAM, and use PgBouncer (PostgreSQL) or ProxySQL (MySQL) for connection pooling between PHP and DB
📦 Applies To
PHP 5.0+ web queue-worker
🔗 Prerequisites
🔍 Detection Hints
MySQL 'Too many connections' error; connection count near max_connections; slow time-to-first-byte from connection overhead
Auto-detectable: ✓ Yes mysql-processlist pgbouncer proxysql datadog
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File


✓ schema.org compliant