Skip to content
Neon vs Supabase vs Railway: Choosing Managed Postgres in 2026
Milos KnezevicMilos Knezevic20 Oct 2026 · 12 min read

Neon vs Supabase vs Railway: Choosing Managed Postgres in 2026

Supabase, Neon and Railway all sell managed Postgres with three different philosophies. Pooling, branching, cold starts and regions decide which fits you.

All three serve real Postgres. The same SQL runs on each, Prisma connects to each the same way, and a pg_dump taken from one restores into another. Hold on to that fact, because it makes the whole decision lower-stakes than it feels — we will come back to it at the end. But the products wrapped around that shared Postgres core answer three different questions. Supabase asks: what if the database were your entire backend? Neon asks: what if the database behaved like a serverless function? Railway asks: what if you just rented a server that somebody else patches? Work out which question matches your project, and most of the comparison resolves itself.

Supabase sells Postgres as a platform

Supabase is not really a database product. It is a backend product with Postgres at its centre. Alongside the database you get authentication with social providers, file storage, realtime subscriptions, edge functions, and an auto-generated API where Row Level Security policies act as your authorization layer. If you adopt the pieces, the value is hard to argue with: a solo developer gets in an afternoon what used to take a month of backend wiring, on a free tier generous enough to launch a real product.

The trade-off is that you are adopting an ecosystem, not choosing a database. RLS policies encode your business rules in SQL inside the database. Supabase Auth keeps your users in its own schema. Storage buckets and realtime channels each add another thread tying your app to the platform. None of this is a trap — it is the deal, and it is a good deal when you actually use the pieces. But if all you wanted was a Postgres connection string for Prisma, the rest is baggage: a dashboard full of services you never touch, and a mental model considerably larger than the thing you needed.

There is one behaviour that catches nearly everyone who puts a side project on the free tier: Supabase pauses free projects after roughly a week without activity, and a paused project does not wake when a request arrives. It stays down until you resume it from the dashboard. I know this one first-hand — this site runs on Supabase, and when it shipped to production, the sleeping database was a genuine operational concern. The answer was two-part: the public pages were built to never touch Postgres at render time, and a small daily cron keeps the database awake for the parts that do.

app/api/cron/db-keepalive/route.ts
import { prisma } from "@/lib/prisma";

export async function GET(request: Request) {
  const auth = request.headers.get("authorization");
  if (auth !== `Bearer ${process.env.CRON_SECRET}`) {
    return new Response("Unauthorized", { status: 401 });
  }
  await prisma.$queryRaw`SELECT 1`;
  return Response.json({ ok: true, pingedAt: new Date().toISOString() });
}
vercel.json
{
  "crons": [
    { "path": "/api/cron/db-keepalive", "schedule": "0 6 * * *" }
  ]
}

The secret check is not optional — the route is publicly reachable, and an unauthenticated endpoint that touches your database is an invitation. Vercel sends the CRON_SECRET header automatically on scheduled invocations. And yes, pinging your own database every morning to stop it falling asleep is a mild hack. I am comfortable with it: the honest alternative is the paid plan, and paying twenty-five dollars a month to keep a pre-revenue project's database warm is the wrong trade.

warning

A paused Supabase free project does not auto-resume on traffic. If your demo gets a burst of visitors from a job application or a forum link while the database sleeps, they see errors until you log in and click restore. Keep it awake, or build your public pages so they render without it.

Neon sells Postgres as serverless infrastructure

Neon made the opposite bet. Instead of adding services around Postgres, it rebuilt the storage layer underneath, so that compute and storage scale independently. When nobody is querying, compute scales to zero and you pay close to nothing; when a query arrives, a cold start brings it back in something like half a second — quick enough that a human clicking a link rarely notices, slow enough that you would not want it in front of every request on a busy API. Unlike the Supabase pause, this happens automatically in both directions. A Neon database left alone for six months answers the next query by itself. For projects that are idle most of their life, this is the shape serverless always promised.

