Skip to main content

Supabase Production Checklist for React Native and Expo Apps

· 9 min read
Full Stack Developer

A React Native app can connect to Supabase in minutes. Production readiness takes more work: every exposed table needs an authorization model, mobile auth links must return to the right build, database changes need a repeatable release process, and the team needs a way to detect and recover from failures.

This checklist starts after the basic integration works. Use it before the first public release and repeat the relevant sections before major launches.

The short version​

Do not ship until you can answer yes to these questions:

  • Does the app contain only a Supabase publishable key, never a secret key?
  • Is Row Level Security enabled and tested for every client-accessible table?
  • Are Storage buckets protected by explicit policies?
  • Do sign-up, deep links, token refresh, sign-out, and account recovery work in release builds?
  • Are database changes tracked as migrations and tested outside production?
  • Are custom SMTP, abuse controls, indexes, logs, and alerts configured?
  • Do you know what is backed up and how you would restore service?
  • Have you tested the expected load and failure states?

The Supabase platform secures and operates its infrastructure, but your schema, queries, access policies, keys, capacity, and application behavior remain your responsibility.

1. Use the correct API key in each environment​

A mobile binary is a public environment. Anyone can inspect values bundled in it, even when they came from a build-time environment variable.

Supabase's current key model separates:

  • publishable keys for public clients such as mobile and web apps;
  • secret keys for trusted server components that you control.

Legacy projects may still use anon and service_role keys. Supabase is moving from those legacy keys to publishable and secret keys, but the security boundary is the same: the low-privilege public key can ship in the app; the elevated key must not.

Never place a secret or legacy service_role key in:

  • React Native source code;
  • Expo public configuration;
  • EAS environment variables that are embedded in the client bundle;
  • over-the-air updates;
  • a public repository;
  • logs, analytics events, or crash reports.

Secret keys bypass Row Level Security. Use them only in a server, protected API, worker, or Supabase Edge Function that performs its own authorization checks.

2. Enable Row Level Security everywhere the client can reach​

Supabase makes direct client access practical through Postgres Row Level Security. RLS must be enabled on every table exposed through the Data API, with policies that express who can read, insert, update, and delete each row.

For user-owned data, a policy often compares the authenticated user's ID with a column such as user_id. The exact model depends on your product, but the tests should cover both allowed and denied access.

For every policy, test at least:

  1. the owner can perform the intended action;
  2. another signed-in user cannot access the row;
  3. a signed-out user cannot access protected data;
  4. an update cannot transfer ownership by changing an owner column;
  5. list queries do not reveal rows outside the user's scope;
  6. related views and functions preserve the same boundary.

Do not verify policies only from the SQL editor with an administrative role. Test through the same publishable key and authenticated sessions that the app uses.

3. Protect Storage with the same rigor as database rows​

A private database row does not automatically make its associated file private. Review every Storage bucket and decide whether it is public or private.

For private buckets, define policies for:

  • listing objects;
  • downloading an object;
  • uploading to an allowed path;
  • replacing or deleting an object;
  • limits on file type and size enforced by your application or server.

Use predictable ownership paths only when policies validate them. Do not trust a client-provided folder name by itself. Test attempts to read and overwrite files owned by another account.

4. Test the complete mobile authentication lifecycle​

Authentication works differently in a development client, a store build, and a standalone app. Verify the full lifecycle on physical devices:

  • email-and-password sign-up and confirmation;
  • magic links or one-time passwords, if enabled;
  • OAuth provider redirects;
  • password recovery;
  • session restoration after a cold start;
  • token refresh after the app returns from the background;
  • sign-out and removal of local session state;
  • deleted, disabled, and expired accounts.

Configure the correct redirect URLs and app links for development, staging, and production. A link that opens Expo Go successfully may still fail in a signed store build.

For production email flows, configure a custom SMTP provider. Supabase describes its default SMTP service as a limited, best-effort option for exploration rather than a production delivery service. Test email templates, sender reputation, link tracking, and recovery flows before launch.

5. Add abuse controls before traffic arrives​

Review Auth rate limits and enable the protections that match your threat model. Common controls include:

  • email confirmation;
  • reasonable OTP expiry and resend intervals;
  • CAPTCHA for sign-up, sign-in, and password recovery where appropriate;
  • MFA for administrative access and high-risk user actions;
  • server-side rate limits for expensive custom endpoints;
  • limits on anonymous sign-ins and resource creation;
  • monitoring for repeated failures or unusual traffic.

Protect the Supabase organization itself with MFA. Ensure more than one trusted owner can recover administrative access without sharing credentials.

