Skip to content

database · side by side

Neon vs Supabase for a Next.js app

Both fill the database slot, so a generated repo carries one or the other, never both. Every line below is read out of the two manifests.

Short answer

Pick Neon if

Teams that want plain Postgres plus a throwaway database per pull request, running on Vercel or another serverless host where connections are scarce.

Pick Supabase if

Teams that want one Postgres provider to also cover auth, storage and realtime. Also teams who want to run the real stack locally, not against a shared dev database.

Supabase is tested with Supabase Auth and Supabase Storage. Neon isn't yet.

Side by side

Price, obligations, and the surface each one adds. No row is written by hand. This is manifest.yaml, rendered.

Neon compared with Supabase on pricing, fit, trade-offs, required companions, environment variables, dependencies, MCP servers and repo footprint.
From the manifestOption ANeonOption BSupabase
In one lineNeon

Serverless Postgres you can branch like git, with a driver built for cold starts.

Supabase

Managed Postgres with row level security, realtime and a local stack in Docker.

PricingNeon

Free plan: up to 100 projects, each with 100 CU-hours a month and 0.5 GB of storage. Launch and Scale have no monthly minimum: you pay per CU-hour ($0.106 on Launch) plus $0.35 per GB-month of storage.

Supabase

Free: 2 active projects, 500 MB database each, paused after a week idle. Pro is $25/month per organisation with $10 of compute credit, 8 GB disk per project, 7 days of daily backups and no pausing. Extra projects add compute cost.

Best forNeon

Teams that want plain Postgres plus a throwaway database per pull request, running on Vercel or another serverless host where connections are scarce.

Supabase

Teams that want one Postgres provider to also cover auth, storage and realtime. Also teams who want to run the real stack locally, not against a shared dev database.

Trade-offsVerbatim from the manifestNeon
  • Standard Postgres. ORMs and psql work unchanged, with no custom query layer to learn.
  • Branching is copy-on-write, so a preview branch of a 20 GB database only adds storage for what the branch changes.
  • Compute scales to zero after 5 idle minutes and wakes in a few hundred milliseconds. On low-traffic previews that shows up as a slow first request.
  • Database only. No auth, storage, realtime or generated API. Pair it with Better Auth or Clerk. Supabase bundles those.
  • Two connection strings to keep straight (pooled and direct). Point a migration at the pooled one and it fails in confusing ways.
Supabase
  • A full Postgres, not a subset: extensions, triggers, functions and logical replication all work.
  • Row level security is the security model. Going through the service role key everywhere throws away most of what you are paying for.
  • The local CLI boots Postgres, PostgREST, GoTrue, Realtime and Storage in Docker, so the dev loop needs Docker running.
  • Branching exists but is a paid feature and slower to spin up than a local reset. Most teams use local for the inner loop and branches for previews.
  • Two connection strings: direct on port 5432 and the pooler on 6543. Pick the wrong one for a serverless runtime and you run out of connections in production.
  • Auth, storage and realtime are optional. Using Supabase purely as Postgres is supported and common.
Required companionsAdded for you, with a reasonNeon
  • An ORM battery
Supabase
  • An ORM battery
Recommended alongsideSuggested, never added for youNeon

Nothing suggested.

Supabase
  • Supabase Auth
  • Supabase Storage
Env vars you will manageEvery one documented in docs/onboard.mdNeon

4 variables · 1 required

  • DATABASE_URL
  • DATABASE_URL_UNPOOLED
  • NEON_API_KEY
  • NEON_LOCAL_PROXY
Supabase

6 variables · 3 required

  • DATABASE_URL
  • NEXT_PUBLIC_SUPABASE_ANON_KEY
  • NEXT_PUBLIC_SUPABASE_URL
  • DIRECT_URL
  • SUPABASE_ACCESS_TOKEN
  • SUPABASE_SERVICE_ROLE_KEY
