scribase
All posts
·Scribasesupabasefree-tierkeep-alive

Why Supabase pauses free projects, and three ways to stop it

What Supabase's docs actually say about the 7-day pause, how to restore a paused project, and three fixes: a free GitHub Action, the Pro plan, or a backend that scales to zero instead of pausing.

If you landed here, your Supabase project probably answered every request with a bare "Failed to fetch" one morning, and the dashboard showed a Restore project button where your app used to be. This post explains why that happens, quoting the documentation rather than folklore, and gives three ways to make it not happen again. The first one is free and takes one file.

What the docs say

Supabase's pricing page states it plainly: "Free projects are paused after 1 week of inactivity", and the Free plan has a "Limit of 2 active projects" (pricing). The production checklist adds the nuance: "We may pause applications on the Free Plan that exhibit low activity in a 7-day period to save on server resources" (going into production).

What counts as activity, per the official FAQ: "Opening the project in the dashboard or sending real requests from your app both count as activity", and "You get an email about a week before a pause, and another once it happens" (FAQ). Supabase does not publish the exact threshold. Requests through the project's API that touch the database are the documented path, which matters for the fix below.

Paid plans are not paused for inactivity: "Upgrade to Pro to guarantee that we won't pause your project for inactivity" (same production checklist).

How to tell it is paused, and how to get it back

A paused project answers every API request with HTTP 540 (HTTP status codes). In a browser the symptom is usually a network error without CORS headers, so the app reports "Failed to fetch" or "Load failed" rather than 540.

curl -s -o /dev/null -w '%{http_code}\n' \
  -H "apikey: $SUPABASE_ANON_KEY" "https://YOUR-REF.supabase.co/rest/v1/"
# 200 = awake, 540 = paused

To restore: open the project in the dashboard and click Restore project. You need a free slot (2 active projects on the Free plan; paused projects do not count). The docs say "users have a 1-year window to restore the project on the platform from within Supabase Studio", after which the backup file and Storage objects can still be downloaded (upgrading). You may read elsewhere that paused projects are deleted after 90 days; as of 2026-11-12 the docs say one year for one-click restore. Check the current docs before relying on either number, and take a supabase db dump as soon as the project is back.

Fix 1: a daily query from a free GitHub Action

The documented path to "active" is real database requests through the API. So make one every day. A scheduled GitHub Actions workflow with one curl is enough (no third-party action, no runtime to update):

# .github/workflows/keep-alive.yml  (secrets: SUPABASE_URL, SUPABASE_ANON_KEY)
name: Keep Supabase alive
on:
  schedule:
    - cron: "17 6 * * *"
  workflow_dispatch:
permissions:
  contents: read
jobs:
  ping:
    runs-on: ubuntu-latest
    steps:
      - name: Read one row   # any small table works
        run: |
          curl -fsS --retry 3 --retry-delay 10 \
            "${{ secrets.SUPABASE_URL }}/rest/v1/keepalive?select=*&limit=1" \
            -H "apikey: ${{ secrets.SUPABASE_ANON_KEY }}" \
            -H "Authorization: Bearer ${{ secrets.SUPABASE_ANON_KEY }}"

Two details matter more than the cron line:

  • Read a table, not just the root. A GET /rest/v1/ alone proves the gateway is up; reading one row of a small table is a database request. The step above does that with the anon key, so the table needs RLS on and a policy that allows the read (a keepalive table with one public row is the usual shape). An RPC that returns a constant has been reported as not enough; a read that touches a table is the safe choice.
  • Watch the watcher. GitHub disables scheduled workflows in repositories with no pushes for 60 days, and a weekly cron can miss the 7-day window after one failed run. Turn on failure notifications for the workflow so a silent stop does not go unnoticed.

The same idea works from Vercel cron, a Cloudflare Worker cron trigger, or any machine with curl; GitHub Actions is just a free scheduler for it. Treat every keep-alive as fragile by construction: Supabase decides what counts as activity, and the docs say "may pause".

Fix 2: pay Supabase

Supabase's Pro plan costs $25 a month plus $10 a month of compute credits per organization (pricing), and it is the only option that Supabase itself documents as removing the pause. If the project earns money or holds data you cannot lose, this is the straightforward answer and there is nothing clever to add.

Fix 3: a backend that scales to zero instead of pausing

The pause exists because a free project occupies a running Postgres whether or not anyone is using it. The other way to solve that is a backend where an idle project costs nothing to keep and wakes on the next request.

If you need Postgres only, Neon's free plan scales compute to zero after five minutes idle and reactivates on the next query (Neon: scale to zero); you keep the database and bring your own auth, storage and email.

If you need the whole backend your app already uses (auth, storage, realtime, functions, the supabase-js client), that is what Scribase is for: one project with Postgres, Auth, Storage, Realtime and Edge Functions behind one URL and one anon key, plus a Resend-compatible email API from the same vendor. Idle projects scale to zero on every tier and are never paused; there is no cap on the number of projects. One project is free with no time limit (0.5 GB database, 1 GB files, no card); new accounts start with 14 days of Hobby, and more projects are from $5 a project a month. Moving a project is one importer run (schema, data, RLS policies, auth users with their password hashes, storage objects, with row counts per table at the end), and export is a button, so you can leave the same way. If a paused project is still inside its restore window, the rescue tool runs that import into a free 72-hour project with no account.

Two defaults come with that move and are worth naming, because they are the reason to centralize rather than just to stop the pause: the project does not go to sleep when nobody is looking, and a migration that would leave a public table without row level security is refused before it runs (how that works).

Which one

  • Side project you want to keep free: Fix 1, today, and set a calendar reminder to check the Action's last run.
  • Production on Supabase: Fix 2.
  • Four vendors, four invoices, and a pause on top: Fix 3, and bring the email and auth with you.

Sources, each read on 2026-11-12: Supabase pricing, going into production, free project pausing FAQ, HTTP status codes, upgrading; Neon scale to zero; Scribase pricing.