Loading…
Loading…
Why serverless databases like PlanetScale and Neon are changing how we build full-stack serverless architectures.
Tags
Traditional databases were designed for long-running servers with persistent connections. Serverless functions create thousands of short-lived connections that overwhelm conventional connection pools. Serverless databases like Neon, PlanetScale, and Turso solve this by separating compute from storage, offering HTTP-based query interfaces, and scaling to zero when idle. This guide compares the major players, explains their architectures, and helps you choose the right one for your stack.
Serverless compute has been production-ready for years. You can deploy an API to AWS Lambda or Vercel Edge Functions and handle anything from zero to millions of requests without managing servers. But the moment your function tries to connect to a database, the serverless illusion breaks.
A PostgreSQL instance has a default connection limit of 100. A single Vercel deployment can spawn hundreds of concurrent function invocations during a traffic spike, each one trying to open its own database connection. The database rejects connections, your functions throw errors, and your users see 500 pages.
The traditional fix -- running PgBouncer or a similar connection pooler in front of your database -- works, but now you are managing infrastructure again. You need to provision the pooler, keep it running, and scale it independently. You have re-introduced the "server" that serverless was supposed to eliminate.
Serverless databases solve this at the platform level. They are designed from the ground up for ephemeral, high-concurrency workloads.
Traditional databases run compute (query parsing, execution, optimization) and storage (reading and writing data to disk) on the same machine. Serverless databases separate these concerns:
This separation enables two key features: scale-to-zero (no compute running means no compute charges) and instant scale-up (new compute nodes can attach to the storage layer immediately).
Neon is a fully managed PostgreSQL service built on a custom storage engine. It is wire-compatible with PostgreSQL, meaning your existing Postgres tools, ORMs, and drivers work without changes.
// Using Neon's serverless driver (HTTP-based, no TCP connection needed)
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL);
export async function getProducts() {
const products = await sql`SELECT * FROM products WHERE active = true`;
return products;
}Neon's serverless driver sends queries over HTTP/WebSocket instead of a persistent TCP connection, which is ideal for edge functions that cannot maintain TCP sockets.
Key features:
// Neon branching in a CI pipeline
// Each PR gets its own database branch with production data
const branchName = `preview-pr-${prNumber}`;
// Created via Neon API: POST /projects/{id}/branchesPlanetScale is built on Vitess, the same technology that scaled YouTube's MySQL infrastructure. It provides a serverless MySQL experience with a unique approach to schema migrations.
// PlanetScale with Drizzle ORM
import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { connect } from '@planetscale/database';
const connection = connect({
url: process.env.DATABASE_URL,
});
const db = drizzle(connection);
const users = await db.select().from(usersTable).where(eq(usersTable.active, true));PlanetScale's standout feature is non-blocking schema changes. Traditional MySQL schema migrations lock tables during ALTER TABLE operations. PlanetScale uses Vitess's online DDL to apply schema changes without downtime:
Turso takes a different approach by building on libSQL, a fork of SQLite. Instead of a centralized database with a connection pooler, Turso replicates your database to edge locations worldwide.
// Turso with libSQL client
import { createClient } from '@libsql/client';
const db = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const result = await db.execute({
sql: 'SELECT * FROM posts WHERE published = ?',
args: [true],
});Turso is compelling for read-heavy workloads where latency matters. Your data is replicated to edge locations, so reads are served from the nearest replica. Writes go to the primary and propagate to replicas asynchronously.
Each serverless database handles connection pooling differently:
Neon offers both a traditional pooled connection string (via PgBouncer built into the platform) and a serverless HTTP driver. Use the pooled string for server-based applications and the serverless driver for edge functions.
PlanetScale uses an HTTP-based protocol exclusively. There are no TCP connections to manage. Every query is a stateless HTTP request, which maps perfectly to serverless function lifecycles.
Turso uses HTTP for its remote connections and embedded libSQL for local development. The client library handles reconnection and retries transparently.
Next.js on Vercel + Prisma → Neon (best Prisma integration, Postgres compatibility)
Nuxt/SvelteKit on Cloudflare → Turso (edge replication, SQLite simplicity)
Remix on AWS Lambda → PlanetScale (MySQL, battle-tested at scale)
Astro with simple data needs → Turso (embedded mode for development, remote for prod)
Serverless databases have cold starts just like serverless functions. When a Neon compute node wakes from scale-to-zero, the first query takes 300-500ms instead of the usual 5-10ms.
Strategies to mitigate this:
// Option 1: Keep the database warm with a cron job
// Runs every 4 minutes to prevent Neon from suspending
export async function warmDatabase() {
await sql`SELECT 1`;
}
// Option 2: Use Neon's autosuspend configuration
// Set a longer delay before suspending (e.g., 10 minutes)
// This is configured in the Neon dashboard, not in code
// Option 3: Accept the cold start for non-critical paths
// Pre-warm only for routes where latency mattersNot all database drivers work in edge runtimes (Cloudflare Workers, Vercel Edge Functions). Edge runtimes do not support Node.js APIs like net and tls, which means traditional TCP-based database drivers fail.
| Database | Edge Compatible Driver | Protocol |
|---|---|---|
| Neon | @neondatabase/serverless | HTTP/WebSocket |
| PlanetScale | @planetscale/database | HTTP |
| Turso | @libsql/client | HTTP |
Serverless databases charge differently from traditional managed databases:
The key difference from traditional databases: you pay for actual usage, not provisioned capacity. A development database that sits idle costs almost nothing.
Assuming zero cold start latency. Scale-to-zero saves money but adds latency to the first request. Profile your cold start times and decide whether the cost savings justify the latency penalty for your use case.
Using TCP drivers on edge runtimes. This is the most common error. If you deploy to Cloudflare Workers or Vercel Edge Functions, you must use the HTTP-based driver, not the standard pg or mysql2 driver.
Ignoring read replica lag. Turso and other replicated databases have eventual consistency. A write to the primary may take milliseconds to propagate to edge replicas. If a user writes data and immediately reads it from a different replica, they may not see their own write. Use the primary for read-after-write scenarios.
Not setting connection timeouts. Even with HTTP-based drivers, queries can hang. Always set reasonable timeouts:
const sql = neon(process.env.DATABASE_URL, {
fetchOptions: {
signal: AbortSignal.timeout(5000), // 5 second timeout
},
});Over-relying on branching for testing. Database branches are excellent for preview deployments, but they should not replace proper test fixtures and seed data. Branches inherit production data, which may contain PII.
Serverless databases are the right choice when:
Stick with traditional managed databases when:
Serverless functions like AWS Lambda create thousands of rapid, short-lived connections that overwhelm traditional connection pools designed for persistent, long-running server processes.
They use HTTP-based connection pooling at the platform level, eliminating the need for persistent TCP connections and handling thousands of ephemeral serverless function connections seamlessly.
Scale-to-zero means the database separates compute from storage, so when no queries are running, compute resources shut down entirely and you only pay for storage, then instantly spin up when traffic returns.
Collaboration
I help startups and established companies design, build, and scale world-class digital products. From deep technical architecture to pixel-perfect UI: let's bring your vision to life.
Learn how to design stable API contracts between Micro-Frontends and Backend-for-Frontend layers with versioning, ownership boundaries, error handling, and schema governance.
An architectural deep dive into using Next.js as a Backend-for-Frontend, including route handlers, server components, auth boundaries, caching, and service orchestration.
A practical guide to using Next.js Cache Components and Partial Prerendering in real applications, with tradeoffs, cache strategy, and freshness considerations.