When to Stop Using Supabase for Postgres

Supabase is great for speed, but not forever. Here’s when startups should move to plain Postgres and how to do it safely.

By Tushar Goyal
EngineeringStartupsTechnology
When to Stop Using Supabase for Postgres

Supabase is the right choice early, but the wrong choice once its convenience starts dictating your architecture.

That point comes earlier than most founders expect. You should switch when Supabase stops being a product accelerator and starts becoming a performance tax, an operational constraint, or both.

We’ve done exactly that. On Surge, a Next.js platform handling thousands of concurrent users with real-time updates, we rebuilt the data layer twice. We started with Supabase realtime because it got us to launch faster. Then we moved to a custom Postgres + Redis pub/sub setup because Supabase realtime was adding 200ms+ latency under load, and that delay was visible in the product.

That is the core rule: don’t leave Supabase because you’ve become philosophically anti-BaaS. Leave when the abstraction gets in the way of the thing users actually pay for.

Supabase is excellent until the abstraction leaks

Most startups should start with Supabase.

I’d rather see a founder ship in 3 weeks on Supabase than spend 6 weeks hand-rolling auth, storage, row-level security, migrations, and realtime infrastructure they do not yet need. Early on, speed is a bigger advantage than control.

Supabase is especially strong when:

  • You need auth, database, file storage, and admin tooling in one place, and you need all of it working this month, not next quarter.
  • Your team is small, and nobody should be burning days setting up basic backend plumbing instead of shipping user-facing features.
  • Your product usage is still low enough that a little extra latency or a little less flexibility does not materially change retention.

But founders make the wrong decision when they confuse a good starting point with a permanent backend strategy.

Supabase gives you Postgres, but not raw freedom. It gives you Postgres inside an opinionated system with hosted services, API conventions, realtime behavior, auth assumptions, and operational tradeoffs.

That trade is usually worth it at the start. It stops being worth it when one of these happens:

  • Your latency budget gets tight, and managed abstractions add enough delay that the app feels worse.
  • Your backend workflows get more custom, and you start fighting the platform instead of building on top of it.
  • Your infra bill becomes less important than engineering predictability, observability, and control.

The counterintuitive part is this: switching off Supabase is not a sign that you chose badly. It’s often proof that you used it correctly.

The clearest signs you should move to plain Postgres

You do not need a dramatic rewrite moment. You need a threshold.

Here are the thresholds that matter most.

1. Realtime latency is hurting the product

This was the breaking point on Surge.

We initially used Supabase realtime because it was fast to implement. That was the right decision for V1. Once usage climbed to thousands of concurrent users, we saw 200ms+ latency under load, and realtime updates no longer felt realtime.

That mattered because the product depended on live data visibility. If users expect immediate state changes, 200ms is not a backend metric. It is a UX problem.

Switch when:

  • Users can notice delayed updates in collaborative views, dashboards, trading-style surfaces, live ops tools, or any interface where state freshness matters.
  • You need tighter control over event fanout, subscription behavior, or backpressure than the managed realtime layer allows.
  • You’ve already spent more than a few days trying to tune around the platform instead of replacing the bottleneck.

Our replacement was simple in principle:

  • Keep Postgres as the source of truth because relational data was still the right fit.
  • Push realtime messaging through Redis pub/sub because we needed lower-latency fanout with predictable behavior under load.
  • Control the server layer ourselves so we could tune exactly what was emitted, when, and to whom.

A basic version of that architecture looks like this:

// server-side event publish example
await db.query(
  'insert into notifications (user_id, type, payload) values ($1, $2, $3)',
  [userId, 'update_ready', JSON.stringify(payload)]
)

await redis.publish(
  `user:${userId}:events`,
  JSON.stringify({ type: 'update_ready', payload })
)

That is less magical than Supabase realtime. It is also far easier to reason about once scale makes correctness and latency non-negotiable.

2. You need backend logic that does not fit the happy path

Supabase works best when your product maps cleanly to CRUD, auth policies, storage, and a thin server layer.

Move when your core product logic starts living in:

  • Complex job orchestration, where work runs across queues, retries, scheduled tasks, and external APIs.
  • Fine-grained event pipelines, where you need to sequence writes, side effects, and notifications exactly.
  • Security models that go beyond straightforward row-level policies and require custom backend enforcement.

