Best SaaS Boilerplates with Neon or PlanetScale in 2026
TL;DR
Neon (serverless Postgres) and PlanetScale (serverless MySQL) solve the same problem: databases that scale to zero, branch like Git, and handle connection pooling for serverless environments. Neon is the newer and faster-growing option; PlanetScale switched to a paid-only model in 2024 but remains excellent. The boilerplates that work best with these: T3 Stack (Prisma native), Drizzle-based starters (better raw performance), and any Next.js boilerplate that supports connection pooling configuration. Here's how each database fits into the boilerplate ecosystem.
Key Takeaways
- Neon: serverless Postgres, Git-like branching, free tier generous — growing fast in 2025-2026
- PlanetScale: serverless MySQL, no foreign keys enforced (schema changes without locking)
- T3 Stack + Neon: the most common combination — Prisma + serverless Postgres
- Drizzle + Neon: gaining ground — better performance, smaller bundle, edge-native
- Branching: both support DB branching — a killer feature for development workflows
- Connection pooling: critical for serverless — both handle it natively
Neon vs PlanetScale: Quick Comparison
Neon:
→ Serverless Postgres
→ Autoscaling: scales to 0 when idle (pay only when used)
→ Branching: create DB branch per PR (like Git)
→ Free tier: 10GB storage, shared compute
→ Compatible with: any Postgres client, Prisma, Drizzle, Kysely
→ Connection pooling: built-in via Neon Serverless Driver
PlanetScale:
→ Serverless MySQL (Vitess-based)
→ No foreign key enforcement (schema changes without downtime)
→ Branching: deploy requests (like PRs for schema changes)
→ Free tier: removed in 2024 (paid from $39/month)
→ Compatible with: Prisma (MySQL), Drizzle, TypeORM
→ Connection pooling: built-in
For new projects in 2026: Neon wins on price and Postgres compatibility.
PlanetScale still wins for MySQL-specific use cases or existing MySQL stacks.
The Dev Workflow Killer Feature: Branching
Both databases let you branch your database the same way you branch your code:
# Neon branching workflow:
# 1. Create branch for your feature:
neon branches create --name feature/new-schema
# 2. Run migrations on branch:
DATABASE_URL="neon-branch-connection-string" npx prisma migrate dev
# 3. Test changes without affecting main DB
# 4. Merge branch to main when PR is approved
# GitHub Actions integration:
# .github/workflows/preview.yml:
- name: Create Neon Branch
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch_name: preview/${{ github.head_ref }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run Migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ steps.neon.outputs.db_url_with_pooler }}
# Result: every PR gets its own database branch automatically
This is a workflow improvement over Supabase (no automatic branching) and traditional Postgres (you'd manage this manually).
Boilerplate 1: T3 Stack + Neon
Price: Free Stack: Next.js + TypeScript + Prisma + tRPC + Tailwind Database: Neon Postgres (via Prisma)
T3 Stack is the most natural fit for Neon — both are TypeScript-first, both work well in serverless environments.
# Create T3 app:
npm create t3-app@latest my-saas
# .env:
DATABASE_URL="postgresql://[user]:[pass]@ep-[id].us-east-2.aws.neon.tech/neondb?sslmode=require&pgbouncer=true"
DIRECT_URL="postgresql://[user]:[pass]@ep-[id].us-east-2.aws.neon.tech/neondb?sslmode=require"
# prisma/schema.prisma:
datasource db {
provider = "postgresql"
url = env("DATABASE_URL") # Pooled (for runtime)
directUrl = env("DIRECT_URL") # Direct (for migrations)
}
The pgbouncer=true flag is critical for serverless — it enables connection pooling so each serverless function invocation doesn't open a new database connection.
// Example Prisma schema for SaaS:
model User {
id String @id @default(cuid())
email String @unique
name String?
subscriptions Subscription[]
createdAt DateTime @default(now())
}
model Subscription {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
stripeCustomerId String @unique
stripePriceId String
status String // active | canceled | past_due
currentPeriodEnd DateTime
}
// T3 Stack query via tRPC:
// server/api/routers/subscription.ts
export const subscriptionRouter = createTRPCRouter({
getStatus: protectedProcedure.query(async ({ ctx }) => {
return ctx.db.subscription.findUnique({
where: { userId: ctx.session.user.id },
});
}),
});
Best for: TypeScript-first developers who want end-to-end type safety and a free setup.
Boilerplate 2: Drizzle-Based Starters + Neon
Price: Free Stack: Next.js + Drizzle ORM + Neon Serverless Driver + Tailwind
Drizzle + Neon is the emerging gold standard for 2026. Drizzle's native Neon serverless driver gives better performance than Prisma in edge environments.
npm install drizzle-orm @neondatabase/serverless
npm install -D drizzle-kit
// db/schema.ts:
import { pgTable, text, timestamp, varchar, boolean } from 'drizzle-orm/pg-core';
export const users = pgTable('users', {
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
email: varchar('email', { length: 255 }).unique().notNull(),
name: varchar('name', { length: 100 }),
plan: varchar('plan', { length: 50 }).default('free').notNull(),
createdAt: timestamp('created_at').defaultNow().notNull(),
});
export const subscriptions = pgTable('subscriptions', {
id: text('id').primaryKey().$defaultFn(() => crypto.randomUUID()),
userId: text('user_id').references(() => users.id).notNull(),
stripeCustomerId: varchar('stripe_customer_id', { length: 255 }).unique(),
status: varchar('status', { length: 50 }).notNull(),
currentPeriodEnd: timestamp('current_period_end'),
});
// db/index.ts — Neon serverless driver:
import { neon } from '@neondatabase/serverless';
import { drizzle } from 'drizzle-orm/neon-http';
import * as schema from './schema';
const sql = neon(process.env.DATABASE_URL!);
export const db = drizzle(sql, { schema });
// Usage in Next.js API route:
// app/api/user/route.ts
import { db } from '@/db';
import { users } from '@/db/schema';
import { eq } from 'drizzle-orm';
export async function GET(req: Request) {
const { userId } = getAuth(req);
const user = await db.query.users.findFirst({
where: eq(users.id, userId),
});
return Response.json(user);
}
Performance advantage: Drizzle + Neon serverless HTTP driver has ~3x better cold start performance vs Prisma in edge environments (Vercel Edge, Cloudflare Workers).
Starter repos to fork:
- drizzle-team/drizzle-nextjs-neon
- Search GitHub for "drizzle neon starter" — many community templates
Boilerplate 3: Supastarter (Supabase) vs Neon Setup
If you're considering Supastarter but want Neon instead of Supabase:
// Supastarter uses Supabase Auth + Storage + DB
// You can replace just the DB layer with Neon:
// Instead of Supabase Postgres:
// DATABASE_URL=postgresql://...supabase.co/postgres
// Use Neon:
// DATABASE_URL=postgresql://...neon.tech/neondb?pgbouncer=true
// Supastarter's Prisma schema works with any Postgres
// You lose: Supabase Auth (need to add Clerk/NextAuth separately)
// You gain: DB branching, potentially better pricing at scale
// However: this is significant customization work
// Only worth it if you specifically need Neon branching
// OR if you're at a scale where Neon's autoscaling saves money
Verdict: For most boilerplate users, pick Supastarter AND use Supabase Postgres (they're designed together). Switch to Neon only if you have a specific workflow reason.
Boilerplate 4: PlanetScale + Prisma Starters
If you specifically need MySQL (legacy codebase, MySQL expertise):
# Any boilerplate with Prisma can use PlanetScale:
npm install @prisma/client prisma
# prisma/schema.prisma:
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma" # PlanetScale doesn't enforce foreign keys
}
# .env:
DATABASE_URL="mysql://[user]:[pass]@[host]/[database]?sslaccept=strict"
The relationMode = "prisma" flag: PlanetScale uses Vitess which doesn't enforce foreign key constraints at the database level. Prisma handles referential integrity in the application layer instead. This requires slightly different query patterns but works well.
PlanetScale use cases:
- Existing MySQL codebases migrating to serverless
- Teams with strong MySQL expertise
- Applications where schema changes without locking is critical
Best boilerplate for PlanetScale: Any Prisma-based starter — T3 Stack, ShipFast, Supastarter all work with provider = "mysql" swap.
Neon Branching in CI/CD
The workflow that makes Neon special for boilerplates:
# .github/workflows/preview.yml
name: Preview Deployment
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Create Neon branch
id: neon-branch
uses: neondatabase/create-branch-action@v5
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch_name: preview/pr-${{ github.event.number }}
api_key: ${{ secrets.NEON_API_KEY }}
- name: Run database migrations
run: npx prisma migrate deploy
env:
DATABASE_URL: ${{ steps.neon-branch.outputs.db_url_with_pooler }}
- name: Deploy to Vercel preview
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
scope: ${{ secrets.VERCEL_ORG_ID }}
env:
DATABASE_URL: ${{ steps.neon-branch.outputs.db_url_with_pooler }}
- name: Delete Neon branch on PR close
if: github.event.action == 'closed'
uses: neondatabase/delete-branch-action@v3
with:
project_id: ${{ secrets.NEON_PROJECT_ID }}
branch: preview/pr-${{ github.event.number }}
api_key: ${{ secrets.NEON_API_KEY }}
Result: Every PR gets its own database. Reviewers can test with real data. No shared staging database conflicts.
Pricing at Scale
Neon:
Free tier: 1 project, 10GB storage, 100 compute hours/month
Launch: $19/month — 10 projects, 100GB storage
Scale: $69/month — unlimited projects, 1TB storage
Autoscaling: pay per compute second when active
PlanetScale:
Scaler Pro: $39/month per database
Team: $599/month
Supabase (for comparison):
Free: 2 projects, 500MB, paused after 1 week inactivity
Pro: $25/month per project
Team: $599/month
For early-stage SaaS: Neon free tier → $19/month is excellent value
For teams with multiple preview environments: Neon's branching saves hours
Choosing Between Neon and PlanetScale in 2026
For most new projects in 2026, Neon wins the comparison on three dimensions: it's PostgreSQL (not MySQL), the free tier is more accessible than PlanetScale's post-2024 paid model, and the Git-like branching workflow integrates with modern CI/CD pipelines via official GitHub Actions.
PlanetScale's advantages are real but narrower than they were before the free tier removal. Vitess-based deployments are genuinely excellent at handling schema changes without table locking — a significant operational advantage for high-traffic applications where ALTER TABLE statements would cause downtime. PlanetScale's deploy request workflow, which requires explicit schema change approval before applying to production, adds a governance layer that some teams find valuable. If your team has deep MySQL expertise and you're building something with very high write throughput that needs lock-free schema changes, PlanetScale remains competitive.
For boilerplate compatibility, Neon's Postgres compatibility means any Postgres-targeting ORM works without modification. Drizzle, Prisma, Kysely, and raw pg all connect to Neon with just a connection string change. PlanetScale's MySQL engine means Prisma needs relationMode = "prisma" and you lose foreign key enforcement at the database level — a tradeoff that changes how you write queries and requires application-level referential integrity checks.
The migration consideration matters too: PostgreSQL to PostgreSQL migrations (Neon to Supabase, Neon to Railway Postgres, Supabase to self-hosted) are straightforward with pg_dump. MySQL to PostgreSQL migrations (PlanetScale to Neon) require schema conversion and data type mapping. If you might want to move databases later, starting with Postgres across all options keeps your options open.
What the Branching Workflow Actually Unlocks
Database branching sounds like a nice-to-have until you experience the alternative: a single staging database shared between all developers, all feature branches, and the CI pipeline. The shared staging database creates constant conflicts — migrations from one developer's feature break another developer's tests, and database state from one feature contaminates integration tests for another.
Neon's branching workflow fixes this by making databases as cheap as Git branches. Each developer's feature branch gets its own database branch, initialized from a copy of the main database state. Schema migrations run on the branch. When the feature is ready to merge, the migration is reviewed alongside the code in the PR. When the PR merges, the migration applies to the main database. When the branch database is deleted, the Neon branch database is deleted automatically.
The CI/CD implication: every PR can run against a fresh database with its exact schema, seeded with known data. Flaky tests caused by shared database state disappear. Integration tests that mutate data don't affect other PRs. Test isolation is guaranteed by infrastructure, not by test setup and teardown discipline.
The Vercel + Neon integration makes this workflow zero-configuration: Vercel preview deployments automatically get Neon database branches via the Neon Vercel integration. A PR opened on GitHub creates a Vercel preview URL and a Neon database branch simultaneously. The preview deployment connects to its dedicated database branch. When the PR closes, both are cleaned up.
Connection Pooling for Serverless Environments
The most common Neon configuration mistake is misunderstanding connection pooling in serverless environments. Standard PostgreSQL has a per-connection overhead — each connection allocates memory on the database server and requires a TCP handshake. In traditional server applications, you open a connection pool at startup and reuse connections for the lifetime of the process. In serverless functions, each invocation might start fresh with no persistent connection pool.
Without connection pooling for serverless, a popular Next.js API route handling 1,000 concurrent requests would attempt to open 1,000 simultaneous PostgreSQL connections, exhausting the database's connection limit and causing widespread failures. Neon handles this through two mechanisms: PgBouncer-compatible pooling via a special endpoint (the ?pgbouncer=true connection string parameter), and the Neon serverless HTTP driver (the @neondatabase/serverless package) which sends queries over HTTP/WebSockets rather than maintaining persistent TCP connections.
For Prisma users, the correct setup is two connection strings: DATABASE_URL with ?pgbouncer=true for runtime queries (pooled, used by the application), and DIRECT_URL without the pgbouncer flag for migrations (direct, since Prisma Migrate doesn't work through PgBouncer). The Prisma documentation for Neon covers this explicitly. For Drizzle users, the Neon HTTP driver handles connection management automatically without additional configuration.
PlanetScale handles this differently: it uses HTTP-based query execution by default via the PlanetScale database driver, which avoids the TCP connection model entirely. This is one of PlanetScale's strengths for serverless — you don't need to configure pooling separately because the query protocol itself is connectionless.
Evaluating Serverless Database Costs at Scale
The free tier economics of Neon and PlanetScale (post-2024) are significantly different, and understanding the cost curves helps you choose the right starting point for your product.
Neon's free tier (10GB storage, 100 compute hours/month) is genuinely useful for development and early production. The compute hour model means you pay for actual usage rather than a fixed reservation — an idle database accumulates no compute charges. As traffic grows, the autoscaling feature means Neon adjusts compute automatically, and the cost scales proportionally rather than requiring a manual tier upgrade.
PlanetScale's removal of the free tier in 2024 means new projects start at $39/month minimum. For a well-funded startup or a team that knows they'll need MySQL, this is acceptable. For bootstrapped indie founders validating ideas, $39/month before first dollar of revenue is a significant constraint that makes Neon's free tier more attractive.
The practical recommendation for new projects: start with Neon free tier during development and pre-launch, upgrade to Neon's $19/month Launch plan when you have consistent traffic, and re-evaluate at $100+/month cloud spend. PlanetScale makes sense for teams with MySQL expertise, existing MySQL schemas, or enterprise requirements around zero-downtime schema deployments that PlanetScale's deploy request system uniquely addresses.
What to Look for in a Boilerplate's Database Layer
Not every boilerplate that claims Neon or PlanetScale support has implemented the integration correctly. Before committing to a starter, audit these three specific points.
Connection pooling configuration. The single most common Neon integration mistake in boilerplates is missing the pgbouncer=true parameter on the runtime DATABASE_URL. Without it, every serverless function invocation opens a raw TCP connection to Postgres, which quickly exhausts connection limits on any traffic spike. A correctly configured boilerplate will have two environment variables: DATABASE_URL with ?pgbouncer=true for Prisma runtime queries, and DIRECT_URL without the flag for schema migrations. If the boilerplate's .env.example has only a single DATABASE_URL variable and uses Prisma, that's a red flag.
Migration strategy. Serverless database projects need a clear migration story. The Neon branching workflow means migrations should run against a branch database in CI, never directly against the production database. Look for whether the boilerplate's CI configuration (GitHub Actions or similar) includes a database branching step. Boilerplates that run prisma migrate deploy or drizzle-kit migrate directly against DATABASE_URL in their CI workflow are running migrations against a shared environment — either staging (with all the shared state problems) or production (high risk). The best boilerplates use Neon's GitHub Actions integration to create branch databases per PR.
Edge runtime compatibility. If you plan to use Vercel Edge Functions, Cloudflare Workers, or any runtime that's not Node.js, the boilerplate's database client must be edge-compatible. Prisma's standard client is not edge-compatible without Prisma Accelerate. Drizzle's neon-http adapter is edge-compatible. If the boilerplate targets edge deployment and uses Prisma without Accelerate, the database queries will fail in edge runtimes. Check the boilerplate's deployment documentation explicitly.
Practical Project Setup: Neon + Drizzle From Scratch
For developers who want to start from the Drizzle + Neon combination without a full boilerplate, the minimal setup is straightforward and worth understanding regardless of which boilerplate you choose. This is effectively the database layer that any quality boilerplate should provide.
The setup takes about 15 minutes: install drizzle-orm, @neondatabase/serverless, and drizzle-kit; define your schema in a db/schema.ts file using Drizzle's table builder functions; configure a drizzle.config.ts that points to DIRECT_URL for migrations; and instantiate the neon HTTP client with drizzle() in db/index.ts. From there, drizzle-kit generate creates migration files from your schema, and drizzle-kit migrate runs them against the Neon database.
The reason to understand this setup even when using a boilerplate: every Neon + Drizzle boilerplate is ultimately this setup plus additional layers. When something breaks in a boilerplate's database layer, debugging is much faster if you understand the minimal working configuration. The most common issue in practice — a query that works in development but fails in production — is almost always a connection string difference between the local setup (direct TCP connection) and the serverless environment (requires HTTP driver or pooler).
For the broader comparison of boilerplates that use these database configurations alongside their full auth, billing, and UI stacks, the best SaaS boilerplates 2026 guide is the right next step. The NextJS SaaS tech stack 2026 article covers how the database layer fits into the full stack decision. And best free open-source SaaS boilerplates 2026 lists which open-source starters have correctly implemented Neon database configuration — useful if you want to study a real integration before choosing a paid boilerplate.
Compare SaaS boilerplates by database compatibility at StarterPick.
See Drizzle and Prisma ORM comparisons for these databases: Drizzle vs Prisma for boilerplates 2026.
Compare the full infrastructure stack options: Self-hosted vs cloud Supabase for SaaS.
Find the best SaaS boilerplates by database: Best SaaS boilerplates 2026.