all posts

PandaStack vs Supabase: an honest comparison

Ajay Kumar··9 min read

Supabase is what a lot of teams reach for when they want a backend without writing a backend: point it at a Postgres schema and get a REST and GraphQL API, row-level-security-based auth, realtime subscriptions, file storage, and edge functions, all from one dashboard. It's open source, it's popular for good reason, and for a CRUD app with auth it can take you from empty repo to working product in an afternoon.

PandaStack does not try to be that. It's a Firecracker-microVM compute substrate: sandboxes for running arbitrary and untrusted code, git-driven hosting for apps you write and deploy yourself in any language or framework, managed Postgres as dedicated per-tenant virtual machines rather than a shared multi-tenant cluster, and serverless functions with cron. If Supabase's promise is 'don't write a backend,' PandaStack's premise is the opposite: you write and run the backend, and the platform's job is to isolate and execute it well.

I'm Ajay, founder of PandaStack, so read this as a vendor comparison, not a neutral benchmark. My rule for these: cite specific numbers only for PandaStack, describe Supabase qualitatively rather than inventing its internals, and say plainly where Supabase wins. Supabase is a mature, widely-deployed product with a large community and years of hardening on the auth/RLS/realtime stack. Managed platforms change their pricing, limits, and internals over time, so verify anything Supabase-specific against their own current docs before designing around it.

Two different shapes, not two competitors

Supabase's core idea is that your database schema is your API surface. Define tables and RLS policies in Postgres, and Supabase generates the REST/GraphQL endpoints, handles auth tokens, and enforces access control as row-security predicates evaluated inside the shared database. The backend, in the traditional sense of a server process you write, mostly disappears — which is the entire point, and it's a genuinely good trade for a large class of apps.

PandaStack's core idea is that isolation should be a virtual machine boundary, not a database row-security policy. Every sandbox, every app, every function invocation, and every managed database runs in its own Firecracker microVM with its own kernel — not as a tenant-scoped view into one shared Postgres cluster. That buys you strict tenant isolation and the ability to run code you don't trust, but it means PandaStack has no equivalent of 'define a table, get an API' — you write the server, PandaStack runs it.

Auth, auto-generated APIs, and who writes the backend

Supabase Auth is a first-class, deeply integrated piece: email/password, OAuth providers, magic links, and JWTs that RLS policies read directly, so 'is this user allowed to see this row' is expressed once, in SQL, and enforced everywhere the row is touched — REST, GraphQL, realtime, storage. Combined with the auto-generated API, a working authenticated CRUD app can exist with close to zero backend code. That's the batteries-included promise, and it's real.

PandaStack has no auto-generated API layer and no built-in auth product. If you deploy an app, you bring your own auth (or plug in something like Clerk, Auth0, or Supabase Auth itself) and you write your own API — Express, FastAPI, Gin, whatever the framework gives you. PandaStack's job starts after that: run your git repo's build and start commands in an isolated microVM, behind a stable URL, with blue-green deploys. If you're choosing PandaStack specifically to avoid writing an API layer, you've picked the wrong tool — that's Supabase's whole reason to exist.

Database isolation: row-security in a shared cluster vs. a dedicated VM

This is the sharpest technical difference and worth being precise about. A Supabase project's Postgres instance is dedicated to that project, but Supabase's row-level-security model — the thing most teams actually mean when they talk about multi-tenancy on Supabase — puts multiple tenants' rows in the same tables inside the same database, with access control enforced by policies the database evaluates on every query. That's a well-proven pattern and it scales operationally very well, but it means a policy bug, a misconfigured `USING` clause, or a privilege-escalation path in Postgres itself is the thing standing between one tenant's rows and another's.

