20 Checks Before Your App Goes Live

A free self-check list for apps built with Supabase, Lovable, Bolt, Replit or Cursor. Run it on your own app before real users and real data arrive. Each check says how to test it yourself.

Database and row level security

  1. 1

    Row level security is on for every table in the public schema.

    Supabase dashboard, Table Editor: any table marked RLS disabled is readable by anyone holding your public anon key.

  2. 2

    No policy uses using (true) on data that belongs to a user or a company.

    Search your migrations for using (true) and with check (true). Each one should have a reason you can explain.

  3. 3

    Policies check ownership, not just sign-in.

    A policy that only checks auth.role() = 'authenticated' lets every signed-in user see every row. It should compare against auth.uid() or a membership table.

  4. 4

    Update policies have a with check clause.

    Without it, a user can move a row into another company by changing its owner column.

  5. 5

    Users cannot change their own role.

    If a members or profiles table holds the role, confirm a normal user cannot insert or update that column.

Keys and secrets

  1. 6

    The service role key never reaches the browser.

    Search your code for SERVICE_ROLE. In Next.js, any variable starting with NEXT_PUBLIC_ is sent to the browser. In Vite, the same applies to VITE_.

  2. 7

    Secret files are in .gitignore.

    Confirm .env and .env.local are listed. If a secret was ever committed, rotate it, because git history keeps it.

  3. 8

    Payment and email API secret keys are server only.

    Stripe, Razorpay and email provider secret keys should appear only in server routes or edge functions.

Auth and access

  1. 9

    Admin pages are protected on the server.

    If admin access depends on a value in local storage or a hidden button, any user can switch it on.

  2. 10

    Email confirmation and password rules are set the way you intend.

    Supabase dashboard, Authentication settings.

  3. 11

    Redirect URLs are limited to your own domains.

    Authentication, URL Configuration: the allow list should not contain wildcards you do not need.

  4. 12

    One company can never see another company's data.

    Create two test accounts in two test companies and try to open each other's records by changing IDs in the URL or the request.

Storage and functions

  1. 13

    Buckets with customer files are private.

    Storage settings: a public bucket serves any file to anyone with the link, with no expiry.

  2. 14

    Customer files are served through signed URLs.

    Signed URLs expire. Permanent public links to invoices, IDs or documents do not.

  3. 15

    Edge functions check who is calling.

    A function that takes a user, company or role from the request body and acts on it with the service role key must first confirm the caller is allowed.

  4. 16

    Functions only accept calls from your own domains.

    Look for Access-Control-Allow-Origin set to * on functions that change data.

Payments and launch basics

  1. 17

    Payment webhooks verify the signature.

    Stripe: stripe.webhooks.constructEvent with your webhook secret. Razorpay: validate the X-Razorpay-Signature header.

  2. 18

    Backups or point-in-time recovery are on, and you have tried a restore.

    Supabase dashboard, Database, Backups. A backup you have never restored is a guess.

  3. 19

    Errors reach you before customers tell you.

    Error monitoring with alerts on the front end and in functions.

  4. 20

    Changes are tested somewhere other than production.

    A separate staging project, so a migration mistake never lands on live data first.

Some Checks Failed?

Most of these are quick to fix once you know exactly where they are. Our Quick Launch Check runs this list against your code in 48 hours and tells you what to fix first.