Dependencies addedNeon
  • @neondatabase/serverless ^1.0.0
  • @types/pg ^8.23.0 (dev)
  • pg ^8.23.0 (dev)
Supabase
  • @supabase/supabase-js ^2.117.0
  • postgres ^3.4.4
  • server-only ^0.0.1
  • supabase ^2.2.1 (dev)
MCP serversWritten into .mcp.jsonNeon
  • neon: https://mcp.neon.tech/mcp?readonly=true
Supabase
  • supabase: npx -y @supabase/mcp-server-supabase@latest --read-only
Footprint in your repoNeon

5 files, plus 5 injections into shared stack files

Supabase

8 files, plus 4 injections into shared stack files

What changes in your repo

The paths each battery contributes, diffed. A path in the third list is written by both, so swapping rewrites that file rather than adding one.

Only with Neon (4)

  • scripts/2 files
    • db-branch.ts
    • neon-local-proxy.ts
  • src/2 files
    • db/2 files
      • health.ts
      • neon-local.ts

Only with Supabase (7)

  • src/1 file
    • db/1 file
      • url.ts
  • supabase/2 files
    • seed/1 file
      • 00_conventions.sql
    • config.toml
  • variants/4 files
    • browser-anon/1 file
      • src/1 file
        • db/1 file
          • supabase-browser.ts
    • browser-shared-session/1 file
      • src/1 file
        • db/1 file
          • supabase-browser.ts
    • starter-profiles/2 files
      • supabase/2 files
        • migrations/1 file
          • 20250101000000_init_profiles.sql
        • seed/1 file
          • 10_profiles.sql

Same path, different implementation (1)

  • src/1 file
    • db/1 file
      • client.ts

Shared stack files Neon injects into

  • db-client
  • env-required
  • hook-probes
  • legal-processors
  • verify-checks

Shared stack files Supabase injects into

  • db-client
  • env-required
  • legal-processors
  • verify-checks

Neon in your .env.local

.env.localbash7 lines
# required
DATABASE_URL=postgresql://user:password@ep-example-123456-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require

# optional
DATABASE_URL_UNPOOLED=postgresql://user:password@ep-example-123456.us-east-2.aws.neon.tech/neondb?sslmode=require
NEON_API_KEY=neon_api_key_xxxxxxxxxxxxxxxxxxxx
NEON_LOCAL_PROXY=

Supabase in your .env.local

.env.localbash9 lines
# required
DATABASE_URL=postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:6543/postgres
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example.anon-key
NEXT_PUBLIC_SUPABASE_URL=https://<project-ref>.supabase.co

# optional
DIRECT_URL=postgresql://postgres.<project-ref>:<password>@aws-0-<region>.pooler.supabase.com:5432/postgres
SUPABASE_ACCESS_TOKEN=sbp_0000000000000000000000000000000000000000
SUPABASE_SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.example.service-role-key

What changes for your agents