PandaStack's managed Postgres is a dedicated Firecracker microVM per database — not a shared cluster with policy-based row filtering. Two tenants on PandaStack aren't two RLS-scoped views into the same server; they're two separate virtual machines that don't share a Postgres process, a buffer cache, or a connection pool. Create takes 30–90 seconds because it's booting and initializing a real instance, not provisioning a schema in a warm cluster. The trade-off is real: a shared cluster with RLS is cheaper to run at scale and gives you cross-tenant SQL in one place when you actually want it (admin dashboards, cross-tenant analytics); a VM-per-tenant model gives up that convenience for a stronger isolation boundary.

Untrusted and AI-generated code: the thing a BaaS isn't built for

Supabase Edge Functions run on Deno, which sandboxes JavaScript/TypeScript reasonably well for the workloads it's designed for — webhook handlers, small API glue, auth triggers. It is not designed to run arbitrary untrusted code across languages: no general filesystem, no ability to shell out to a compiler or a package manager, no support for a customer's own Python, Go, or Rust with real system calls. That's a deliberate scope limit, not an oversight — a BaaS optimizing for 'ship a CRUD backend fast' has no reason to open that door.

PandaStack sandboxes exist specifically for that door: AI agents executing generated code, code interpreters, per-tenant logic where tenants don't trust each other or you don't trust the code at all. Each sandbox restores from a baked Firecracker snapshot — 179ms p50 / 203ms p99 for the full create path, with the snapshot-restore step itself landing around 49ms — and gets its own kernel behind the hypervisor, so the isolation boundary a neighbor has to cross is the VMM's tiny device model, not a language runtime's sandbox or a shared kernel's syscall filter. If your product needs to run code a customer wrote, or an LLM wrote, this is the category of problem PandaStack targets and Supabase explicitly does not.

Side by side

  • Core model: Supabase generates an API from your Postgres schema — you mostly configure, don't code. PandaStack runs code you write — sandboxes, git-deployed apps, and functions — in isolated microVMs.
  • Auth: Supabase Auth is built in, deeply wired into RLS policies, and largely code-free to set up. PandaStack has no built-in auth product — bring your own (Supabase Auth, Clerk, Auth0, or your own) inside the app you deploy.
  • Database isolation: Supabase enforces tenant separation with row-level-security policies inside one shared Postgres cluster per project. PandaStack gives each managed database its own dedicated Firecracker microVM — separate process, separate disk, no shared buffer cache between tenants.
  • Realtime: Supabase Realtime streams database changes (inserts/updates/deletes, presence, broadcast) as a first-class, managed product with client SDKs. PandaStack has no built-in realtime layer — you'd run your own WebSocket server as a deployed app.
  • Self-hosting: Supabase is open source and self-hostable, composed of several services (Postgres, GoTrue, PostgREST, Realtime, Storage) you run together via Docker Compose or Kubernetes. PandaStack is Apache-2.0 and self-hostable as a single control plane plus per-host agents on your own Firecracker-capable Linux hosts, with true VM-level tenant isolation rather than a policy layer inside shared Postgres.
  • Untrusted code execution: Supabase Edge Functions run trusted-ish JavaScript/TypeScript on Deno for API glue and webhooks — not built for arbitrary or adversarial code. PandaStack sandboxes are built for exactly that: AI-agent-generated code, customer scripts, anything you don't trust, each in its own kernel.

Self-hosting and openness

Both projects are open source, and both let you run the whole thing yourself instead of using the hosted version — that part isn't a differentiator so much as a shared value. What differs is what you're hosting. Self-hosting Supabase means running its full service mesh (Postgres, GoTrue for auth, PostgREST for the REST API, Realtime, Storage) and getting the same BaaS surface on your own infrastructure. Self-hosting PandaStack means running the control-plane API and per-host agents on Firecracker-capable Linux boxes (KVM required — bare metal or a VM host that supports nested virtualization) and getting the same microVM substrate: sandboxes, git-driven app hosting, and per-tenant database VMs, with 16,384 pre-allocated network slots per agent host for fast sandbox networking. Neither self-hosting path saves you the underlying trade-off — you still don't get an auto-generated API on PandaStack, and you still don't get VM-level tenant isolation on Supabase.

