Database Connection Pooling
debt(d7/e5/b5/t5)
Closest to 'only careful code review or runtime testing' (d7). The term's detection_hints show automated=no, and the code_pattern 'new PDO\(|pg_connect' only detects connection creation, not whether pooling is properly configured. Connection exhaustion issues typically manifest only under production load, requiring runtime testing or careful review of infrastructure setup. No automated tools from detection_hints can catch missing PgBouncer/ProxySQL configuration.
Closest to 'touches multiple files / significant refactor in one component' (e5). The quick_fix mentions adding PgBouncer or ProxySQL in production and configuring pool sizes - this involves infrastructure changes, configuration files, and potentially adjusting application connection parameters. While setting ATTR_PERSISTENT is a one-liner, the full solution for production pooling requires deployment configuration, not just code changes.
Closest to 'persistent productivity tax' (b5). The term applies_to web, cli, and queue-worker contexts, meaning the pooling strategy affects multiple execution environments. The choice of pooler (PgBouncer vs ProxySQL) and pool sizing becomes a system-wide concern that shapes deployment architecture and influences how all database-touching code behaves under load. Not quite 'defines the system's shape' (b9) but definitely more than localized.
Closest to 'notable trap (a documented gotcha most devs eventually learn)' (t5). The misconception field explicitly states the trap: 'PHP persistent connections (ATTR_PERSISTENT) are the same as a connection pool.' This is a documented gotcha where developers think they have pooling via ATTR_PERSISTENT when they actually just have per-process connection reuse. Common mistake of 'persistent connections with dirty state' reinforces this trap.
TL;DR
Explanation
Opening a DB connection is expensive (TCP handshake, authentication, SSL). Pooling: maintain N open connections, hand them out per request, return after use. PHP-FPM: each worker maintains its own persistent connection (PDO with ATTR_PERSISTENT). PgBouncer (PostgreSQL), ProxySQL (MySQL): external poolers between app and DB. Benefits: lower latency, limited max connections to DB (DB has hard limits). Pitfalls: persistent connections in PHP-FPM can carry state (transactions, temp tables) — always clean up. Swoole: built-in connection pool per coroutine pool. Laravel Octane: persistent PDO connections per worker.
Common Misconception
Why It Matters
Common Mistakes
- Not using PgBouncer/ProxySQL in production — DB exhausts connections under load.
- Persistent connections with dirty state (uncommitted transactions left on connection).
- Forgetting to return connections to Swoole pool in finally block.
Code Examples
// New connection per request — 100 workers = 100 connections:
$pdo = new PDO($dsn, $user, $pass); // Fresh connection each time
// PHP-FPM persistent:
$pdo = new PDO($dsn, $user, $pass, [PDO::ATTR_PERSISTENT => true]);
// External pooler config (PgBouncer):
# pgbouncer.ini:
# max_client_conn = 1000 (app connections)
# pool_size = 20 (DB connections)