Prevent Supabase project from pausing with GitHub Actions

Schedule a workflow in GitHub Actions to prevent your Supabase project from pausing in free tier.

Natt Nguyen·March 17, 2024 (9 months ago)·3 min read

#supabase
#github-actions
Prevent Supabase project from pausing with GitHub Actions

I never sleep, cause sleep is the cousin of death. — Nas

As an indie software builder, I have been searching for a database for my hobbyist projects. I appreciate Supabase's generous free tier, the speed of the database, and the clean user interface. Projects under the free tier plan will pause after one week of inactivity, with Supabase sending warning emails before and when this occurs. You can easily unpause your Supabase project through the dashboard to get your apps up and running again. Opting for the paid tiers eliminates the pausing of inactive projects.

In this article, I'll show you how to create a GitHub Actions scheduled workflow to call your API and prevent your Supabase project from pausing in the free tier. I will be using Next.js App Router Route Handlers to create an API to fetch data from the database to prevent Supabase project from pausing.

# .github/workflows/supabase-activity-scheduler.yml

name: Supabase Activity Scheduler

on:
schedule:
- cron: "0 0 * * 0,3" # Runs every Sunday and Wednesday
workflow_dispatch:

jobs:
send-http-request:
runs-on: ubuntu-latest

steps:
- name: Send HTTP Request
run: curl https://<YOUR_DOMAIN_NAME>/api/etc/supabase-activity-scheduler
# .github/workflows/supabase-activity-scheduler.yml

name: Supabase Activity Scheduler

on:
schedule:
- cron: "0 0 * * 0,3" # Runs every Sunday and Wednesday
workflow_dispatch:

jobs:
send-http-request:
runs-on: ubuntu-latest

steps:
- name: Send HTTP Request
run: curl https://<YOUR_DOMAIN_NAME>/api/etc/supabase-activity-scheduler
# .github/workflows/supabase-activity-scheduler.yml

name: Supabase Activity Scheduler

on:
schedule:
- cron: "0 0 * * 0,3" # Runs every Sunday and Wednesday
workflow_dispatch:

jobs:
send-http-request:
runs-on: ubuntu-latest

steps:
- name: Send HTTP Request
run: curl https://<YOUR_DOMAIN_NAME>/api/etc/supabase-activity-scheduler
# .github/workflows/supabase-activity-scheduler.yml

name: Supabase Activity Scheduler

on:
schedule:
- cron: "0 0 * * 0,3" # Runs every Sunday and Wednesday
workflow_dispatch:

jobs:
send-http-request:
runs-on: ubuntu-latest

steps:
- name: Send HTTP Request
run: curl https://<YOUR_DOMAIN_NAME>/api/etc/supabase-activity-scheduler

The runtime of the workflow takes around 2 seconds to complete but you are billed for the entire minute. Keep in mind, the project will pause after one week of inactivity. Assuming this workflow runs at least once a week, you'll be consuming approximately 4.35 minutes out of the 2,000 minutes or 0.22% total monthly usage allotted in the GitHub Free plan. I would schedule twice a week just to be on the safer side.

// app/api/etc/supabase-activity-scheduler/route.ts

import { createClient } from "@supabase/supabase-js"

const supabaseUrl = "<YOUR_SUPABASE_URL>"
const supabaseKey = "<YOUR_SUPABASE_KEY>"
const supabase = createClient(supabaseUrl, supabaseKey)

export async function GET() {
try {
// Fetch data to prevent Supabase project from pausing
const { data, error } = await supabase.from("user").select()
if (error) throw new Error(error.message)
return Response.json(data)
} catch (error) {
const message = (error as Error).message ?? "An error occurred."
return Response.json({ error: message }, { status: 400 })
}
}
// app/api/etc/supabase-activity-scheduler/route.ts

import { createClient } from "@supabase/supabase-js"

const supabaseUrl = "<YOUR_SUPABASE_URL>"
const supabaseKey = "<YOUR_SUPABASE_KEY>"
const supabase = createClient(supabaseUrl, supabaseKey)

export async function GET() {
try {
// Fetch data to prevent Supabase project from pausing
const { data, error } = await supabase.from("user").select()
if (error) throw new Error(error.message)
return Response.json(data)
} catch (error) {
const message = (error as Error).message ?? "An error occurred."
return Response.json({ error: message }, { status: 400 })
}
}
// app/api/etc/supabase-activity-scheduler/route.ts

import { createClient } from "@supabase/supabase-js"

const supabaseUrl = "<YOUR_SUPABASE_URL>"
const supabaseKey = "<YOUR_SUPABASE_KEY>"
const supabase = createClient(supabaseUrl, supabaseKey)

export async function GET() {
try {
// Fetch data to prevent Supabase project from pausing
const { data, error } = await supabase.from("user").select()
if (error) throw new Error(error.message)
return Response.json(data)
} catch (error) {
const message = (error as Error).message ?? "An error occurred."
return Response.json({ error: message }, { status: 400 })
}
}
// app/api/etc/supabase-activity-scheduler/route.ts

import { createClient } from "@supabase/supabase-js"

const supabaseUrl = "<YOUR_SUPABASE_URL>"
const supabaseKey = "<YOUR_SUPABASE_KEY>"
const supabase = createClient(supabaseUrl, supabaseKey)

export async function GET() {
try {
// Fetch data to prevent Supabase project from pausing
const { data, error } = await supabase.from("user").select()
if (error) throw new Error(error.message)
return Response.json(data)
} catch (error) {
const message = (error as Error).message ?? "An error occurred."
return Response.json({ error: message }, { status: 400 })
}
}

Run of the mill API to fetch users.

With this step up, you don't need to worry about your apps not working from a paused Supabase project in free tier.

If you aim to fully integrate into Supabase's ecosystem, you can conveniently schedule Supbase's edge functions using pg_cron and pg_net extension directly from the dashboard.

If you are looking for a cron provider with a generous free tier, Vercel has a few listed here.

Subscribe to my blog

I'd love to share my love for design, engineering, and thinking with you when my new articles are published.

You can unsubscribe at any time, no hard feelings.