← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Connection Pooling — pgBouncer & ProxySQL

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

Closest to 'specialist tool catches it' (d5). Detection requires monitoring tools like pgbouncer stats, proxysql admin interface, mysql-processlist, or APM tools like Datadog to observe connection saturation, 'Too many connections' errors, or PHP-FPM worker counts exceeding safe DB connection ratios. Standard linters won't catch missing pooler infrastructure.

e5 Effort Remediation debt — work required to fix once spotted

Closest to 'touches multiple files / significant refactor in one component' (e5). Adding PgBouncer or ProxySQL requires infrastructure changes: installing the pooler, configuring pool_mode, updating application DSNs, and tuning pool sizes. While the quick_fix suggests it's conceptually simple, the actual deployment touches infrastructure config, application database configuration, and requires testing transaction behavior.

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

Closest to 'persistent productivity tax' (b5). Once deployed, the external pooler becomes load-bearing infrastructure that affects all database-connected code paths (web and queue-worker contexts per applies_to). Developers must understand transaction pooling semantics, pool saturation monitoring, and connection lifecycle. However, it's infrastructure-level burden rather than code-pervasive, so not quite b7.

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

Closest to 'notable trap' (t5). The misconception explicitly states developers wrongly believe PHP persistent connections provide the same benefits as external poolers. This is a documented gotcha most devs eventually learn — the difference between per-process connection reuse and true connection multiplexing. Additional traps include pool_mode confusion (statement vs transaction mode) per common_mistakes.

About DEBT scoring →

Also Known As

external connection pooler PgBouncer ProxySQL

TL;DR

External connection poolers sit between PHP-FPM and your database — multiplexing hundreds of PHP connections onto a small pool of real DB connections.

Explanation

PHP-FPM creates a new database connection per worker. With 100 FPM workers × 10 servers, the database sees 1,000 connections — far above what PostgreSQL or MySQL handle efficiently. pgBouncer (PostgreSQL) and ProxySQL (MySQL) are lightweight proxies that multiplex many client connections onto a smaller pool of real server connections. pgBouncer modes: session pooling (one real connection per client session), transaction pooling (most efficient — real connection held only during a transaction), and statement pooling (PostgreSQL only). ProxySQL also adds query routing, read/write splitting, and query caching. Configure PHP's PDO DSN to point to the pooler rather than the database directly — no application code changes required.

Common Misconception

PHP persistent connections provide the same benefits as an external connection pooler. Persistent connections reuse one connection per PHP process. External poolers like PgBouncer multiplex many PHP connections through a small pool of actual database connections, dramatically reducing database load.

Why It Matters

Extended connection pooling patterns (proxy poolers, connection multiplexing) allow far more application instances than database max_connections — critical for high-concurrency PHP-FPM deployments.

Common Mistakes

  • Not using PgBouncer or ProxySQL in transaction mode — session mode holds a server connection for the full request duration.
  • Not configuring pool_mode correctly — statement mode breaks transactions; transaction mode is usually correct.
  • Assuming PHP PDO persistent connections equal a proper pooler — they are per-process and do not multiplex.
  • Not monitoring pool saturation — queries queue silently when all pool connections are in use.

Code Examples

✗ Vulnerable
# Without PgBouncer — 500 PHP workers exhaust Postgres max_connections=100:
# php-fpm pm.max_children = 500
# Each worker holds 1 connection = 500 needed, but max is 100 — connection errors
# With PgBouncer (transaction mode):
# PHP connects to PgBouncer (up to 500), PgBouncer holds 100 server connections
# Connections multiplexed — no exhaustion
✓ Fixed
// PDO persistent connections — reuse DB connections across PHP-FPM workers
\$pdo = new PDO(
    'mysql:host=localhost;dbname=app;charset=utf8mb4',
    DB_USER, DB_PASS,
    [PDO::ATTR_PERSISTENT => true] // reuse connection in same FPM worker process
);

// Caveat: persistent connections can hold transactions open — use with care
// Better for high-traffic: PgBouncer (PostgreSQL) or ProxySQL (MySQL)
// They pool connections at the network level, transparent to PHP

// ProxySQL — sits between PHP-FPM and MySQL:
// PHP connects to ProxySQL on port 6033
// ProxySQL maintains a pool of real MySQL connections
// Reduces MySQL max_connections pressure dramatically

Added 15 Mar 2026
Edited 22 Mar 2026
Views 32
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 2 pings F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 1 ping F 0 pings S 0 pings S 0 pings M 0 pings T 0 pings W 1 ping T 2 pings F 0 pings S
No pings yet today
Amazonbot 1 Perplexity 1
Amazonbot 10 Perplexity 7 Ahrefs 2 Google 1 Unknown AI 1
crawler 21
DEV INTEL Tools & Severity
🟠 High ⚙ Fix effort: High
⚡ Quick Fix
Add PgBouncer in front of PostgreSQL with transaction pooling mode — it multiplexes hundreds of PHP workers onto 10-20 actual DB connections, eliminating connection overhead
📦 Applies To
PHP 5.0+ web queue-worker
🔗 Prerequisites
🔍 Detection Hints
MySQL 'Too many connections'; max_connections at capacity; PHP-FPM workers > DB max_connections / 2; no PgBouncer or ProxySQL in stack
Auto-detectable: ✓ Yes pgbouncer proxysql mysql-processlist datadog
⚠ Related Problems
🤖 AI Agent
Confidence: Medium False Positives: Medium ✗ Manual fix Fix: Medium Context: File

✓ schema.org compliant