Articles

Connection Pooling vs Serverless Database Connections

Traditional connection pooling assumes long-lived servers. Serverless functions break that assumption — here's how proxies and edge drivers fix it.

Chisato Chisato · · 4 min read
An abstract illustration representing database systems

Connection pooling keeps a set of open database connections ready for reuse instead of opening a new one per request — a pattern that works cleanly on a long-running server, and breaks down when the thing making the connections is a serverless function that starts, runs briefly, and disappears. The mismatch between how pooling assumes an application behaves and how serverless platforms actually run is why serverless database access needed its own set of solutions.

Why connection pooling exists

Opening a database connection isn’t free. It involves a TCP handshake, often a TLS handshake, authentication, and session setup on the database side — work that can take tens of milliseconds and consume real resources on the database server, which typically caps how many concurrent connections it will accept at all. Connection pooling amortizes that cost: a pool of already-open connections sits ready, and each request borrows one, uses it, and returns it rather than paying the setup cost every time.

This works well when the pool lives inside a long-running process — a traditional application server that starts once and handles thousands of requests over its lifetime, reusing the same handful of connections the whole time.

What changes with serverless

A serverless function doesn’t work that way. Each invocation can run in a fresh execution environment, and platforms scale by spinning up more instances under load — potentially dozens or hundreds running concurrently, each with no shared memory with the others. If each instance opens its own pool of database connections, the total connection count scales with concurrent function invocations, not with any deliberate capacity plan. A traffic spike that triggers a burst of new function instances can spike the connection count on the database far past what it’s configured to accept, and functions that scale to zero when idle throw away whatever pool they’d built up anyway — there’s no long-lived process for a pool to live in.

This is the core incompatibility: connection pooling assumes a stable population of long-lived processes; serverless platforms are built around ephemeral, rapidly-scaling ones. Naively pointing a serverless function at a traditional database with a per-function connection pool tends to work fine in testing and fall over under real concurrent load.

Connection proxies (pooling at the edge)

The common fix is moving the pool out of the application entirely and into a dedicated proxy that sits between many serverless function instances and the database. Each function instance connects to the proxy — a cheap, fast connection — and the proxy maintains and multiplexes a much smaller, bounded pool of actual connections to the database behind it. The database sees a stable, capped connection count regardless of how many function instances are running concurrently; the functions see something that looks like a normal database connection without needing to manage pooling themselves.

This pattern shows up under different names depending on the platform and database — a pooler sitting in front of Postgres, a proxy layer bundled with a managed database service — but the shape is consistent: centralize pooling in one place instead of leaving every ephemeral caller to manage its own.

HTTP and WebSocket-based drivers

A different approach skips the traditional database wire protocol from the serverless function entirely and talks to the database over HTTP or WebSockets instead, routed through an edge-friendly proxy that handles the actual database connection on the far side. This matters especially for platforms like Cloudflare Workers, where the runtime doesn’t support arbitrary raw TCP sockets the way a Node.js server does — an HTTP-based driver works within that constraint, while a traditional TCP-based database client often can’t run there at all.

The tradeoff is usually a small amount of added latency per query, since requests now pass through an extra proxy hop, in exchange for functions that work reliably within serverless and edge runtime constraints without needing to manage connection state themselves.

Pooling strategies compared

In-process poolingConnection proxyHTTP/WebSocket driver
Where the pool livesInside each application instanceA separate proxy tierHandled proxy-side, over HTTP
Works well with long-running serversYesYes, but often unnecessaryNot typically needed
Works well with serverless/edgeNo — pool count scales with instancesYes — bounded regardless of instance countYes — designed for it
Requires raw TCP supportYesYes, on the proxy side onlyNo
Added latencyMinimalSmall (proxy hop)Small to moderate (HTTP overhead)

Where this fits with read replicas and sharding

Connection management is a separate concern from how data itself is scaled, but the two interact. Routing serverless read traffic through a proxy in front of a read replica applies the same principle twice over — bounding connections and distributing read load — and the same logic extends to sharded setups, where a proxy layer can also be the thing that knows how to route a given query to the correct shard, rather than pushing that routing logic into every ephemeral function instance.

It’s also worth remembering that pooling doesn’t fix everything a serverless database access pattern can strain — slow queries, missing indexes, or unbatched N+1 queries (see the N+1 query problem) still cost the same regardless of how connections are managed; pooling only removes connection setup as the bottleneck, not query performance itself.

The takeaway

Connection pooling was designed for a world of long-running application servers with a stable, predictable connection count — an assumption serverless computing breaks by design. Proxies that centralize pooling outside the function, or drivers that route over HTTP instead of raw database connections, both solve the same underlying problem: keeping the database’s connection count bounded and stable even as the number of ephemeral callers scales up and down unpredictably.

Chisato Chisato · · 4 min read

What Is Chaos Engineering? Breaking Things on Purpose

Chaos engineering deliberately injects failures into production-like systems to find weaknesses before real outages do. How it works in practice.

#DevOps #Cloud Infrastructure #Reliability
Chisato Chisato · · 6 min read

How to Deploy a Hono API on Cloudflare Workers

Deploy a Hono API on Cloudflare Workers step by step: scaffold the project, add routes, middleware, and KV storage, test locally, and ship it worldwide.

#Cloud #Serverless #Cloudflare