Skip to content

PATTERN Cited by 4 sources

Connection multiplexing proxy

What it is

A connection multiplexing proxy is a server tier placed between application clients and a database that:

  1. Accepts a large number of client-facing connections (thousands to millions).
  2. Owns a much smaller, bounded pool of upstream connections to the backing database.
  3. Multiplexes incoming client queries onto the smaller upstream pool, queueing excess requests when the pool is saturated.

The client sees "the database" — native wire protocol, normal connection semantics. The database sees "one proxy" — a bounded, well-behaved consumer of a fixed connection budget.

Canonical instances: Vitess VTTablet (for MySQL), PgBouncer (for Postgres), ProxySQL, RDS Proxy, Aurora Proxy.

Problem

Each open database connection carries non-trivial cost:

This makes the database's max_connections a memory-derived hard ceiling, not a tunable knob. RDS MySQL caps at 16,000. Raising it risks memory overcommit → OOM crash.

Meanwhile, N application processes each hold their own local pool of P connections. Aggregate upstream connection count = N × P. Scale-out of application tier (especially serverless, where every invocation is a fresh process with fresh pool) trivially breaches the database ceiling. Nothing at the application tier can prevent this — each process sizes its own pool independently, and no process sees the aggregate.

Solution shape

Place a single logical tier between applications and the database that owns the upstream connection budget. Applications connect to the proxy, not the database. The proxy enforces the ceiling once, globally, regardless of how many application processes connect.

┌─────────┐ ┌─────────┐ ... ┌─────────┐
│ app 1   │ │ app 2   │     │ app N   │   N * P connections here
└────┬────┘ └────┬────┘     └────┬────┘   (cheap: gRPC/TLS to proxy,
     │           │               │          or even plain TCP)
     └───────────┴───────────────┘
          ┌──────┴──────┐
          │    proxy    │   ← owns the upstream ceiling
          │  (bounded   │     (e.g. 300 connections)
          │    pool)    │
          └──────┬──────┘
                 │  300 MySQL connections max
          ┌─────────────┐
          │  database   │
          └─────────────┘

The client-facing ceiling is decoupled from the upstream ceiling: a PlanetScale MySQL database sustains 1,000,000 concurrent client connections (Liz van Dijk benchmark, Source: sources/2026-04-21-planetscale-one-million-connections) against backing MySQL instances with max_connections in the hundreds.

Why the proxy can multiplex

Most OLTP queries are short (sub-ms to tens of ms). A single upstream connection can serve hundreds or thousands of client queries per second. The proxy's pool size just needs to be concurrency × average-query-duration / 1 sec — typically orders of magnitude smaller than the client-facing connection count.

Admission control falls out naturally: when every upstream connection is in use, new queries queue at the proxy (pool-exhaustion becomes a signal with a natural threshold), and the proxy can reject, wait, or apply backpressure without overwhelming the database.

Consequences

Positive:

  • Global admission control: upstream ceiling is enforced once, regardless of client topology.
  • Cold-start friendly: clients connect cheaply to the proxy (no MySQL SSL handshake per fresh process).
  • max_connections stability: the ceiling is a property of the proxy's config, not an emergent property of client scale.
  • Observability choke point: the proxy is a natural place for query logging, rewrite, caching, routing, throttling (patterns/query-routing-proxy-with-health-aware-pool).
  • Composable with two-tier pooling — the proxy is the second tier beneath the application's own local pool.

Negative:

  • One more hop on the query path (latency cost: typically <1 ms on same-network proxy).
  • Session-state handling becomes harder — tainted connections can't be rotated across callers without mitigation (see patterns/settings-aware-connection-pool and concepts/reserved-connection).
  • Proxy availability becomes a new dependency — the proxy's HA story must match or exceed the database's.
  • Feature gap — some database features (LISTEN/NOTIFY in Postgres; prepared statements across callers; session advisory locks) are incompatible with aggressive pooling modes.

Known implementations

Proxy Backing DB Pooling granularity Distinctive features
Vitess VTTablet MySQL Per-query (+ settings-pool) Lockless atomic pool; in-cluster sidecar per MySQL instance; shard-aware routing; settings-aware pool from v15
PgBouncer Postgres Session / transaction / statement Lightweight (single-threaded event loop); query_wait_timeout admission control; canonical three-mode exposition (Source: sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer)
ProxySQL MySQL Connection multiplexing Query routing, caching, firewall
RDS Proxy MySQL / Postgres Per-transaction AWS-managed; IAM auth integration
PgCat Postgres Session / transaction Rust-implemented; sharding support

The shape is general: applications-to-many, proxy-to-few.

Relationship to other patterns

Seen in

  • sources/2026-04-21-planetscale-connection-pooling-in-vitesscanonical wiki first citation. Harshit Gangal (Vitess core maintainer, PlanetScale, 2023-03-27) frames Vitess's central architectural answer to unbounded application-tier connection growth: "By allowing client applications to connect only to Vttablet, the need for a connection pool at the application level was eliminated. This meant that connections could be centrally managed in Vttablet, with the maximum number of allowed connections being configurable in Vttablet, rather than growing unbounded as the number of applications increased." The VTTablet tier is the canonical 2010 YouTube-origin instance of the pattern; the 2023 post is the load-bearing wiki disclosure.

  • sources/2026-04-21-planetscale-one-million-connections — Liz van Dijk benchmarks the client-facing ceiling the multiplexing-proxy pattern enables: 1,000,000 concurrent client connections against bounded upstream MySQL pools, 62.5× above RDS MySQL's 16,000-connection ceiling.

  • sources/2026-04-21-planetscale-scaling-postgres-connections-with-pgbouncer — Ben Dicken canonicalises the Postgres analogue: PgBouncer as the multiplexing-proxy tier between clients and Postgres, with explicit max_client_conndefault_pool_sizemax_db_connectionsmax_connections configuration chain.

  • sources/2025-09-24-planetscale-processes-and-threads — Ben Dicken canonicalises the OS-substrate why: "It maintains its own pool of direct connections to the database, typically between 5 and 50. … It acts as a funnel: pushing the queries from thousands of connections into tens of connections."

Last updated · 517 distilled / 1,221 read