What deploying actually looks like

On Supabase, 'deploying' usually means pushing SQL migrations and maybe an edge function — there's rarely a full application server to deploy at all, because the generated API is the server. On PandaStack, you deploy a real application: point at a git repo, PandaStack detects the framework, builds it in an isolated microVM, health-checks it, and flips traffic blue-green. That's the shape of the platform — it hosts what you built, rather than generating what you'd otherwise have to build.

# Deploy a FastAPI backend (or any git repo) from scratch, auto-deploying on
# every push to main. There's no schema to define first -- you bring the app.
curl -sS -X POST https://api.pandastack.ai/v1/apps \
  -H "Authorization: Bearer $PANDASTACK_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "acme-api",
    "git_url": "https://github.com/acme/api",
    "git_branch": "main",
    "auto_deploy": true
  }'

# Attach a dedicated managed Postgres -- not a shared multi-tenant cluster,
# a real per-database Firecracker microVM -- and wire the connection string
# into the app's env.
curl -sS -X POST https://api.pandastack.ai/v1/databases \
  -H "Authorization: Bearer $PANDASTACK_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"label": "acme-api-db", "size": "1g"}'

# Need to run something you don't fully trust -- a customer's script, code an
# LLM just generated -- inside the same platform? That's a sandbox, not an
# app: a fresh Firecracker microVM restored from a snapshot in ~179ms p50.
curl -sS -X POST https://api.pandastack.ai/v1/sandboxes \
  -H "Authorization: Bearer $PANDASTACK_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"template": "code-interpreter", "ttl_seconds": 600}'

There's no Supabase equivalent to that third call, by design — a BaaS built around 'your schema is your API' has no reason to expose a general-purpose untrusted-code-execution primitive, and Supabase Edge Functions don't attempt to be one.

Where Supabase is the better choice

  • You want a backend without writing one. Define tables and RLS policies, get REST and GraphQL for free. For a CRUD app with auth, this is dramatically less code than writing and hosting your own API server.
  • You need realtime and storage out of the box. Live query subscriptions, presence, broadcast, and file storage as managed, integrated products with client SDKs — building and hosting those yourself is real work Supabase has already done.
  • Auth is a solved problem for you. Email/password, OAuth, magic links, and JWTs that your RLS policies read directly, with a mature dashboard and years of production hardening across a huge number of apps.
  • You want the biggest ecosystem and community for this exact pattern. Supabase has extensive documentation, a large Discord/GitHub community, and countless tutorials and starter templates for the BaaS pattern specifically.
  • Your tenants don't need VM-level isolation from each other. If row-level security inside one well-configured Postgres cluster meets your compliance and threat model, it's operationally simpler and cheaper than a VM per tenant.

Where PandaStack is the better choice

  • You need to run untrusted or AI-generated code. Customer scripts, LLM-generated code, notebook cells, agent tool calls — code you don't trust needs a kernel boundary, and that's not what a BaaS is built to provide.
  • You're deploying real applications, not just a schema. Any language, any framework, your own build and start commands — not limited to what an edge-function runtime supports.
  • Per-tenant isolation is a hard requirement, not a nice-to-have. If a security review asks 'what stops tenant A's workload from touching tenant B's,' 'separate virtual machines' is a stronger answer than 'a row-security policy we tested.'
  • You want fork and snapshot as real primitives. A forked microVM inherits its parent's memory and disk copy-on-write — 400–750ms same-host, 1.2–3.5s cross-host — which has no equivalent in a shared-database model.
  • You want to self-host with true tenant isolation. Apache-2.0, and the isolation boundary you get on your own infrastructure is the same VM-per-workload model, not a policy layer you have to get right inside one shared Postgres cluster.

How to choose in one paragraph

