Turso vs PlanetScale vs Neon: Serverless Database Showdown 2026
·PkgPulse Team
TL;DR
Neon won the developer-first Postgres race in 2026 — branching, autoscale-to-zero, and the best DX. PlanetScale changed pricing in 2024 (killing the free tier), which drove many developers to Neon and Turso. Turso is the edge SQLite play — co-locate databases near users for sub-10ms reads, with the embedded replicas feature for literally running the database in your app process. For most SaaS apps: Neon (Postgres, generous free tier). For global edge apps needing low latency: Turso. PlanetScale: still solid for MySQL shops with branching workflows.
Key Takeaways
- Neon: serverless Postgres, branching per GitHub branch, autoscale-to-zero, generous free tier
- Turso: libSQL (SQLite fork), edge distribution, embedded replicas, Drizzle/LibSQL client
- PlanetScale: serverless MySQL, schema branching, free tier eliminated in 2024
- Pricing shift: PlanetScale's 2024 pricing change hurt adoption; Neon + Turso benefited
- For Next.js on Vercel: Neon (Postgres Serverless is the official Vercel partner)
- For edge functions: Turso (SQLite runs at the edge, Postgres doesn't)
Downloads
| Package | Weekly Downloads | Trend |
|---|---|---|
@neondatabase/serverless | ~300K | ↑ Fast growing |
@libsql/client (Turso) | ~200K | ↑ Growing |
@planetscale/database | ~250K | ↓ Declining |
Neon: Serverless Postgres
npm install @neondatabase/serverless
# Or use with Drizzle:
npm install drizzle-orm @neondatabase/serverless
// Neon serverless client (optimal for serverless/edge):
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// Works in Vercel Edge Functions (no persistent connection):
export async function GET(req: Request) {
const rows = await sql`
SELECT id, name, email FROM users
WHERE plan = 'pro'
ORDER BY created_at DESC
LIMIT 10
`;
return Response.json(rows);
}
// With Drizzle ORM (recommended):
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql);
// All Drizzle operations work:
const users = await db.select().from(usersTable).where(eq(usersTable.plan, 'pro')).limit(10);
Neon Branching
# Neon CLI:
npm install -g @neondatabase/cli
neonctl auth
# Create a branch for your PR:
neonctl branches create --name feature/new-user-schema
# Run migrations on the branch:
DATABASE_URL=$(neonctl branches get feature/new-user-schema --output json | jq -r '.connection_string') \
npx drizzle-kit migrate
# Merge branch (after PR merges):
neonctl branches delete feature/new-user-schema
GitHub Actions integration:
- name: Create Neon branch
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ vars.NEON_PROJECT_ID }}
branch_name: preview/${{ github.event.pull_request.number }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run migrations on branch
env:
DATABASE_URL: ${{ steps.create-branch.outputs.db_url }}
run: npx drizzle-kit migrate
Neon Pricing
Free tier:
→ 0.5 GB storage
→ 191.9 compute hours/month (autoscale-to-zero helps)
→ 1 project, 10 branches
→ Postgres 16
Launch: $19/month
→ 10 GB storage
→ 300 compute hours
→ Unlimited branches
Scale: $69/month
→ 50 GB storage
→ Compute scales automatically
Turso: Edge SQLite
npm install @libsql/client
# Or with Drizzle:
npm install drizzle-orm @libsql/client
// Turso client:
import { createClient } from '@libsql/client';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
// Execute SQL:
const result = await client.execute({
sql: 'SELECT * FROM users WHERE plan = ? LIMIT 10',
args: ['pro'],
});
// With Drizzle ORM:
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN!,
});
export const db = drizzle(client);
Turso Embedded Replicas (The Killer Feature)
// Embedded replica: database runs in your app process
// Reads hit local SQLite file, writes sync to Turso cloud:
import { createClient } from '@libsql/client';
const client = createClient({
url: 'file:/tmp/mydb.sqlite', // Local SQLite replica
syncUrl: process.env.TURSO_DATABASE_URL, // Sync from Turso
authToken: process.env.TURSO_AUTH_TOKEN,
});
// Sync latest changes:
await client.sync();
// Reads: zero network latency (local file)
const fastRead = await client.execute('SELECT * FROM users WHERE id = ?', [userId]);
// Writes: go to Turso cloud, then sync back
await client.execute('UPDATE users SET plan = ? WHERE id = ?', ['pro', userId]);
Embedded replica use case:
→ Read latency: <1ms (local SQLite)
→ Write latency: ~50ms (network to Turso)
→ Best for: high-read apps (blog, product catalog)
→ Works in: Cloudflare Workers, Lambda, Bun, Node.js
Turso Pricing
Free tier:
→ 500 databases
→ 9 GB total storage
→ 1 billion row reads/month
→ 25 million row writes/month
Scaler: $29/month
→ 10,000 databases (multi-tenant!)
→ 24 GB storage
→ 10 GB network egress
PlanetScale: MySQL with Branching
npm install @planetscale/database
// PlanetScale client:
import { connect } from '@planetscale/database';
const conn = connect({
host: process.env.DATABASE_HOST,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
});
const results = await conn.execute('SELECT * FROM users WHERE plan = ?', ['pro']);
PlanetScale Pricing (2026)
⚠️ Free tier eliminated in March 2024
Scaler: $39/month
→ 10 GB storage
→ 1 billion row reads/month
→ 10 million row writes/month
For comparison, Neon ($19/mo) and Turso (free tier) are cheaper
for most startup use cases.
Comparison Table
| Neon | Turso | PlanetScale | |
|---|---|---|---|
| Engine | PostgreSQL | SQLite (libSQL) | MySQL |
| Edge compatible | ✅ (HTTP API) | ✅ (native) | ✅ (HTTP API) |
| Branching | ✅ | ❌ | ✅ |
| Embedded replicas | ❌ | ✅ | ❌ |
| Free tier | ✅ Generous | ✅ Very generous | ❌ Eliminated 2024 |
| Prisma support | ✅ | Limited | ✅ |
| Drizzle support | ✅ | ✅ | ✅ |
| Autoscale | ✅ to zero | N/A | ✅ |
| Multi-tenant (per-user DB) | ❌ | ✅ (500 free DBs) | ❌ |
Decision Guide
Choose Neon if:
→ Postgres is your standard
→ Next.js on Vercel (official partnership)
→ Need database branching for CI/CD
→ Free tier is important (most startup use)
Choose Turso if:
→ Multi-tenant SaaS needing per-user database
→ Global edge deployment with low read latency
→ SQLite is acceptable (most SQL features work)
→ Cloudflare Workers (libSQL runs at the edge)
Choose PlanetScale if:
→ MySQL is required (legacy code, existing data)
→ Schema branching workflow is already established
→ Budget for $39+/month
→ Not price-sensitive
Compare database packages on PkgPulse.