6. Make schema changes reproducible​

Production schema changes should come from reviewed migrations, not a sequence of undocumented dashboard edits.

A practical workflow is:

  1. create the migration locally;
  2. test it against a disposable or staging database;
  3. regenerate TypeScript types;
  4. run application and policy tests;
  5. review backward compatibility with the current mobile release;
  6. apply the migration through a controlled deployment path;
  7. verify the resulting schema and application health.

Mobile releases can remain installed for months. Prefer additive database changes first, release compatible app code, observe adoption, and remove old columns or behavior later. A migration that requires every user to update the app immediately is fragile.

7. Separate development, staging, and production​

Use separate Supabase projects or an equivalent isolated workflow so tests and previews cannot mutate production data.

Each environment should have its own:

  • project URL and keys;
  • database and Storage buckets;
  • Auth redirect URLs and provider credentials;
  • Edge Function secrets;
  • webhook destinations;
  • test accounts and seed data.

Do not copy raw production user data into development. If a realistic dataset is needed, create minimized, sanitized fixtures.

8. Review query performance and capacity​

RLS policies and application queries both affect database work. Before launch:

  • add indexes for columns used in filters, joins, ordering, and RLS predicates;
  • remove unbounded list queries;
  • paginate large collections;
  • avoid fetching columns the screen does not use;
  • inspect slow and frequent queries with Supabase's database tooling;
  • review connection usage for servers and functions;
  • test expected traffic against staging;
  • understand the compute and Realtime limits of your plan.

Load testing should model real user behavior and stay away from production. Test sign-in bursts, the busiest read paths, writes that trigger database functions, file uploads, and Realtime subscriptions separately.

9. Make Realtime access explicit​

Only enable replication for tables that need Realtime behavior. Sensitive data still needs RLS and appropriate Realtime authorization.

In the app, handle:

  • duplicate or out-of-order events;
  • reconnects after backgrounding;
  • stale UI when the subscription is unavailable;
  • channel cleanup when a screen unmounts or a user signs out;
  • a fallback refresh path.

Realtime should improve the experience, not become the only way the app can recover correct state.

10. Prepare backups and a recovery procedure​

Know which backup features your Supabase plan provides, how long backups are retained, and whether Point-in-Time Recovery is enabled. Supabase also documents CLI database dumps for teams that need their own logical exports.

A backup is useful only if the team knows how to use it. Document:

  • who can initiate recovery;
  • which data and roles are included;
  • how Storage objects are handled;
  • the expected recovery point and recovery time;
  • how the app behaves while recovery is in progress;
  • how restored data is verified before traffic returns.

Run a recovery exercise with non-production data. Do not wait for an incident to discover that the procedure is incomplete.

11. Add observability and an incident path​

At minimum, monitor:

  • API and Auth error rates;
  • database CPU, memory, connections, and disk usage;
  • slow or high-volume queries;
  • Edge Function failures and latency;
  • Storage upload failures;
  • Realtime connection problems;
  • mobile crashes and failed network requests.

Alerts need an owner and a response. Write a short runbook for expired keys, email delivery failures, a failed migration, high database load, and suspected unauthorized access. Keep credentials and raw user data out of logs.

12. Run the final release check​

Use a signed release build, production-like configuration, and test accounts. Verify:

  • a new user can register and confirm an account;
  • an existing user can sign in, recover access, and sign out;
  • one user cannot access another user's rows or files;
  • offline, timeout, and rate-limit errors have usable UI;
  • database migrations work with the previous and new app versions;
  • analytics and crash reporting contain no secrets or sensitive payloads;
  • support can identify the app version and environment involved in a report.

Record the result and the exact versions tested. Production readiness is an evidence-backed release decision, not a feeling that the integration looks done.

Current platform notes: September 2026​

Supabase is transitioning hosted projects from legacy anon and service_role keys to publishable and secret keys. Existing legacy keys can continue to work during migration, but new implementation guidance should use a publishable key in the mobile app and keep secret keys in controlled backend components.

Re-check the official production checklist, key documentation, limits, and backup options before each major release because plan capabilities and platform defaults can change.

How this guide stays current​

UpdatedPlatform contextWhat changed in this guide
September 2026Publishable and secret key migrationUpdated client/server key guidance and retained legacy-key migration context.

If you are still building the first integration, start with our Supabase tutorial for React Native, then return to this checklist before release.

Authoritative references​

Practical product notes

Get the next useful guide

Occasional tutorials, product resources, and lessons from building and launching software.