If you're building a product where the backend is fundamentally 'a database with access rules,' and you want auth, a generated API, realtime, and storage without writing or hosting a server yourself — use Supabase. That's not a smaller use case, it's most apps, and a huge amount of real software gets built and shipped exactly that way. Choose PandaStack when the thing you need to run is code, not just data: an app you're deploying by git push in whatever language you wrote it in, untrusted or AI-generated code that needs a real kernel boundary, or per-tenant workloads where VM-level isolation is a requirement your customers or your compliance team will actually ask about. Plenty of teams end up using both — Supabase (or something like it) for the data-and-auth layer, PandaStack for the parts that need to execute code they don't fully control.

Frequently asked questions

Is PandaStack a Supabase alternative?

Only for specific pieces, not as a drop-in replacement. Supabase is a batteries-included backend-as-a-service: point it at a Postgres schema and get an auto-generated REST/GraphQL API, RLS-based auth, realtime subscriptions, and storage, with little to no backend code required. PandaStack doesn't generate an API from your schema or ship a built-in auth product — it's a Firecracker-microVM compute substrate for running code you write: sandboxes for untrusted/AI-generated code, git-driven app hosting for any language or framework, and managed Postgres as dedicated per-tenant VMs. If what you actually want is Supabase's specific BaaS pattern, PandaStack won't replicate it. If what you want is a place to deploy real applications and isolate risky code, PandaStack is built for that and Supabase generally isn't.

How does database isolation differ between the two platforms?

Supabase's multi-tenancy model, for teams using RLS, puts multiple tenants' rows in the same Postgres tables inside one shared project database, with row-level-security policies enforcing who can see what on every query. PandaStack's managed Postgres is one dedicated Firecracker microVM per database — a separate process, disk, and buffer cache per tenant, not a shared cluster with policy-based filtering. Create takes 30–90 seconds because it's provisioning a real instance. The trade-off runs both ways: RLS in a shared cluster is cheaper to operate at scale and makes cross-tenant queries easy when you want them; a VM per tenant gives up that convenience for a materially stronger isolation boundary. Verify Supabase's current RLS and multi-tenancy guidance against their own docs, since the specifics can change.

Can I run untrusted or AI-generated code on Supabase?

Not really, and it isn't trying to support that. Supabase Edge Functions run on Deno, sandboxed for the workloads they're designed for — webhook handlers and small API glue in JavaScript/TypeScript — but there's no general filesystem access, no arbitrary-language support, and no path to running a customer's own compiler or package manager. That's a deliberate scope limit for a BaaS optimized around schema-to-API generation. PandaStack sandboxes exist specifically for this: each one restores from a baked Firecracker snapshot in about 179ms p50 with its own kernel behind the hypervisor, built to run code you genuinely don't trust — AI agent output, customer scripts, per-tenant logic — not just to sandbox your own well-behaved functions.

Do I still need to write my own backend if I use PandaStack?

Yes. PandaStack has no equivalent to Supabase's auto-generated REST/GraphQL API and no built-in auth product — you write the server (in any language or framework) and PandaStack's job is to deploy it from your git repo, build it, health-check it, and run it in an isolated microVM behind a stable URL with blue-green deploys. If avoiding backend code entirely is the goal, that's exactly what Supabase is built to do and PandaStack is not trying to compete on that axis.

Can I self-host either platform?

Yes, both are open source. Self-hosting Supabase means running its service mesh yourself — Postgres, GoTrue for auth, PostgREST, Realtime, and Storage — typically via Docker Compose or Kubernetes, and you get the same BaaS surface on your own infrastructure. Self-hosting PandaStack (Apache-2.0) means running the control-plane API plus per-host agents on your own Firecracker-capable Linux hosts (KVM required), which gets you the same microVM substrate — sandboxes, git-driven app hosting, per-tenant database VMs — with true VM-level tenant isolation rather than a row-security policy layer inside one shared Postgres instance. Self-hosting doesn't change which platform's core model fits your problem; it just moves it onto hardware you control.

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.