Tunas Akara
Back to Blog

Self-Hosting Supabase in Production: What You're Actually Signing Up For

by RayhanUpdated 6 min read
supabaseself-hostingpostgresqldevops
Self-Hosting Supabase in Production: What You're Actually Signing Up For

Self-Hosting Supabase in Production: What You're Actually Signing Up For

Self-hosting Supabase looks like one command: clone the repository, run docker compose up, open Studio. That's day one, and day one is genuinely that easy. The decision you're actually making is about day two hundred — who notices the failed backup, who plans the version upgrade, who rotates the secrets.

I've run self-hosted Supabase in production and migrated teams onto and off of it. This is the honest ledger.

Legitimate reasons to self-host

There are real ones. Data locality: in one healthcare deployment I built, patient-adjacent data wasn't allowed to leave the facility, full stop. The stack ran on a server inside the building, and no managed offering could satisfy that constraint. Regulated industries and government work in Indonesia raise the same wall more often each year.

On-prem mandates: some clients simply require that systems run on infrastructure they control. Cost at scale: past a certain sustained load, a VPS you administer undercuts the managed tier meaningfully.

And there's the illegitimate reason: saving twenty-five dollars a month. If the motivation is a hobby-tier invoice, the ops time will cost more than the subscription ever would.

What the stack actually contains

"Supabase" is not one service. The self-hosted compose file brings up Postgres, GoTrue for auth, PostgREST for the instant API, the Realtime server, the Storage API with an image proxy, Kong as the gateway, Studio, an analytics service, and an edge-functions runtime. A dozen containers, each with its own configuration, logs, failure modes, and release cadence.

Loading diagram…

Think of self-hosting as building your own house — your own plumbing, wiring, and roof — instead of renting a move-in-ready apartment. You're not adopting a database. You're adopting a platform team's worth of services, minus the platform team.

Backups become your job — and buckets count

The managed platform backs you up invisibly. Self-hosted, backups are yours, and the mistake I see most often is scoping them to Postgres alone.

Storage buckets don't live in the database. The Storage API keeps object metadata in Postgres but writes the actual files to a disk volume or an S3-compatible store. Back up only the database and your restore will come up with every bucket intact — as rows pointing at files that no longer exist. The file volume must join the backup scope, and it must be captured consistently with the database dump, or restored metadata and restored files drift apart.

And a backup that has never been restored is a rumor. Restore drills on a schedule are non-negotiable — I've written up the practice in verifying Postgres backups, and it applies doubly here because there are two stores to bring back in step.

Upgrades and monitoring are now yours too

On the managed platform, upgrades happen to you. Self-hosted, an upgrade is a project: a dozen images whose versions must stay mutually compatible, release notes to read, a maintenance window to schedule, and a rollback plan for when auth behaves differently afterwards. Pin every image version explicitly — latest in production is how surprise upgrades happen at 3 a.m.

Monitoring follows the same logic. Disk growth on the database and the file volume, connection-pool saturation, container restarts, certificate expiry — nobody is watching any of it unless you wired the watching yourself.

The security surface

The compose stack is a set of internal services fronted by Kong, and that topology is a security decision: only the gateway belongs on the network edge. Postgres, GoTrue, PostgREST, and Storage should be unreachable from outside — every port you expose beyond the gateway is attack surface you volunteered for.

The JWT secret is the root of trust for the whole stack: the anon and service-role keys handed to clients are derived from it, and anyone holding the service-role key holds your database. Treat rotation as a rehearsed practice, not an emergency skill — rotating the secret invalidates every issued token and both derived keys, so it must be a planned, coordinated change.

Keep secrets in an environment manager, never in a compose file that reaches git. The default secrets in the sample configuration exist to be replaced before the first deploy, not after the first incident.

When managed hosting is the honest recommendation

If nobody on the team will own this — genuinely own it, with backup drills and upgrade windows and monitoring on a dashboard someone actually looks at — the managed platform is the correct answer, and I say so in assessments even when a self-hosting contract would pay better.

The true cost of self-hosting is denominated in people, not servers. It's the right call when a regulatory wall or real scale demands it. It's an expensive hobby when it's chosen for the compose file's one-command charm.

Either way, what you build on top doesn't change — the applications and dashboards that connect these systems neither know nor care where the stack runs. Choose with the ledger open: locality, control, and cost on one side; backups, upgrades, monitoring, and secret discipline on the other. Both sides are real.

Related Posts

Building something similar?

IoT Backend & Multi-Protocol Integration

Backends that ingest device telemetry across MQTT, WebSocket, Modbus, and BLE, and normalize it into reliable real-time dashboards.

See how I can help