· neon / turso / postgres

Neon vs Turso: Serverless Postgres vs SQLite (2026)

Neon wins for Postgres-first teams and Vercel preview environments. Turso wins for read-heavy SQLite workloads — but embedded replicas break on Cloudflare Workers.

By

1,802 words · 10 min read

If you are building on Postgres and need per-branch preview databases or painless connection pooling, use Neon. If your app is read-heavy and you can live with SQLite semantics, Turso is worth the detour — with one important exception: embedded replicas do not work on Cloudflare Workers. Both are “serverless” in name; they are meaningfully different in every other way.

Who this is for

Developers choosing a serverless database for a new project, or migrating off a traditional managed Postgres or SQLite host. If you already have a strong opinion about Postgres vs SQLite, you likely already have your answer.

What we tested

This article is based on public documentation, pricing pages, and official changelogs — not a controlled benchmark. We ran queries against both services in a test project, but we do not have a head-to-head latency number that survived fact-checking (see Caveats). All pricing data is from June 2026; both services reprice frequently.

Findings

The core difference

Neon is managed Postgres — specifically the open-source Neon project, which separates storage from compute, enables copy-on-write branching, and adds a serverless pricing model on top. Your SQL is standard PostgreSQL. Your ORM works without changes. Your pg driver works without changes.

Turso is a managed service built on libSQL, a fork of SQLite that adds network access, replication, and a handful of extensions. Your SQL is SQLite SQL — which is mostly ANSI SQL but has enough rough edges to matter (see “SQLite gotchas” below).

If you have an existing Postgres codebase, “does it work with Neon?” is almost never a question. With Turso, it is.

Branching

Neon’s branching is the headline feature and the one place it has no real competition. Creating a branch is an instantaneous copy-on-write operation — Neon does not copy pages; it creates a new pointer into the same storage. You can spin up a database branch for every PR in a CI pipeline and it adds essentially no cost or time.

# Neon CLI — create a branch for a PR
neonctl branches create --project-id <id> --name preview/pr-42 --parent main

Turso has no equivalent. It has read replicas and embedded replicas, but those are replication — not copy-on-write branches of schema and data.

If branching matters to your workflow, this section ends the comparison. If you are also weighing Supabase as a Postgres option, Neon vs Supabase covers that comparison directly.

Connection pooling

Neon ships PgBouncer as part of every project — enabled by appending ?pgbouncer=true to the connection string. It handles up to 10,000 clients. In serverless environments (Vercel Edge Functions, Next.js API routes), where every function invocation opens a new connection, this saves you from the “too many connections” error that kills most naive serverless Postgres setups.

Turso is connection-per-HTTP-request by design. SQLite does not have the same connection exhaustion problem Postgres does.

Scale to zero

Both services scale to zero. Neon’s compute pauses after 5 minutes of inactivity on the free tier; cold start is a few hundred milliseconds. On paid tiers you can disable auto-suspend entirely or tune the timeout.

Turso databases also sleep after inactivity. Cold start behavior is comparable.

Embedded replicas — and why they do not work on Cloudflare Workers

Turso’s most interesting feature is embedded replicas: your app holds a local SQLite file that stays in sync with the remote primary. Reads hit the local file (zero network round-trip); writes go through the HTTP API to the primary and sync back. For long-lived processes — a Node.js server running for hours, an Electron app, a background job — this is a genuine win.

import { createClient } from "@libsql/client";

const client = createClient({
  url: "file:local.db",
  syncUrl: process.env.TURSO_DATABASE_URL,
  authToken: process.env.TURSO_AUTH_TOKEN,
  syncInterval: 60, // seconds
});

await client.sync(); // pull latest from primary
const result = await client.execute("SELECT * FROM products WHERE active = 1");

The catch: embedded replicas require a writable filesystem. Cloudflare Workers do not provide one. If you deploy to Workers, you must use @libsql/client/web — HTTP-only mode — which means every read goes over the network. The edge-proximity advantage disappears. Turso’s documentation acknowledges this; it is not a bug, but it is a sharp edge worth knowing before you commit to the architecture. If your target is Cloudflare Workers specifically, Turso vs D1 covers the direct comparison between Turso and Cloudflare’s native SQLite option.

Neon on Cloudflare Workers is a different trade-off. Neon recommends Hyperdrive (Cloudflare’s connection proxy) with pg ≥ 8.16.3 for acceptable latency. You are still doing Postgres over TCP, but Hyperdrive caches connection setup and pools at the edge.

// Neon on Cloudflare Workers via Hyperdrive
import { Pool } from "pg";

export default {
  async fetch(request: Request, env: { HYPERDRIVE: Hyperdrive }) {
    const pool = new Pool({ connectionString: env.HYPERDRIVE.connectionString });
    const { rows } = await pool.query("SELECT now()");
    await pool.end();
    return Response.json(rows[0]);
  },
};

Neither option is zero-latency. Neon adds a TCP round-trip through Hyperdrive. Turso in web mode adds an HTTP round-trip to the nearest replica. If edge latency is truly critical, you need a different database entirely — D1 or an on-device store. For a broader look at when each edge database option is the right fit, Edge database tradeoffs: when latency is a lie maps out the full landscape.

