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
Compare SaaS boilerplates by database compatibility at StarterPick.