We’ve seen this pattern repeatedly in AI products.

On Harmony.ai, the hard part was not standing up a database. It was orchestrating LLM tool-calling chains and controlling token costs. We shipped in 4 weeks, but the biggest cost driver was prompt token count, so we cached intermediate outputs aggressively. That kind of system benefits from plain backend control much more than a batteries-included platform mindset.

The rule is simple: if your backend is becoming a product in itself, own it.

3. You want Postgres, but not the platform opinions around it

A lot of teams say, “We use Supabase because we want Postgres.” That is backwards.

If what you truly want is Postgres, use Postgres once the surrounding managed services stop helping.

That usually happens when:

  • You want direct control over pooling, replicas, extensions, vacuum strategy, and tuning without wondering what the platform supports this month.
  • You need observability that goes beyond a hosted dashboard and into logs, traces, query analysis, and custom metrics tied to your app behavior.
  • You are integrating multiple backend services and want one database layer without coupling app logic to a specific vendor’s auth and API model.

A practical setup for many startups is:

database: Postgres
cache_and_pubsub: Redis
api: FastAPI or Next.js server routes
auth: Clerk or custom JWT
jobs: Trigger.dev / Celery / BullMQ
files: S3-compatible storage

That stack is not inherently better on day 1. It becomes better when you need control more than convenience.

What you should not migrate for

Do not switch because a senior engineer thinks “real infra” is more respectable.

That is how startups lose a month and gain nothing.

Here are bad reasons to leave Supabase:

  • Your traffic is still modest, your app is mostly CRUD, and the current system is not causing visible user pain. In that case, keep shipping features.
  • You dislike vendor lock-in in theory, but you have not identified a concrete operational or product constraint. Abstract fear is not a migration trigger.
  • You are optimizing cost too early. Saving a few hundred dollars a month is irrelevant if the migration delays revenue.

We chose React Native over Flutter for Uniffy for exactly this reason. The client’s team already knew React, so onboarding speed mattered more than theoretical performance wins. Infrastructure decisions should follow the same logic.

Use the thing that reduces time-to-value until it starts increasing time-to-progress.

A good litmus test is this:

  • If Supabase is helping junior and mid-level engineers move faster without introducing user-visible problems, keep it.
  • If your senior engineers are building workarounds around Supabase every week, stop pretending the abstraction is still saving time.
  • If your product experience now depends on behavior the platform cannot guarantee, migrate before that pain spreads across the codebase.

How to switch without turning it into a rewrite

Do not “migrate off Supabase.” Migrate one responsibility at a time.

Founders get into trouble when they treat this as a grand platform exorcism. It should be a controlled extraction.

A clean sequence looks like this:

  • Move realtime first if that is the bottleneck. This is what we effectively did on Surge, because that was the part directly affecting UX.
  • Move backend logic next if your business rules are escaping the Supabase model. Keep the database where it is temporarily if that reduces risk.
  • Move auth only if auth is actually constraining you. Replacing auth early creates user-facing edge cases and rarely delivers immediate upside.
  • Move the database hosting last if the actual Postgres layer is not the problem. Many teams can keep the data where it is while removing the higher-level platform dependencies.

Your migration plan should preserve two things:

  • The schema should remain boring. If you are redesigning your data model during the migration, you are taking on two risks instead of one.
  • The interface boundaries should get clearer. Every piece you extract should leave the system easier to understand than before.

A common intermediate state is completely fine:

  • Postgres remains the system of record.
  • New writes go through your own API layer instead of generated client access.
  • Realtime moves to Redis or WebSocket infrastructure you control.
  • Auth still lives on the old provider until there is a strong reason to replace it.

That is not half-finished architecture. That is good sequencing.

What to Do Next

Run a 60-minute backend review and answer one question: where is Supabase currently adding measurable friction to product velocity or user experience?

Be specific. If the answer is “realtime updates feel delayed above a few thousand concurrent users,” replace realtime first. If the answer is “our business logic is now spread across database policies, edge functions, and app code,” put a proper API layer in front of Postgres first.

Do not migrate because you are growing. Migrate because one part of the platform is now the bottleneck.

If you're at this stage, schedule a call with us.