How to Keep Your Supabase Project from Getting Paused
March 2025
Supabase offers a generous free tier for developers, but one common issue many users face is their free projects getting paused after 1 week of inactivity. When a project is paused, database connections and API requests stop working until it's manually resumed, which can be disruptive.
Supabase automatically pauses projects when the project hasn't received API requests or when there has been no database activity for a certain period to time.
There are multiple ways to prevent your Supabase project from getting paused:
- Upgrading to a Paid Plan
- Scheduling a Cron Job that periodically send requests to Supabase
In this blog, we will focus specifically on using a Cron Job to query the API Daily, ensuring your project remains active without manual intervention.
Using a Cron Job to Query the API Daily
- Create an API called
/healthin your backend that a cron job can periodically call. The endpoint can perform a simple operation, such as querying a single record from a table in Supabase.
1https://*****.vercel.app/api/health 2
- To enhance security, include a secret key as a query parameter to authenticate requests before executing the check.
1https://*****.vercel.app/api/health?secret=abcdefghijklmnopqrstuvwxyz1234567890 2
- Next, go to Google Cloud Console and use Cloud Scheduler to set up a job that periodically calls your health API endpoint. Configure the job with the following steps:
- Name:
supabase-keep-alive - Description:
Daily trigger to keep supabase project alive - Frequency:
0 9 * * *(Triggers daily at 9:00 AM) - Target Type:
HTTP - URL:
https://*****.vercel.app/api/health?secret=abcdefghijklmnopqrstuvwxyz1234567890 - HTTP Method:
GET
- Name:
- Like clockwork, the
/healthendpoint is triggered daily by Google Cloud Scheduler, ensuring that the project remains active. - How to check if the
/healthendpoint is called every day and whether it was successful or not? Manually checking Cloud Scheduler isnβt practical. - So letβs set up Slack notifications to track both success and failure.
Slack notifications
Here is how you can use Slack Incoming Webhooks feature to receive success/failure notifications.
- Visit Slack Incoming Webhooks
- Create a new webhook and select the channel where you want to receive notifications
- You'll receive a webhook URL, something like
https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX - Integrate this webhook call into your
/healthendpoint to send notifications - Here is a sample
/healthendpoint implementation
1import { createClient } from "@supabase/supabase-js"; 2import { NextRequest, NextResponse } from "next/server"; 3 4const supabaseUrl = process.env.SUPABASE_URL || "" 5const supabaseKey = process.env.SUPABASE_KEY || "" 6const supabase = createClient(supabaseUrl, supabaseKey) 7 8async function sendSlackMessage(message: string) { 9 const timestamp = new Date().toLocaleString("en-IN", { 10 timeZone: "Asia/Kolkata", 11 day: "2-digit", 12 month: "long", 13 year: "numeric", 14 hour: "2-digit", 15 minute: "2-digit", 16 second: "2-digit", 17 hour12: true 18 }).replace(" am", " AM").replace(" pm", " PM") 19 20 await fetch(process.env.SLACK_WEBHOOK_URL!, { 21 method: "POST", 22 headers: { 23 "Content-Type": "application/json", 24 }, 25 body: JSON.stringify({ 26 text: `*π Supabase Keep-Alive Triggered!* ${message} π ${timestamp}` 27 }) 28 }) 29} 30 31export async function GET(req: NextRequest) { 32 try { 33 /* Simple authenticate */ 34 const token = req.nextUrl.searchParams.get("token") 35 if (token !== process.env.HEALTH_CHECK_SECRET) { 36 await sendSlackMessage("β Authorization failed") 37 return NextResponse.json({ status: "unauthorized" }, { status: 401 }); 38 } 39 40 /* Call to database */ 41 const { data, error } = await supabase 42 .from('languages') 43 .select() 44 45 /* Check if error occurred */ 46 if (error) { 47 await sendSlackMessage("β Call to database failed") 48 return NextResponse.json({ status: "database error", error }, { status: 500 }); 49 } 50 51 /* Check if data is found */ 52 if (data.length === 0) { 53 await sendSlackMessage("β No data found") 54 return NextResponse.json({ status: "no data found" }, { status: 404 }); 55 } 56 57 /* Send success message */ 58 await sendSlackMessage("β Keep-alive check executed successfully") 59 return NextResponse.json({ status: "ok" }, { status: 200 }); 60 } catch (error) { 61 await sendSlackMessage("β Internal server error") 62 return NextResponse.json({ status: "internal server error", error }, { status: 500 }); 63 } 64} 65
- Here is how you'll receive slack notifications

Now, whenever the cron job runs, it will trigger a Slack message confirming the query was successful or reporting an error.
I hope this was helpful!