all posts

The best Neon alternatives in 2026

Ajay Kumar··9 min read

Neon's architecture is the interesting part: storage is separated from compute, so a branch is a metadata operation rather than a copy, and an idle database can scale its compute to zero because the data isn't sitting on it. Branch-per-pull-request became a normal thing to do because of this design.

The same design produces the trade-offs people leave over. Here they are, and where each one goes. I build PandaStack, which runs managed Postgres on microVMs — a different point on the same spectrum, and I'll be specific about where it's the wrong answer.

The reasons people leave

1. Cold starts after idle

Scale-to-zero compute means the first query after an idle period waits for compute to come back. For a staging environment or an internal tool, this is a great deal. For a user-facing API with sporadic traffic — exactly the workload that idles — it's a latency spike on the request that mattered.

The mitigations are all forms of not idling: a minimum compute setting, a keepalive query, or accepting the spike. If your traffic pattern makes those unattractive, you want a database whose compute simply stays up, which is most of them.

2. Extensions and Postgres surface area

Every managed Postgres restricts extensions, and each provider's list is different. This bites specifically when you need something outside the common set — a custom C extension, a niche foreign data wrapper, an extension version newer than the provider offers, or anything requiring superuser.

If you need arbitrary extensions, the answer is a platform where the database is a machine you control rather than a service you're given: a dedicated Postgres instance, a VM you manage, or a managed offering built on per-database virtual machines. That's the category my product is in, and it's the one place I'd genuinely recommend it over Neon.

3. Cost at steady load

Usage-based database pricing wins for spiky and idle workloads and loses for consistent ones. A database busy around the clock on a compute-hour model is a variable-cost version of a fixed cost, without the predictability. If your compute never scales down because your traffic never stops, you're paying for the flexibility and not using it.

4. Latency and connection behaviour

Separating storage from compute adds a network hop on the paths where the compute node hasn't cached the pages it needs. For most workloads this is unnoticeable; for a query pattern that scans a lot of cold data, it isn't. Worth benchmarking your slowest real query rather than a synthetic one.

Whatever you move to, check connection limits and put a pooler in front if your app opens connections per request. Postgres connection exhaustion is the most common database outage in serverless architectures, and it looks like a database failure when it's an application design problem.

The options

  • Supabase — Postgres plus auth, storage, and realtime. Right if you want the surrounding platform; more product than you need if you only want a database.
  • Amazon RDS or Aurora — the boring, dependable answer. Extremely well understood, excellent operational tooling, no cold starts on provisioned instances. More setup, more knobs, and Aurora Serverless has its own scale-down behaviour worth reading closely.
  • Crunchy Bridge, Timescale, and similar specialists — strong Postgres expertise, generous extension support, straightforward pricing. Good when you want Postgres taken seriously without running it yourself.
  • PlanetScale — worth naming, but it's a different database lineage; treat a move there as a migration rather than a swap.
  • PandaStack (mine) — each database is a Postgres instance on its own microVM with a durable volume, so compute stays up, the extension surface is the machine's rather than a provider allowlist, and clone-to-a-point-in-time creates an independent database from the archive. The trade is that provisioning a new database takes tens of seconds rather than being instant, because you're getting a machine.
  • Self-managed Postgres on a VM — cheapest, most control, and you now own backups, failover, patching, and the 3am page. Legitimate if you have the on-call rotation already.

If you're leaving, don't lose branching

Branch-per-pull-request is the habit worth keeping. Once a team has a real database per preview environment, going back to a shared staging database that three people are mutating simultaneously feels awful.

Different platforms implement the equivalent differently — copy-on-write clones, restore-from-snapshot, or a scripted restore of a recent backup into a fresh instance. The properties to compare: how long it takes, whether it costs a full copy of storage, and whether the clone is genuinely independent so a destructive test can't touch production.

# A clone should be an independent database, not a view of production.
# Point-in-time clones make "restore to just before the bad migration"
# a normal operation rather than an incident.
pandastack db clone prod-db \
  --label pr-482 \
  --target-time 2026-08-18T09:15:00Z

# The source database is untouched; the clone gets its own id and URL

Migrating Postgres without losing data

  1. Match the major version on the destination first. A version jump during a provider migration is two risky changes at once.
  2. Check extensions on both sides before dumping anything. A restore that fails halfway on a missing extension is a bad way to learn.
  3. Do a full dump-and-restore rehearsal into the new provider, timed, with the real data volume. The number you get is your maintenance window.
  4. For anything where that window is too long, use logical replication to catch up, then cut over with a short pause on writes.
  5. Keep the old database running and readable for at least a week. Not a snapshot — actually running.

The short version

Cold starts hurting user-facing traffic: a database whose compute stays up. Blocked by the extension allowlist: a database that's a machine you control. Steady load making usage pricing expensive: fixed-size provisioned instances. Wanting the surrounding platform: Supabase. And if branch-per-PR is the reason you're on Neon in the first place, make sure whatever you move to can do something equivalent — that's the feature you'll miss.

Frequently asked questions

Why does my Neon database have a cold start?

Because compute scales to zero when the database is idle, which is the flip side of separating storage from compute. With no compute node running, the first query after an idle period waits for one to be started and to warm its page cache. For staging environments, internal tools, and preview branches this is an excellent trade — you pay nothing while nothing is happening. For a user-facing endpoint with sporadic traffic it lands the latency spike on precisely the requests that matter. The mitigations are all variations of not idling: configure a minimum always-on compute, run a periodic keepalive query, or move to a platform whose database compute simply stays up.

What is the best alternative for Postgres branching?

It depends on which property of branching you actually rely on. If it is speed — a branch in seconds for every pull request — look for copy-on-write clones or snapshot-based provisioning and check whether creating one duplicates storage cost. If it is independence — a preview environment where a destructive test cannot possibly touch production — verify the clone is a genuinely separate database rather than a view or a shared-storage trick. If it is point-in-time restore, check how far back the archive goes and how long a restore takes with your real data volume. Most managed Postgres platforms now offer something in this space, but the implementations differ enormously on those three axes.

Which managed Postgres supports custom extensions?

Broadly, the ones where your database is a machine rather than a shared service. Every managed provider maintains an extension allowlist, because letting tenants load arbitrary C code into a shared instance is not something a multi-tenant service can safely do. If you need a custom extension, a version newer than the provider ships, an unusual foreign data wrapper, or anything requiring superuser, your options are a dedicated instance from a provider that allows it, a platform that gives each database its own virtual machine, or self-managed Postgres on your own VM. Check the specific extension against the specific provider's list before committing — the lists differ more than you would expect.

How do I migrate a Postgres database between providers safely?

Match the major version on the destination before anything else, so you are not combining a provider migration with a version upgrade. Compare extension availability on both sides, since a restore that fails halfway through on a missing extension wastes your entire window. Rehearse a full dump and restore into the new provider with your real data volume and time it — that number is your maintenance window, and it is usually longer than people guess. If it is too long, set up logical replication to bring the destination current, then cut over with a brief pause on writes. Keep the old database genuinely running and readable for at least a week afterwards.

Is serverless Postgres cheaper than a provisioned instance?

For intermittent workloads, substantially. For steady ones, usually not. Compute-hour billing is excellent when the database genuinely idles — development, staging, preview branches, internal tools that see traffic a few hours a day — because you pay close to nothing the rest of the time. When the database is busy around the clock, the same model is a variable-cost version of a fixed cost, with less predictability and no discount for the flexibility you are not using. Look at a week of your own utilisation graph rather than the pricing page, and price the idle hours honestly, including whether anything in your stack polls the database and prevents it from ever scaling down.

Keep reading

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.