Skip to content

travisvn/supabase-pause-prevention

Repository files navigation

Supabase Pause Prevention ⏸️

GitHub stars GitHub forks GitHub repo size GitHub language count GitHub top language GitHub last commit Hits

🛑 Stop Supabase projects from pausing due to inactivity! 🙌

On the free-tier plan, projects that are inactive for more than 7 days are paused.

Please star ⭐️ if you find this useful

Tip

NEW & IMPROVED VERSION written in Python available at supabase-inactive-fix repo

Solution / How it works

  • Creating a cron job (scheduled task) that makes a simple database call
    • (This keeps your Supabase project active)
  • Fetching keep-alive.ts API endpoints for the other projects, as Vercel limits free-tier users to one cron job.

Getting Started

Super simple to add to your existing Supabase project!

Configure your main project

Only 3 files matter

utils/supabase folder contains files provided in the Supabase docs for the Next.js Web App demo — Supabase

Everything else is boilerplate from Next.js create-next-app

Configuring your other Supabase projects

After selecting your primary project (the one that implements the code provided in this repository), you'll want to add an API endpoint to your other Supabase projects

The only requirement is that this endpoint is reachable and makes a call to your Supabase database

Note

API endpoint must make database call
Ensure the server doesn't cache this

Example of a setup using Prisma as an ORM

/pages/api/keep-alive.ts

// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type { NextApiRequest, NextApiResponse } from 'next'
import { prisma } from 'src/server/db'

// See next example for contents of @/utils/helper
import { generateRandomString } from '@/utils/helper'

export default async function handler(
  _req: NextApiRequest,
  res: NextApiResponse
) {
  try {
    const randomString = generateRandomString()
    const dbResponse = await prisma.keepAlive.findMany({
      where: {
        name: {
          equals: randomString,
        }
      }
    })
    const successMessage = (dbResponse != null) ? `Success - found ${dbResponse.length} entries` : "Fail"
    res.status(200).json(successMessage)
  } catch (e) {
    res.status(401).send("There was an error")
  }
}

/prisma/schema.prisma

// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema

generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["postgresqlExtensions"]
}

datasource db {
  provider   = "postgresql"
  url        = env("DATABASE_URL")
  extensions = [uuidOssp(map: "uuid-ossp")]
}

model KeepAlive {
  id     BigInt  @id @default(autoincrement())
  name   String? @default("")
  random String? @default(dbgenerated("gen_random_uuid()")) @db.Uuid
}
Helper function for '/pages' directory (legacy support)

/utils/helper.ts

const defaultRandomStringLength: number = 12

const alphabetOffset: number = 'a'.charCodeAt(0)
export const generateRandomString = (length: number = defaultRandomStringLength) => {
  let newString = ''

  for (let i = 0; i < length; i++) {
    newString += String.fromCharCode(alphabetOffset + Math.floor(Math.random() * 26))
  }

  return newString
}

Sample SQL

Any table and column can be called, but if you'd rather go with a generic, here's a SQL query for a keep-alive table

CREATE TABLE "keep-alive" (
  id BIGINT generated BY DEFAULT AS IDENTITY,
  name text NULL DEFAULT '':: text,
  random uuid NULL DEFAULT gen_random_uuid (),
  CONSTRAINT "keep-alive_pkey" PRIMARY key (id)
);

INSERT INTO
  "keep-alive"(name)
VALUES
  ('placeholder'),
  ('example');

Important

It is now strongly recommended to use a keep-alive table like the one above.
This is in light of the added features for optional database insertion & deletion actions


Sample response

Visiting https://your-project-domain.vercel.app/api/keep-alive

Results for retrieving
'mzmgylpviofc' from 'keep-alive' at column 'name': []

Other Endpoint Results:
https://your-other-vercel-project-urls.vercel.app/api/keep-alive - Passed
https://your-other-supabase-app.com/api/keep-alive - Passed

Extended response (with insertion / deletion)
Results for retrieving entries from 'keep-alive' - 'name column: [{"name":"placeholder"},{"name":"random"}, ... ,{"name":"uujyzdnsbrgi"}]

Results for deleting
'uujyzdnsbrgi' from 'keep-alive' at column 'name': success

This is a Next.js project bootstrapped with create-next-app.