Each battery ships rules, skills, subagents and hooks that an agent loads before it touches the code that battery owns. Picking one is also picking how your agents behave in src/db/**.

Neon

  • 1

    Agents

  • 2

    Skills

  • 2

    Rules

  • 1

    Hooks

  • 6

    Solution docs

  • 1

    MCP servers

Rules (2)

One connection surface, and the right driver for the job

src/db/** · src/app/api/**

Schema changes go through ORM migration files on the direct URL

src/db/**

Skills (2)

/db-branch

Create, use, reset and delete Neon database branches, for a feature branch, a preview deploy, a migration rehearsal or a point-in-time investigation.

/migrate-on-neon

Run a schema migration against Neon safely, on the direct URL, rehearsed on a branch first, with a recovery path when it fails halfway.

Subagents and hooks

db-inspector

Read-only Neon Postgres inspector. Explains schema, data shape and query plans. Runs SELECT and EXPLAIN only, and refuses every statement that writes or changes schema.

guard-neon-sql

Blocks raw DDL through psql, migrations that would really run through the Neon pooler, and schema pushes that skip migration files. The repo's own db:migrate scripts pass.

PreToolUse · Bash

Supabase

  • 2

    Skills

  • 2

    Rules

  • 5

    Solution docs

  • 1

    MCP servers

Rules (2)

Row level security is on by default and the service role is a last resort

src/db/**

Schema changes go through supabase/migrations, never the dashboard

supabase/**

Skills (2)

/add-rls-policy

Add or fix row level security policies on a Supabase table, with a migration, a policy test and regenerated types.

/local-supabase

Boot, reset, inspect and troubleshoot the local Supabase stack, and pull schema down from a hosted project.

Subagents and hooks

None of its own. The foundation agents and guard hooks still ship.

What each one already knows

Solution docs land in docs/solutions/ in your repo and are published here, so you can read the failure modes before you commit.

Neon (6)

Supabase (5)

Which one to pick

From meta.bestFor and meta.tradeoffs. If a claim is not in the manifest, it is not on this page.

Pick Neon when

Teams that want plain Postgres plus a throwaway database per pull request, running on Vercel or another serverless host where connections are scarce.

And accept that(5)
  • Standard Postgres. ORMs and psql work unchanged, with no custom query layer to learn.
  • Branching is copy-on-write, so a preview branch of a 20 GB database only adds storage for what the branch changes.
  • Compute scales to zero after 5 idle minutes and wakes in a few hundred milliseconds. On low-traffic previews that shows up as a slow first request.
  • Database only. No auth, storage, realtime or generated API. Pair it with Better Auth or Clerk. Supabase bundles those.
  • Two connection strings to keep straight (pooled and direct). Point a migration at the pooled one and it fails in confusing ways.

Pick Supabase when

Teams that want one Postgres provider to also cover auth, storage and realtime. Also teams who want to run the real stack locally, not against a shared dev database.

And accept that(6)
  • A full Postgres, not a subset: extensions, triggers, functions and logical replication all work.
  • Row level security is the security model. Going through the service role key everywhere throws away most of what you are paying for.
  • The local CLI boots Postgres, PostgREST, GoTrue, Realtime and Storage in Docker, so the dev loop needs Docker running.
  • Branching exists but is a paid feature and slower to spin up than a local reset. Most teams use local for the inner loop and branches for previews.
  • Two connection strings: direct on port 5432 and the pooler on 6543. Pick the wrong one for a serverless runtime and you run out of connections in production.
  • Auth, storage and realtime are optional. Using Supabase purely as Postgres is supported and common.

Questions people actually ask

Should I choose Neon or Supabase?
Neon is best for teams that want plain Postgres plus a throwaway database per pull request, running on Vercel or another serverless host where connections are scarce. Supabase is best for teams that want one Postgres provider to also cover auth, storage and realtime. Also teams who want to run the real stack locally, not against a shared dev database. Both fill the database slot, so a generated repo carries one or the other, never both.
How much do Neon and Supabase cost?
Neon: Free plan: up to 100 projects, each with 100 CU-hours a month and 0.5 GB of storage. Launch and Scale have no monthly minimum: you pay per CU-hour ($0.106 on Launch) plus $0.35 per GB-month of storage. Supabase: Free: 2 active projects, 500 MB database each, paused after a week idle. Pro is $25/month per organisation with $10 of compute credit, 8 GB disk per project, 7 days of daily backups and no pausing. Extra projects add compute cost.
What changes in my repo if I switch from Neon to Supabase?
Neon writes 5 files, 4 environment variables and 3 dependencies, and installs 2 path-scoped rules, 2 skills and 6 solution docs. Supabase writes 8 files, 6 environment variables and 4 dependencies, and installs 2 path-scoped rules, 2 skills and 5 solution docs.

Decide once, then build the repo that already knows the decision.

Either way you get that choice’s rules, skills and solution docs installed, plus the guard hooks, an onboarding doc for exactly these env vars, and the Compound Engineering loop. Free and MIT.