The feature that actually wins teams over, though, is branching. Because the storage is copy-on-write, Neon can create a full branch of your database — schema and data — in about a second, without duplicating storage. That sounds like a parlour trick until you see the workflow it makes possible: every pull request gets its own database branch next to its preview deploy. Your migration runs against a realistic copy of production-shaped data instead of an empty dev database. Your reviewer clicks a preview URL backed by an isolated database they can write to without fear. When the PR merges, the branch is deleted. Schema changes stop being the scary part of code review, because the rehearsal happens automatically, every time.

Neon's GitHub and Vercel integrations automate the whole loop — branch created per preview deployment, environment variables wired in, branch removed on merge. It takes an afternoon to set up, and it permanently changes how cautious you have to be about migrations, in the good direction.

Pricing follows usage: compute-hours plus storage. That is wonderful for spiky and dormant workloads, and it needs watching for steady ones. A database that is busy around the clock pays for every one of those compute-hours, and can end up costing more than a flat-rate container that would have been bored at the same load. Usage-based pricing rewards the workloads it was designed for and quietly penalises the rest — run the numbers against your actual traffic shape before assuming serverless means cheaper.

Railway sells Postgres as a container

Railway — and the same class includes Render and Fly Postgres — offers the least clever option of the three: a Postgres instance running continuously in a container, with automated backups, metrics, and a connection string. No scale-to-zero, no branching, no auth or storage services bolted on. It is the closest thing on this list to a server you do not have to patch.

That dullness is the feature. The bill is effectively flat and predictable, which anyone who has been surprised by a usage-based invoice will recognise as a feature in itself. There are no cold starts, ever, and no pause behaviour to design around. There is also no architectural opinion: it is just Postgres with a process supervisor, so everything you know about vanilla Postgres applies without translation. If your application is a long-running Node server with steady traffic, an always-on database next to it is exactly the right shape, and the serverless machinery of the other two buys you nothing but complexity.

What you give up is everything that made the other two interesting. Nothing scales by itself — if traffic grows, you resize and restart. Staging is a second instance you pay for and keep in sync yourself, because there is no branching. And the free allowances are thin compared with Supabase's free tier, so the realistic entry price is a few dollars a month from day one.

The dimensions that actually decide

Feature lists do not settle this choice. Four boring dimensions do, and they are exactly the ones the comparison posts skip.

Connection pooling decides whether serverless works at all

Postgres was designed for a modest number of long-lived connections. Each connection is a process on the server, and a typical instance allows on the order of a hundred of them. Serverless inverts that assumption: a traffic spike spins up hundreds of concurrent function invocations, each opening its own connection, holding it for fifty milliseconds, and abandoning it. Direct connections run out within seconds, and you meet the error every serverless developer eventually meets: "remaining connection slots are reserved". The first time you hit it, you will assume the bug is yours. It is not — it is an architecture mismatch, and the fix is a pooler such as PgBouncer sitting in front of the database, multiplexing thousands of short-lived client connections onto a handful of real ones.

All three providers know this. Supabase ships its pooler, Supavisor, on a separate port of the same host. Neon gives every database a pooled endpoint alongside the direct one. On Railway you either deploy PgBouncer yourself or run a long-lived server where Prisma's built-in pool does the job — the Prisma guide covers how that pool behaves and how to size it. With Prisma on a pooled provider, the standard setup is two URLs: the pooled one for the application, the direct one for migrations, because schema changes need session-level features that transaction-mode pooling cannot provide.

.env
# Pooled URL for the app, direct URL for migrations
DATABASE_URL="postgresql://postgres.abcd1234:PASSWORD@aws-0-eu-central-1.pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1"
DIRECT_URL="postgresql://postgres.abcd1234:PASSWORD@aws-0-eu-central-1.pooler.supabase.com:5432/postgres"

In schema.prisma, point url at DATABASE_URL and directUrl at DIRECT_URL. Prisma sends queries through the pooler and routes migrations down the direct connection automatically — set it up once and forget the distinction exists.

Latency is geography, not provider benchmarks

