new: drive vas from your AI agent over MCP · Cursor, Claude Code, Windsurf
Fly.io
+
Supabase

Fly.io + Supabase Security

Fly.io deploys containers globally close to users, while Supabase provides the database. Cross-region latency and secret synchronisation across machines add unique security dimensions.

Why Fly.io + Supabase?

Fly.io's full container deployment model suits backend applications — APIs, workers, and full-stack servers — that use Supabase as a managed Postgres backend. The combination is popular for latency-sensitive apps needing a globally-distributed server layer.

Common Vulnerabilities

These are the security issues we find most often in Fly.io apps using Supabase.

critical

Service Role Key in Dockerfile or fly.toml

Developers may hardcode Supabase credentials in Dockerfile ENV instructions or fly.toml files, which are committed to version control.

high

Missing RLS When Using Service Role for Performance

Fly.io apps often use the service_role key for all Supabase queries to avoid JWT overhead in latency-sensitive paths. This bypasses RLS and requires manual authorisation logic that is easily missed.

high

Supabase Connection Pooler Misconfiguration

High-concurrency Fly.io apps may misconfigure PgBouncer connection pooling, causing session-level settings (including auth context) to leak between requests.

medium

Secrets Not Set Per App in Multi-App Deployments

When running separate Fly apps (API and worker), teams often share environment variables directly between them rather than setting secrets independently, increasing credential exposure surface.

What We Check for Fly.io + Supabase

Fly Secrets Configuration

Verify all Supabase credentials are set via fly secrets set and not present in Dockerfile, fly.toml, or version-controlled .env files.

Service Key vs Anon Key Usage

Audit application code for service_role key usage and verify each instance either passes user JWT to Supabase or manually enforces equivalent access control.

RLS Effective Verification

For tables accessed via service_role, confirm the application code applies equivalent access restrictions to what RLS policies would enforce.

Connection Pool Session Isolation

Check that the transaction-mode pooler (port 6543) is used for stateless deployments to avoid session leakage between requests.

Quick Security Wins

Apply these fixes right now to improve your security.

Set secrets properly: fly secrets set SUPABASE_SERVICE_ROLE_KEY=your_key — never add to Dockerfile ENV or fly.toml
Add .env and fly.toml to .gitignore to prevent accidental credential commits
Use the anon key with user JWTs for most queries so Supabase RLS handles authorisation automatically
Connect to Supabase via the transaction-mode pooler (port 6543) for containerised deployments
Enable RLS on all tables even if using service_role — it provides a safety net when you switch query modes

The Bottom Line

Fly.io + Supabase is a powerful pairing for latency-sensitive, globally-distributed backends. The service_role key and secret management in multi-machine deployments are the two areas requiring deliberate security attention.

Secure Your Fly.io + Supabase App

Find Row Level Security misconfigurations, exposed credentials, and other vulnerabilities before attackers do.

Start Security Scan

Frequently Asked Questions

How do Fly.io secrets differ from environment variables for Supabase credentials?

Fly secrets are encrypted at rest and injected as environment variables at runtime — they do not appear in your Dockerfile or fly.toml. Always use fly secrets set for Supabase credentials rather than ENV instructions in Dockerfiles, which end up in the image layer and are visible in your git history.

Should I use service_role key in a Fly.io backend API?

It is acceptable for server-side API code to use service_role when it validates user identity itself before any database operation. The risk is that this pattern requires you to replicate RLS logic in application code. A safer approach: pass the user's JWT in the Authorization header when creating the Supabase client so RLS applies automatically.

What Supabase connection mode should I use for Fly.io containers?

Use the transaction-mode pooler (Supabase pooler port 6543) for ephemeral Fly machines. Session mode retains state between queries, which causes problems when connection pools reuse sessions across different users in short-lived containers.

How do I keep Supabase credentials consistent across Fly.io regions?

Fly secrets are global across all machines in an app by default. Run fly secrets set once and the value is available to all machines in all regions. If you have multiple Fly apps (e.g. API and worker), set secrets independently for each app to avoid cross-app credential sharing.