Pricing

TierNeonTurso
Free100 CU-hrs/mo, 0.5 GB storage, 10 branches, mandatory scale-to-zero after 5 min100 databases, 500M row reads/mo, 10M writes/mo, 5 GB total
~$25/moLaunch: $0.106/CU-hr + $0.35/GB-mo, no minimum feeScaler: $24.92/mo flat — 24 GB storage, 100B row reads, 100M writes

A few things worth unpacking.

Neon’s free tier is compute-bounded, not data-bounded. 100 compute-unit-hours sounds generous until you understand the unit. Roughly: 1 CU ≈ 4 GB RAM; the smallest compute size is 0.25 CU (1 GB RAM). An active compute burns compute-unit-hours proportional to the size you allocate. A hobby project with a few hours of daily traffic at the minimum compute size fits comfortably. A project running at 1 CU continuously hits the ceiling fast.

Turso’s free tier is built for multi-tenant apps. 100 separate databases is enough to give every user in a small SaaS their own isolated SQLite. This is a real use case: per-user databases are a Turso design pattern, enabled by libSQL’s lightweight footprint. Neon does not have a comparable model at this price — branches share storage and compute, and you pay per project.

Neon’s $25 tier has no floor. You pay for what you use. A project that scales to zero and logs 10 hours of active compute a month costs $1.06 in compute. Turso Scaler is a flat $24.92 regardless of how little you use it.

Feature table

FeatureNeonTurso
SQL dialectPostgreSQLSQLite / libSQL
Copy-on-write branchingYes (instantaneous)No
Connection poolingPgBouncer built-in (10,000 clients)N/A (HTTP per request)
Scale to zeroYes (configurable timeout)Yes
Embedded replicasNoYes (requires writable filesystem)
Cloudflare WorkersHyperdrive + pg ≥ 8.16.3@libsql/client/web — HTTP only, no embedded replicas
Auth serviceNeon Auth (beta)None built-in
Free tier databases1 project, 10 branches100 databases
Open sourceYes (Neon)Yes (libSQL)

SQLite gotchas

If Turso is your first production SQLite deployment, these will bite you:

1. Typeless by default. SQLite uses “type affinity” — not enforcement. An INTEGER column accepts text without error unless you opt into STRICT tables. Most tutorials skip STRICT; you need to opt in explicitly:

CREATE TABLE products (
  id    INTEGER NOT NULL,
  price REAL    NOT NULL,
  sku   TEXT    NOT NULL
) STRICT;

2. ALTER TABLE is severely limited. You cannot change a column’s type, rename a column (before SQLite 3.25.0), or add constraints after creation. Schema evolution requires rewriting tables, which migration tools like Drizzle handle — but it surprises teams expecting Postgres-style ALTER COLUMN.

3. Single writer at a time. libSQL adds network access but keeps SQLite’s single-writer model. In embedded replica mode, all writes go to the remote primary and queue there. Under high write concurrency, you will see latency build before you see errors.

4. Foreign keys are off by default. You must run PRAGMA foreign_keys = ON; on every connection — or configure it at the client level — otherwise your referential integrity constraints do nothing.

5. No JSONB. SQLite stores JSON as text. The json_* functions work for extraction and path queries, but there is no binary JSON type and no index-on-path support comparable to Postgres’s jsonb GIN indexes.

6. Silent type coercion. In many contexts, '123' = 123 evaluates to true. This hides comparison bugs that Postgres would catch at query time.

None of these are showstoppers in isolation. Together, they add up to a meaningful migration cost if your codebase relies on Postgres-specific features — arrays, enums, JSONB, full-text search vectors, or window functions with Postgres-specific syntax.

Verdict

Pick Neon if:

  • You are on Postgres and want to stay on Postgres.
  • You use Vercel or a similar platform and want per-PR preview databases.
  • You need reliable connection pooling without running your own PgBouncer.
  • Your team uses Postgres-specific features (JSONB, arrays, pg_trgm, full-text, enums).

Pick Turso if:

  • Your app is read-heavy and your read/write ratio strongly favors reads.
  • You need many small, isolated databases cheaply — per-user DBs, multi-tenant SaaS.
  • You are deploying to Node.js, Bun, or Deno (not Cloudflare Workers) and want embedded replicas.
  • You are comfortable with SQLite’s constraints and your schema is migration-friendly.

Do not pick Turso for Cloudflare Workers expecting embedded replicas. You will get HTTP-only mode and a network round-trip. If that is acceptable, fine — but benchmark it first.

Caveats

No verified latency benchmark. We looked for a credible head-to-head benchmark and did not find one that survived fact-checking. The most-cited comparison relies on raw data we could not independently verify. If latency is your deciding factor, run your own test on your own workload and deployment target.

Pricing changes fast. Both services have repriced in the past 12 months. The numbers above are from June 2026. Check the current pricing pages before committing to a tier.

No affiliate links. Neither Neon nor Turso has a publicly documented affiliate program at the time of writing. There are no affiliate links in this article.

References

  1. Neon branching documentation
  2. Neon pricing and plans
  3. Turso pricing
  4. Turso embedded replicas introduction
  5. Cloudflare Workers × Neon | Cloudflare Workers × Turso