Define the Supabase service boundary
Self-hosted Supabase centres on PostgreSQL and a set of services that provide common application functions such as generated APIs, authentication, storage, realtime features, and administration. An application need not use every service. Start by mapping the user journeys, database schema, file types, API consumers, and realtime requirement, then deploy and expose only the parts that fit that map.
The database remains the place where business data and authorisation rules live. A generated API is useful, but it does not remove the need to design roles, ownership, migrations, and recovery. Treat application tables and policies as code-reviewed changes. A broad service key or database credential can bypass a carefully designed client-facing policy, so make the boundary between trusted server work and browser work explicit.
For an illustrative internal portal, the first release might use PostgreSQL, authentication, and storage but no realtime connection. That is a valid scope. Add realtime after the team has tested subscription behaviour, network exposure, and capacity under the application's actual event pattern.
Design database and API access together
Model tables before exposing them. Name data owners, define migrations, choose primary keys and relationships, and decide which operations each user role may perform. PostgreSQL roles and row-level security policies deserve the same review as application code because they determine whether a request may read, insert, update, or delete a record. Keep policies small enough that another engineer can test and explain them.
Use realistic test users for every policy. Test an allowed read, an allowed write, a cross-tenant attempt, an attempt to alter ownership fields, and an administrator-only operation. Include API behaviour and direct database paths where the architecture allows them. A policy that works in a console under an elevated credential proves very little about a browser client.
Generated API endpoints should be placed behind an intended network and authentication boundary. Keep privileged secrets on trusted server components, rotate them through a controlled secret store, and record which internal service owns each credential. Do not place a privileged service secret in a mobile build, public browser code, or a copyable dashboard configuration.
Treat identity, files, and events as separate risks
Authentication configuration affects account creation, sessions, redirects, and recovery. Choose approved identity flows and test them from the actual browser origins and network paths that users will use. Keep an emergency administration procedure, but do not make a shared break-glass account the usual support route. Offboarding needs to remove access from the identity path and any application roles derived from it.
Storage needs its own authorisation review. List bucket purposes, allowed file types, maximum sizes, malware or content inspection responsibilities, retention, and who can read each object. Test object access with an ordinary user, another tenant's user, and a server-side component. File metadata and signed access paths can disclose information even when the object itself is protected.
Realtime workload depends on subscriptions, event rate, client reconnects, and database changes. Measure the intended use case rather than assuming a chat-like workload. Set limits and observe behaviour when a client reconnects or a downstream dependency fails. If the application does not need immediate events, simpler request-response paths often reduce the operating surface.
Operate the self-hosted stack as one service
Self-hosting adds responsibility for PostgreSQL, Supabase service configuration, network access, object storage where used, backups, monitoring, and updates. Follow the current self-hosting architecture and release guidance for the selected version. Keep an architecture record that shows databases, service endpoints, storage, identity, ingress, and the system that supplies secrets. This keeps troubleshooting from becoming a search across undocumented containers.
Back up database data and test the restore path alongside files and configuration. A database-only restore may leave records pointing at missing objects; an object-only recovery may restore files with no authorisation context. Set recovery objectives with the application owner, test in isolation, and record the accepted loss window and steps that still require manual work.
Run upgrades through a representative environment when possible. Confirm migrations, API behaviour, row-level security tests, login, uploads, and any realtime use. Pin the versions that passed the test, read version-specific compatibility notes, and name the person who decides whether an issue requires rollback or a corrective release.
Decisions that need an owner
Write down the boundary before clients depend on it.
| Area | Decision | Evidence |
|---|---|---|
| Client access | Which tables and operations are exposed to browser clients? | Policy tests for allowed and cross-tenant requests. |
| Server privilege | Where are privileged credentials used and who can change them? | Secret inventory and a reviewed trusted-service boundary. |
| Files | Which buckets, retention rules, and object permissions are allowed? | Restricted-user upload and download tests. |
| Recovery | How do PostgreSQL, storage, configuration, and identity dependencies return? | An isolated exercise with documented limits. |
Questions to ask before launch
Does row-level security remove the need for application checks?
No. It is a database enforcement layer and should be tested, but application code still needs correct identity handling, input validation, workflow rules, and careful use of privileged credentials.
Can one storage bucket serve every file type?
It can, but different files often need different permissions, retention, processing, and exposure rules. Separate purposes where that makes policy and review clearer.
What is a useful acceptance test?
Use ordinary accounts to complete a real journey, attempt prohibited cross-tenant actions, upload and retrieve an allowed file, then restore the agreed data boundary in an isolated environment.
Roll out safely
Map tables, user roles, API clients, file paths, event requirements, trusted services, and recovery targets before choosing the deployed components.
Run policy and identity tests with real user roles. Exercise uploads, migrations, database recovery, and API failures through the same ingress path clients will use.
Monitor database health, service availability, storage growth, credential changes, and access failures. Review upgrades, policy changes, and incident records with application owners.
Handover evidence
Keep these items in the platform runbook.
Policy test set
Named tests cover each role's allowed actions and prohibited tenant or ownership changes.
Service map
The map names database, API, identity, storage, ingress, secrets, and their operating owners.
Recovery drill
The team has exercised the agreed restore boundary for database data, objects, and configuration.

