Turso vs PlanetScale vs Neon: Serverless Databases for TypeScript 2026
Databricks acquired Neon in early 2026 and cut compute costs 15-25%. PlanetScale killed its free tier in 2024 but remains the reliability benchmark for MySQL-based SaaS. Turso replicates SQLite to edge locations globally, cutting read latency by up to 90% for distributed applications. These aren't the same database in different wrappers — they're distinct architectural choices with different tradeoffs on cost, latency, and scale.
TL;DR
Neon for serverless Postgres with a free tier, schema branching, and scale-to-zero — the default choice for new TypeScript projects on Postgres. PlanetScale for production MySQL workloads where uptime guarantees matter more than free tier savings. Turso when SQLite at the edge fits your workload: read-heavy apps, multi-tenant databases, or Cloudflare Workers deployments. For most new applications in 2026, Neon is the pragmatic starting point.
Key Takeaways
- Neon: Serverless Postgres, free tier (100 compute-hours/month, 0.5 GB), acquired by Databricks 2026
- PlanetScale: No free tier since April 2024; plans from $39/month (Scaler Pro)
- Turso: SQLite + libSQL, free tier (9 GB, 500 databases), $4.99/month Developer plan
- Neon: Schema branching like Git branches for your database — dev/staging/PR environments
- PlanetScale: Database branching, non-blocking schema changes, MySQL compatibility
- Turso: Edge replicas reduce read latency by up to 90%; works on Cloudflare Workers natively
- All three have TypeScript SDKs and work with Drizzle, Prisma, and raw SQL clients
The Serverless Database Landscape
Traditional databases run on dedicated servers. Serverless databases add:
- Scale-to-zero: The database pauses when idle (reducing costs for low-traffic apps)
- Connection pooling: Managed by the platform (no PgBouncer setup)
- Branching: Database schema branches for development environments
- Edge proximity: Replicas close to users for lower latency
The tradeoff: cold starts on serverless databases add latency after periods of inactivity.
Neon
Type: Serverless PostgreSQL GitHub stars: 16K (neon repo) Creator: Neon Inc. (acquired by Databricks, Jan 2026)
Neon is purpose-built serverless Postgres. It separates compute from storage, enabling true scale-to-zero — the database pauses when idle and resumes in ~300ms on the next connection.
Connection
import { neon } from '@neondatabase/serverless';
const sql = neon(process.env.DATABASE_URL!);
// Executes a query against your Neon database
const users = await sql`SELECT * FROM users WHERE active = true`;
With Drizzle ORM
import { drizzle } from 'drizzle-orm/neon-http';
import { neon } from '@neondatabase/serverless';
import { users } from './schema';
const sql = neon(process.env.DATABASE_URL!);
const db = drizzle(sql);
const activeUsers = await db
.select()
.from(users)
.where(eq(users.active, true));
With Prisma
// schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
import { PrismaClient } from '@prisma/client';
const prisma = new PrismaClient();
// Works with Neon out of the box
const users = await prisma.user.findMany({ where: { active: true } });
Neon Branching
Neon's killer feature: database branches for development environments.
# Install Neon CLI
npm install -g neonctl
# Create a branch for a feature (copies production data)
neonctl branch create --name feature/user-auth --parent main
# Use branch in dev environment
neonctl connection-string feature/user-auth
# postgres://user:pass@ep-xxx.us-east-2.aws.neon.tech/main?sslmode=require
# Delete branch when done
neonctl branch delete feature/user-auth
This enables pull-request-level database environments: each PR gets its own database branch with a copy of the schema (and optionally data), so developers test schema changes safely.
Neon Pricing (2026)
| Plan | Compute | Storage | Price |
|---|---|---|---|
| Free | 100 compute-hours/month | 0.5 GB (5 GB across projects) | Free forever |
| Launch | Autoscaling 0.25-4 CU | 10 GB | ~$19/month |
| Scale | Autoscaling 0.25-8 CU | 50 GB | ~$69/month |
Databricks' 2026 acquisition cut compute costs 15-25% across all tiers.
Neon Limitations
- Cold starts: ~300ms latency after idle periods
- PostgreSQL only (no MySQL or SQLite)
- Maximum database size limits on lower tiers
- Scale-to-zero can surprise users with first-request latency
PlanetScale
Type: Serverless MySQL (Vitess-based) Creator: PlanetScale Inc. Technology: Vitess (powers YouTube's MySQL at scale)
PlanetScale uses Vitess — the MySQL sharding infrastructure built at YouTube and used by GitHub, Slack, and Square. It offers MySQL compatibility with horizontal scaling built in.
Connection
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 active = ?', [true]);
console.log(results.rows);
With Drizzle ORM
import { drizzle } from 'drizzle-orm/planetscale-serverless';
import { connect } from '@planetscale/database';
import { users } from './schema';
const connection = connect({
host: process.env.DATABASE_HOST,
username: process.env.DATABASE_USERNAME,
password: process.env.DATABASE_PASSWORD,
});
const db = drizzle(connection);
const activeUsers = await db
.select()
.from(users)
.where(eq(users.active, true));
PlanetScale Branching (Non-Blocking Schema Changes)
PlanetScale's original innovation: schema changes via deploy requests that don't lock tables.
# PlanetScale CLI
pscale branch create mydb add-user-avatar
pscale shell mydb add-user-avatar
# In the SQL shell:
ALTER TABLE users ADD COLUMN avatar_url VARCHAR(500);
# Open a deploy request (like a pull request for schema changes)
pscale deploy-request create mydb add-user-avatar
# Merge the schema change without table locking
pscale deploy-request deploy mydb 1
PlanetScale's foreign key constraint tradeoff: by default, PlanetScale disables foreign key constraints (referential integrity is handled at the application level) to enable horizontal sharding. Some teams find this acceptable; others don't.
PlanetScale Pricing (2026)
| Plan | Price | Includes |
|---|---|---|
| PS-10 (single node) | $5/month | 1 primary, limited |
| Scaler Pro | $39/month | Autoscaling, branching, support |
| Enterprise | Custom | Multi-region, SLA |
No free tier since April 2024. The $5/month single-node plan is limited and not suitable for production.
PlanetScale Strengths
- Production reliability track record (Vitess powers YouTube, GitHub, Slack)
- Non-blocking schema changes (no table locks during ALTER TABLE)
- MySQL compatibility: migrate existing MySQL applications with minimal changes
- Horizontal scaling built-in for multi-tenant SaaS
PlanetScale Limitations
- No free tier (significant disadvantage vs Neon and Turso for exploration)
- MySQL only (no Postgres)
- Foreign keys disabled by default
- Schema branching requires CLI workflow (more friction than Neon's API/dashboard approach)
Turso
Type: SQLite at the edge (libSQL) GitHub stars: 13K+ (libSQL repo) Creator: ChiselStrike / Turso team Technology: libSQL (open-source fork of SQLite)
Turso takes SQLite — the most deployed database engine in the world — and makes it available as a distributed, edge-replicated database service. The underlying technology is libSQL, a Turso-maintained fork of SQLite that adds replication.
Connection
import { createClient } from '@libsql/client';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const result = await client.execute('SELECT * FROM users WHERE active = 1');
console.log(result.rows);
With Drizzle ORM
import { drizzle } from 'drizzle-orm/libsql';
import { createClient } from '@libsql/client';
import { users } from './schema';
const client = createClient({
url: process.env.TURSO_DATABASE_URL!,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const db = drizzle(client);
const activeUsers = await db
.select()
.from(users)
.where(eq(users.active, true));
Edge Replication
Turso's primary advantage: SQLite databases replicated to edge locations globally.
// Turso creates read replicas in 35+ regions
// Your primary write database is in one region
// Read replicas are in every region you choose
// From a Cloudflare Worker in Singapore:
// Read query → Singapore edge replica (~2ms)
// Write query → Primary in us-east-1 (~180ms)
// vs. centralized database:
// Read query → us-east-1 from Singapore (~180ms)
// Write query → us-east-1 from Singapore (~180ms)
For read-heavy applications with global users, this latency reduction (90% on reads) is significant.
Multi-Tenant Databases
Turso supports up to 500 databases on the free tier, making it ideal for multi-tenant architectures where each tenant gets their own isolated database:
// Create a database per tenant
import { createClient as createTursoClient } from '@libsql/turso';
const turso = createTursoClient({ token: process.env.TURSO_API_TOKEN });
// Create a database for a new tenant
const db = await turso.databases.create({
name: `tenant-${tenantId}`,
location: 'iad', // Primary location
});
// Connect to the tenant's database
const client = createClient({
url: db.hostname,
authToken: await turso.databases.createToken(db.name),
});
Turso Pricing (2026)
| Plan | Price | Databases | Storage | Edge Replicas |
|---|---|---|---|---|
| Free | $0 | 500 | 9 GB | 3 locations |
| Developer | $4.99/month | Unlimited | 24 GB | Unlimited |
| Scaler | $29/month | Unlimited | 108 GB | Unlimited |
Turso Limitations
- SQLite only (no PostgreSQL, MySQL)
- Write-heavy workloads don't benefit (writes go to primary region)
- SQLite limitations: no full-text search without extensions, different than Postgres behavior
- Smaller ecosystem than Postgres (fewer extensions, tools, expertise)
Latency Comparison
| Scenario | Neon | PlanetScale | Turso |
|---|---|---|---|
| Cold start | ~300ms | ~50ms | ~5ms |
| Local read (same region) | ~5ms | ~5ms | ~2ms |
| Remote read (cross-region) | ~150-200ms | ~150-200ms | ~5-20ms (edge) |
| Write (any scenario) | ~10ms | ~10ms | ~15ms (to primary) |
Turso's edge replication only helps reads — and only when edge replicas are deployed near users.
Choosing the Right Database
Choose Neon if:
- You want PostgreSQL with a free tier
- Schema branching for PR environments fits your workflow
- You're building on any standard stack (Next.js, Remix, Express)
- Your team knows Postgres and prefers to stay in that ecosystem
- Scale-to-zero cost savings matter for low-traffic applications
Choose PlanetScale if:
- You need MySQL compatibility (migrating existing MySQL apps)
- Production reliability and uptime guarantees are non-negotiable
- Non-blocking schema changes are important for zero-downtime deployments
- You're running high-traffic SaaS that needs Vitess horizontal scaling
Choose Turso if:
- Edge deployment (Cloudflare Workers, Deno Deploy, Fastly) is your target
- Read-heavy global workloads where latency matters
- Multi-tenant architecture where each tenant gets an isolated SQLite database
- SQLite is acceptable (scripts, embedded data, simpler schemas)
The 2026 Default
For most new TypeScript projects: Neon. The free tier is generous, Postgres is the most supported database in the TypeScript ecosystem (Drizzle, Prisma, Kysely all prioritize Postgres), and the schema branching feature is legitimately useful for teams managing migrations across environments.
Turso is the right call when you're building on edge runtimes or need the multi-tenant database-per-tenant pattern. PlanetScale is the right call when production reliability beats all other concerns and your team has MySQL expertise.
Compare database clients and ORMs on PkgPulse.
See the live comparison
View turso vs. planetscale vs neon on PkgPulse →