Connection Pooling with Serverless Functions

This guide shows best practices for connecting to relational databases with Serverless Functions.

Connecting to Databases

Consider a traditional Node.js server connecting to a SQL database. When a request is made to your application, the server opens a connection to the database to execute a SQL query. After completion, the data is returned and the connection is closed.

At a large scale, creating a connection to your database on every request can exhaust server memory usage and hit the maximum number of connections allowed. One solution is to pay for more memory, and another is to use connection pooling.

Connecting to a traditional server with no connection pooling.
Connecting to a traditional server with no connection pooling.
Connecting to a traditional server with no connection pooling.
Connecting to a traditional server with no connection pooling.

What is Connection Pooling?

Pooling is one solution to prevent your application from exhausting all available database connections. Rather than opening a connection with every request, connection pooling allows us to designate a single "pooler" that keeps an active connection to the database. When a request is made that would read from the database, the pooler finds an available connection rather than creating a new connection.

Using connection pooling with a traditional server.
Using connection pooling with a traditional server.
Using connection pooling with a traditional server.
Using connection pooling with a traditional server.

Databases with Serverless Functions

Traditional relational databases were built for long-running compute instances, not the ephemeral nature of serverless functions.

Serverless Functions are stateless and asynchronous. They are not designed for persistent connections to a database. It's easier to exhaust available database connections because functions scale immediately and infinitely when traffic spikes occur.

When a function is invoked, a connection to the database is opened. Upon completion, the connection is closed. Similar to a Node.js server, we want to maximize connection reuse. However, this requires different solutions in serverless environments than connection pooling.

serverless-no-pooling.png
serverless-no-pooling-1.png

Open source solutions like serverless-mysql and serverless-pg attempt to bring connection pooling to serverless environments. By storing variables outside the scope of the function, these solutions can create a connection pool in between invocations. However, there is no guarantee of connection reuse. Therefore, we recommend other solutions.

HTTP Database APIs

Services Vercel Postgres, Supabase (which uses PostgREST), Hasura, or AWS Aurora Data API expose a managed API layer on top of the underlying database. This allows you to execute SQL statements from any application over HTTP without using any drivers or plugins. Further, you don’t need to manage a connection pool or VPC.

Using an HTTP API for your database with Serverless Functions.
Using an HTTP API for your database with Serverless Functions.
Using an HTTP API for your database with Serverless Functions.
Using an HTTP API for your database with Serverless Functions.

These Data APIs don’t require a persistent connection to the database. Instead, they provide a secure HTTP endpoint where you can run your SQL statements without managing connections.

Get started with Vercel Postgres.

Modern Databases with High Connection Limits

New database providers like PlanetScale can handle millions of connections, making them an attractive solution for usage inside Serverless Functions.

Get started with PlanetScale and Vercel in minutes.

Vercel Storage Solutions

Vercel has a suite of storage products, including:

See our docs to learn which product best suits your use-case.

Other Data Storage Solutions

Depending on your data workload, you might explore using other storage solutions that don’t require persistent connections. For example DynamoDB.

Edge Functions

Vercel also offers Edge Functions, which use a slim runtime that doesn’t allow all Node.js APIs. Therefore, when using databases with Edge Functions, you are forced to use solutions that align with the best practices for connecting to databases (like using HTTP-based APIs or connectionless data providers).

Couldn't find the guide you need?