Research / Guides

Troubleshooting guide

Sign-in, database and storage all down at once: how to fix it

Every customer is locked out at the same moment. Sign-in fails, pages that read data come back empty, and uploaded files will not load. We have 6 verified builder reports of this pattern, across Supabase, Convex and hosted app builders. There is usually one cause, because auth, database and storage all depend on the same project and the same keys.

6 verified cases in our dataUpdated 2026-09-26How we collect cases

What you'll see

Why it happens

The project was paused

Supabase can pause a Free plan project that shows low activity over a 7-day period, and it emails a warning first. A paused project returns HTTP 540 and cannot process requests until the owner resumes it. Paid Supabase projects are not paused for inactivity.

A quota, spending limit or unpaid bill triggered a restriction

When Supabase applies its Fair Use Policy, every API request can return 402 with a reason such as exceed_egress_quota, exceed_db_size_quota or overdue_payment. On the Firebase Spark plan, exceeding a product's no-cost quota in a calendar month shuts that product off for the rest of the month, for every app in the project. A Convex deployment that exceeds a usage limit is disabled for the rest of the window, and new function calls return an error that says so.

A key was rotated, disabled or deleted while the app still sends it

Supabase's publishable and secret keys work alongside the legacy anon and service_role keys. Disabling the legacy keys is a separate step in Settings > API Keys. If you disable or replace a key before every client uses the new one, every request from those clients fails. Supabase is deprecating the legacy anon and service_role keys by the end of 2026, and deleting a secret key cannot be undone.

An environment variable was lost or frozen in a deploy

Next.js inlines NEXT_PUBLIC_ variables into the browser bundle at next build, so later changes to them have no effect until you build again. On Vercel, a change to an environment variable applies only to new deployments. If you fix a value in the dashboard without redeploying, production keeps the old one. If a build ran without the variable, production ships an undefined URL or key.

The provider is having an incident

Sometimes nothing on your side changed. Check the provider's status page (for Supabase, status.supabase.com) before you rotate keys or roll back code. Those changes add a second fault you will have to debug once the incident clears.

How to fix it

  1. Read the status code before changing anything

    Call the auth health endpoint directly from outside your app. The status code points to the cause. You can also read it in the browser's DevTools Network tab on the failing page.

    curl -s -o /dev/null -w "%{http_code}\n" \
      "https://<project-ref>.supabase.co/auth/v1/health" \
      -H "apikey: <your-publishable-key>"
    # 200 healthy · 402 restricted (quota or billing) · 540 paused
  2. Clear the account-level cause

    For a paused Supabase project, open the dashboard, select the project and choose Resume project. For a 402, the response names the exceeded quota or overdue payment, so resolve that in billing. On Convex, raise, disable or delete the usage limit that was triggered. On Firebase Spark, upgrade to Blaze or wait for the next billing cycle.

  3. Make every deployed key match the provider's current keys

    Compare the keys in your hosting environment with Settings > API Keys in the dashboard. When you rotate a key, replace it everywhere it is used, then disable or delete the old one.

  4. Rebuild after any environment change

    List the production variables and confirm that every one the build needs is present. Then deploy again so the NEXT_PUBLIC_ values are inlined with the correct values.

    vercel env ls production   # every variable the build reads should be listed
    vercel --prod              # new deployment picks up the current values
  5. Add a health route that covers sign-in and one real read

    Point an external uptime monitor at this route so an outage alerts you before a customer reports it. The read targets a small health_check table with one row and a select policy that allows anon, so Row Level Security does not hide the result.

    // app/api/health/route.ts
    export async function GET() {
      const url = process.env.SUPABASE_URL!;
      const headers = { apikey: process.env.SUPABASE_PUBLISHABLE_KEY! };
      const [auth, data] = await Promise.all([
        fetch(`${url}/auth/v1/health`, { headers, cache: "no-store" }),
        fetch(`${url}/rest/v1/health_check?select=id&limit=1`, { headers, cache: "no-store" }),
      ]);
      const ok = auth.ok && data.ok;
      return Response.json({ auth: auth.status, data: data.status }, { status: ok ? 200 : 503 });
    }
  6. Render an error state instead of an empty screen

    Check the error your client library returns and show a 'service unavailable' message. An empty list tells customers their data is gone.

    const { data, error } = await supabase.from("projects").select("id, name");
    if (error) {
      console.error("projects read failed", error.code, error.message);
      return { state: "unavailable" as const }; // show a banner, not an empty list
    }
  7. Write down your plan's limits and who gets alerted

    Record your plan's pause rules, quotas and restriction behavior. Firebase budget alerts do not cap usage or charges. Convex emails the whole team when a production or preview deployment reaches a usage threshold, so make sure the right inbox is on the team.

Check it's fixed

With Gemmein

Gemmein is in beta. It is one backend for sign-in, protected data and payments, so those also share one dependency, and you still need the external uptime check above. Quotas work differently: going over your plan's band is never refused. The owner is notified and the overage is billed the next month. Every failure comes back as a typed GemmeinError code with a message you can render, so the app can show an error state instead of a blank screen. The trade-off is that sign-in is one-time email codes only, with no passwords and no social login, which will not suit every app.

Read more on gemmein.com →

Questions

Why did sign-in, data and files all fail at the same moment?

They share one project, one set of keys and one billing account. A pause, a restriction, a rejected key or a missing URL breaks all of them at once.

What status code does a paused Supabase project return?

540, and it keeps returning it until the owner resumes the project from the dashboard. A 402 means a Fair Use restriction instead, and the response names the reason.

Will upgrading to a paid plan prevent this?

It removes some causes. Paid Supabase projects are not paused for inactivity, and Firebase Blaze does not shut products off at the no-cost quota. It does not protect you from a rotated key, a lost environment variable or a provider incident.

My app is on a hosted builder and support has not replied. What can I check myself?

Open DevTools, go to the Network tab and note the status code and response body of the failing requests. Then check the platform's status page. If you have access to the underlying backend dashboard, check it for a pause or restriction notice.

I fixed the environment variable but production still uses the old value. Why?

NEXT_PUBLIC_ values are fixed at build time, and on Vercel a variable change applies only to new deployments. Deploy again after the change.

Sources

Related guides

← Back to the full report: what breaks when AI apps go live