Provider latency benchmarks are mostly noise next to one decision: put the database in the same region as the code that queries it. A round trip from a function in Frankfurt to a database in Virginia costs roughly ninety milliseconds of pure physics. A page that runs five sequential queries pays that five times before it renders a byte — close to half a second of latency that no index will ever fix. The same page with everything co-located in Frankfurt pays one or two milliseconds per query. No provider is fast enough to beat the Atlantic.

This interacts with your hosting decision more than people expect. If your functions run on Vercel, pin the function region to your database region in the project settings — the default may not match. And if latency budgets are tight enough that you are counting round trips, the comparison between Vercel and self-hosting is worth reading next, because a VPS in the same datacentre as your database is the lowest-latency topology there is, with trade-offs that go well beyond speed.

tip

Pick the database region first, then pin your serverless function region to match it. This single setting routinely matters more than every provider benchmark combined, and it costs nothing.

What happens when nobody visits, and the day you need a restore

Lay the pause behaviours side by side and they differ in kind, not degree. Neon suspends compute after a few minutes of idleness and resumes by itself in under a second — invisible automation. Supabase free pauses after about a week and stays down until a human intervenes — a tripwire. Railway never pauses, because you are paying for it to stay on — a constant. For anything that must survive being ignored for a month, that ordering is the ranking.

Backups deserve more attention than comparison posts give them, because the day you need one is the worst day of your project. The dimension that matters is point-in-time recovery: restoring to 14:31, the minute before the bad migration ran, rather than to last night's snapshot with a day of customer data missing. Neon's storage design gives you a restore window as a side effect of its architecture. Supabase offers daily backups on paid plans, with point-in-time recovery as a further upgrade. Railway-class providers give you scheduled snapshots. Whatever you pick, run one practice restore before real traffic arrives. A backup you have never restored is a hypothesis, not a safety net.

If you operate from the EU or serve EU users, residency is not a preference, it is an obligation. All three providers offer EU regions — Frankfurt is the common choice — so the requirement is satisfiable everywhere; the work is remembering to do it. Pick the EU region on day one, because moving regions later is effectively a full migration. Check where backups are stored, not just the primary. And note that your database provider is a data processor under GDPR, which means you need their data processing agreement on file — all three publish one. Operating from Austria, I treat this as part of provisioning, not paperwork for later: it is ten minutes on day one, or a genuine problem on the day a customer asks.

The decision rule

Here is the rule by scenario, with no "both are great" escape hatch.

  • Side project that may go dormant: Neon. Scale-to-zero is built for projects that sleep, and it wakes up by itself. Choose Supabase only if you genuinely want its auth and storage — and then keep it awake with a cron, or design your public pages to survive the pause.
  • Serverless-heavy SaaS with preview deploys: Neon. The branch-per-PR workflow and pooled endpoints fit the platform you are already on, and usage-based pricing matches spiky traffic.
  • You want a backend, not just a database: Supabase. Auth, storage, realtime and RLS on one bill beats wiring four separate services together — just accept the ecosystem consciously.
  • Boring, steady production traffic: Railway or Render. Always-on Postgres at a flat, predictable price, no cold starts, no surprises in the invoice.

The comforting part is that this choice is reversible in a way most infrastructure choices are not. All three are genuine Postgres: pg_dump on one side, pg_restore on the other, change DATABASE_URL, redeploy. If all you consumed was the database, switching providers is an evening of work, not a quarter. The exception is platform features. RLS policies travel fine — they are just SQL — but Supabase Auth users and storage buckets do not, and that is precisely the part of the ecosystem that holds you. Adopt those pieces because you want them, not because they were there.

So do the cheap thing tonight: pick by the scenario above, provision in an EU region co-located with your functions, set the pooled and direct URLs, run your first migration, and get back to building the product. Revisit the choice only when the bill, the latency numbers, or the pause behaviour tell you to — those are signals you will actually see, not risks you have to predict. The database is almost never what decides whether a project succeeds. Shipping the thing on top of it is.