Cobra Developers
Blog, Infrastructure

What is serverless Postgres?

The short answer

Serverless Postgres is a hosted PostgreSQL database that separates storage from compute, so the provider can start, stop, and resize the database engine automatically. You pay mainly for what you use, the database can pause when idle, and you can usually connect over HTTP, which suits serverless hosting. The trade-offs are cold starts and a different connection model.

Two of the things we run, Regulars and our internal Social Command Center, keep their data in serverless Postgres. Both are apps on a serverless hosting platform, and both needed a real relational database that behaved well in that environment.

We did not choose it for the name. We chose it because the ordinary way of connecting to Postgres fits poorly with code that starts and stops on every request, and serverless Postgres is the database world's answer to that problem.

Here is what the term means, what it changes, and where it can bite.

What does serverless Postgres mean?

Serverless Postgres is the real PostgreSQL database, offered as a service where you do not choose or manage a server. The provider keeps your data in durable storage and attaches computing power to it only when queries arrive. Capacity grows and shrinks automatically, and billing follows usage instead of a fixed machine size.

A traditional managed database works like a rented machine. You pick a size, it runs all day, and you pay for it whether anyone queries it or not.

Serverless Postgres splits that machine into two parts. Storage holds your data and is always there. Compute is the engine that runs queries, and it can be started, stopped, and resized without touching the data. That split is what makes the other features possible.

It is still Postgres. Your tables, SQL, indexes, and transactions work the way they always have. What changes is how the engine is run and how you connect to it.

What is scale to zero?

Scale to zero means the database engine shuts down completely when nobody has queried it for a while, and starts again on the next query. While it is paused you are not paying for compute, only for stored data. It suits projects that are idle much of the day.

This matters most for the databases nobody thinks about: the staging copy, the demo, the internal tool used on weekday mornings, the side project. Under the rented-machine model each of those costs the same as a busy production database. With scale to zero, an idle database costs close to nothing to keep around.

The price is the wake-up. The first query after a pause waits while the engine starts. That delay is the database version of a cold start, and it is the main trade-off covered below. Whether a database pauses, and after how long, is usually a setting, and providers differ, so read the current documentation for the one you pick.

What is database branching?

Database branching is the ability to create an instant, separate copy of a database, including its data, the same way a developer creates a branch of code. Changes on the branch do not touch the original. It makes testing a schema change against realistic data safe and quick.

Because storage is separate from compute, a provider can make a branch without physically copying everything first. Not every serverless Postgres service offers branching, and those that do implement it differently, but where it exists it changes how a team works:

  1. Create a branch of the production database for the change you are working on.
  2. Run the migration on the branch and watch what it does to real-shaped data.
  3. Point a preview deployment of the app at the branch and test it end to end.
  4. Delete the branch when the change ships.

That lines up neatly with preview deployments on a hosting platform, which we describe in staging vs production. One caution: a branch of production contains production data. Treat it with the same care, or branch from a copy with the personal data removed.

Why do serverless apps connect to Postgres over HTTP?

Serverless apps often connect to Postgres over HTTP because their code does not stay running long enough to keep a normal database connection open. A classic Postgres connection is slow to set up and meant to be reused. An HTTP driver sends each query as a short web request instead, which suits short-lived functions.

On an always-on server, the application opens a handful of connections at startup and shares them among requests for hours. That pool is efficient, and it assumes the application lives a long time.

A serverless function may live for one request. If every request opened its own connection, a traffic spike would open hundreds at once and the database would run out. There are two common fixes: a connection pooler that sits between the functions and the database, or a driver that speaks HTTP. In our apps the driver looks like this:

import { neon } from '@neondatabase/serverless';

const sql = neon(process.env.DATABASE_URL);
const rows = await sql.query('select id, name from shops where id = $1', [shopId]);

The application code above that line does not care how the query traveled. We keep it that way on purpose, so the same code can talk to a different engine in development.

What are the trade-offs of serverless Postgres?

The main trade-offs of serverless Postgres are a delay on the first query after an idle pause, a connection model that differs from a traditional pool, costs that vary with usage, and some dependence on one provider's extra features. None is serious for most apps, but each should be a deliberate choice.

Trade-offWhat it looks likeWhat to do about it
Cold startFirst query after a pause is slowKeep production compute awake if the provider allows it
Connection modelSome features assume a long-lived sessionUse the provider's recommended driver or pooler for each case
Variable costThe bill follows usageWatch usage early and set alerts if they are offered
Provider featuresBranching and HTTP drivers are not standard PostgresKeep your SQL standard so the data can move
LatencyDatabase and app may be in different placesPut them in the same region

The lock-in point deserves a plain statement. Your data and SQL are standard Postgres and can be exported to any other Postgres host. The conveniences around them are the provider's own. If you build your workflow on those, moving means rebuilding the workflow, not the database.

And if your app is a single always-on server with steady traffic, a plain managed Postgres is simpler and perfectly good. We compare the two hosting styles in serverless vs traditional hosting.

How do you develop locally against serverless Postgres?

You develop locally against serverless Postgres by running Postgres itself on your own machine and keeping your SQL identical in both places. You can install it, run it in a container, or do what we do: run Postgres compiled to WebAssembly inside the app, with nothing to install.

Regulars and Social Command Center both use that last approach, through a library called PGlite. If a connection string is set, the app uses the hosted database. If not, it starts a local engine in the same process. The details and the limits are in our post on Postgres in WebAssembly for local development.

Frequently asked questions

Is serverless Postgres real Postgres?

Yes. It runs the PostgreSQL engine, so standard SQL, transactions, indexes, and most common extensions work as usual. The differences are in how the engine is hosted and connected to. Check that any extension you depend on is available before you commit.

Is serverless Postgres good for production?

It can be. Regulars is live on it. The things to settle first are whether production compute should ever pause, which region the database lives in, and how backups and restores work with your provider.

Does serverless Postgres only work with serverless hosting?

No. Any application that can reach the database can use it, including an ordinary long-running server using a normal connection. The HTTP driver exists for short-lived functions, and you are not required to use it.

How is it different from a managed Postgres database?

A traditional managed database is a fixed-size machine that runs all the time. Serverless Postgres starts, stops, and resizes compute for you and bills by usage.

If you are choosing a database for a new product and want a second opinion, we are glad to give one. Tell us about the project.

Who wrote this

The Cobra Developers team. We are a software studio in Arizona that builds and runs its own products and builds websites, web apps, and automation for clients. This post draws on our work on Regulars, Social Command Center. Everything here comes from projects we shipped; see all 30 of them.

guest@cobra: ~