diff --git a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
index 5f957a2b7a7..906e4a5b0fe 100644
--- a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
@@ -1,4 +1,4 @@
-import { Heart, Server } from 'lucide-react'
+import { Clock, Heart, Server, SquareStack } from 'lucide-react'
import {
IconBranching,
@@ -93,6 +93,10 @@ function getMenuIcon(menuKey: string, width: number = 16, height: number = 16, c
return
case 'deployment':
return
+ case 'cron':
+ return
+ case 'queue':
+ return
default:
return
}
diff --git a/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx b/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
index c9dfa878980..353214ce46e 100644
--- a/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
@@ -1,4 +1,4 @@
-import { products } from 'shared-data'
+import { PRODUCT_MODULES, products } from 'shared-data'
type HomeMenuIcon = {
width?: number
@@ -450,7 +450,7 @@ export function IconMenuAI({ width = 16, height = 16, className }: HomeMenuIcon)
xmlns="http://www.w3.org/2000/svg"
>
{
return MenuId.Api
case pathname.startsWith('auth'):
return MenuId.Auth
- case pathname.startsWith('local-development'):
- return MenuId.LocalDevelopment
+ case pathname.startsWith('cron'):
+ return MenuId.Cron
case pathname.startsWith('database'):
return MenuId.Database
case pathname.startsWith('deployment'):
@@ -123,6 +123,8 @@ export const getMenuId = (pathname: string | null) => {
return MenuId.Graphql
case pathname.startsWith('integrations'):
return MenuId.Integrations
+ case pathname.startsWith('local-development'):
+ return MenuId.LocalDevelopment
case pathname.startsWith('monitoring-troubleshooting'):
return MenuId.MonitoringTroubleshooting
case pathname.startsWith('platform'):
diff --git a/apps/docs/content/guides/cron.mdx b/apps/docs/content/guides/cron.mdx
new file mode 100644
index 00000000000..84182b0dd14
--- /dev/null
+++ b/apps/docs/content/guides/cron.mdx
@@ -0,0 +1,34 @@
+---
+title: 'Cron'
+subtitle: 'Schedule Recurring Jobs with Cron Syntax in Postgres'
+---
+
+Supabase Cron is a Postgres Module that simplifies scheduling recurring Jobs with cron syntax and monitoring Job runs inside Postgres.
+
+Cron Jobs can be created via SQL or the Cron interface inside of Supabase Dashboard and can run anywhere from every second to once a year depending on your use case.
+
+Every Job can run SQL snippets or database functions with zero network latency or make an HTTP request, such as invoking a Supabase Edge Function, with ease.
+
+
+
+For best performance, we recommend no more than 8 Jobs run concurrently. Each Job should run no more than 10 minutes.
+
+
+
+## How does Cron work?
+
+Under the hood, Supabase Cron uses the [`pg_cron`](https://github.com/citusdata/pg_cron) Postgres database extension which is the scheduling and execution engine for your Jobs.
+
+
+
+`pg_cron` is not fully supported on Fly Postgres. Learn more about [Fly Postgres limitations](/docs/guides/platform/fly-postgres#limitations).
+
+
+
+The extension creates a `cron` schema in your database and all Jobs are stored on the `cron.job` table. Every Job's run and its status is recorded on the `cron.job_run_details` table.
+
+The Supabase Dashboard provides and interface for you to schedule Jobs and monitor Job runs. You can also do the same with SQL.
+
+## Resources
+
+- [`pg_cron` GitHub Repository](https://github.com/citusdata/pg_cron)
diff --git a/apps/docs/content/guides/cron/install.mdx b/apps/docs/content/guides/cron/install.mdx
new file mode 100644
index 00000000000..736b8870c28
--- /dev/null
+++ b/apps/docs/content/guides/cron/install.mdx
@@ -0,0 +1,44 @@
+---
+title: 'Install'
+---
+
+Install the Supabase Cron Postgres Module to begin scheduling recurring Jobs.
+
+
+
+
+1. Go to the [Cron Postgres Module](/dashboard/project/_/integrations/cron/overview) under Integrations in the Dashboard.
+2. Enable the `pg_cron` extension.
+
+
+
+
+```sql
+create extension pg_cron with schema pg_catalog;
+
+grant usage on schema cron to postgres;
+grant all privileges on all tables in schema cron to postgres;
+```
+
+
+
+
+## Uninstall
+
+Uninstall Supabase Cron by disabling the `pg_cron` extension:
+
+```sql
+drop extension if exists pg_cron;
+```
+
+
+
+Disabling the `pg_cron` extension will permanently delete all Jobs.
+
+
diff --git a/apps/docs/content/guides/cron/quickstart.mdx b/apps/docs/content/guides/cron/quickstart.mdx
new file mode 100644
index 00000000000..874644001a4
--- /dev/null
+++ b/apps/docs/content/guides/cron/quickstart.mdx
@@ -0,0 +1,337 @@
+---
+title: 'Quickstart'
+---
+
+
+
+Job names are case sensitive and cannot be edited once created.
+
+Attempting to create a second Job with the same name (and case) will overwrite the first Job.
+
+
+
+## Schedule a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section to schedule your first Job.
+2. Click on `Create job` button or navigate to the new Cron Job form [here](/dashboard/project/_/integrations/cron/jobs?dialog-shown=true).
+3. Name your Cron Job.
+4. Choose a schedule for your Job by inputting cron syntax (refer to the syntax chart in the form) or natural language.
+5. Input SQL snippet or select a Database function, HTTP request, or Supabase Edge Function.
+
+
+
+
+
+
+```sql
+-- Cron Job name cannot be edited
+select cron.schedule('permanent-cron-job-name', '30 seconds', 'CALL do_something()');
+```
+
+
+
+
+
+
+
+
+ ```
+ ┌───────────── min (0 - 59)
+ │ ┌────────────── hour (0 - 23)
+ │ │ ┌─────────────── day of month (1 - 31)
+ │ │ │ ┌──────────────── month (1 - 12)
+ │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
+ │ │ │ │ │ Saturday, or use names; 7 is also Sunday)
+ │ │ │ │ │
+ │ │ │ │ │
+ * * * * *
+ ```
+
+ You can use [1-59] seconds (e.g. `30 seconds`) as the cron syntax to schedule sub-minute Jobs.
+
+
+
+
+
+
+
+
+You can input seconds for your Job schedule interval as long as you're on Postgres version 15.1.1.61 or later.
+
+
+
+## Edit a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to edit.
+2. Click on the three vertical dots menu on the right side of the Job and click `Edit cron job`.
+3. Make your changes and then click `Save cron job`.
+
+
+
+
+
+
+```sql
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ schedule := '*/5 * * * *'
+);
+```
+
+Full options for the `cron.alter_job()` function are:
+
+```sql
+cron.alter_job(
+ job_id bigint,
+ schedule text default null,
+ command text default null,
+ database text default null,
+ username text default null,
+ active boolean default null
+)
+```
+
+It is also possible to modify a job by using the `cron.schedule()` function by inputting the same job name. This will replace the existing job via upsert.
+
+
+
+
+## Activate/Deactivate a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to unschedule.
+2. Toggle the `Active`/`Inactive` switch next to Job name.
+
+
+
+
+
+
+```sql
+-- Activate Job
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ active := true
+);
+
+-- Deactivate Job
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ active := false
+);
+```
+
+
+
+
+## Unschedule a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to delete.
+2. Click on the three vertical dots menu on the right side of the Job and click `Delete cron job`.
+3. Confirm deletion by entering the Job name.
+
+
+
+
+
+
+```sql
+select cron.unschedule('permanent-cron-job-name');
+```
+
+
+
+Unscheduling a Job will permanently delete the Job from `cron.job` table but its run history remain in `cron.job_run_details` table.
+
+
+
+
+
+
+## Inspecting Job Runs
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you want to see the runs of.
+2. Click on the `History` button next to the Job name.
+
+
+
+
+
+
+```sql
+select
+ *
+from cron.job_run_details
+where jobid = (select jobid from cron.job where jobname = 'permanent-cron-job-name')
+order by start_time desc
+limit 10;
+```
+
+
+
+The records in the `cron.job_run_details` table are not cleaned up automatically. They are also not removed when jobs are unscheduled, which will take up disk space in your database.
+
+
+
+
+
+
+## Examples
+
+### Delete data every week
+
+{/* */}
+
+Delete old data every Saturday at 3:30AM (GMT):
+
+{/* */}
+
+```sql
+select cron.schedule (
+ 'saturday-cleanup', -- name of the cron job
+ '30 3 * * 6', -- Saturday at 3:30AM (GMT)
+ $$ delete from events where event_time < now() - interval '1 week' $$
+);
+```
+
+### Run a vacuum every day
+
+{/* */}
+
+Vacuum every day at 3:00AM (GMT):
+
+{/* */}
+
+```sql
+select cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM');
+```
+
+### Call a database function every 5 minutes
+
+Create a [`hello_world()`](/docs/guides/database/functions?language=sql#simple-functions) database function and then call it every 5 minutes:
+
+```sql
+select cron.schedule('call-db-function', '*/5 * * * *', 'SELECT hello_world()');
+```
+
+### Call a database stored procedure
+
+To use a stored procedure, you can call it like this:
+
+```sql
+select cron.schedule('call-db-procedure', '*/5 * * * *', 'CALL my_procedure()');
+```
+
+### Invoke Supabase Edge Function every 30 seconds
+
+Make a POST request to a Supabase Edge Function every 30 seconds:
+
+```sql
+select
+ cron.schedule(
+ 'invoke-function-every-half-minute',
+ '30 seconds',
+ $$
+ select
+ net.http_post(
+ url:='https://project-ref.supabase.co/functions/v1/function-name',
+ headers:=jsonb_build_object('Content-Type','application/json', 'Authorization', 'Bearer ' || 'YOUR_ANON_KEY'),
+ body:=jsonb_build_object('time', now() ),
+ timeout_milliseconds:=5000
+ ) as request_id;
+ $$
+ );
+```
+
+
+
+This requires the [`pg_net` extension](/docs/guides/database/extensions/pg_net) to be enabled.
+
+
+
+## Caution: Scheduling System Maintenance
+
+Be extremely careful when setting up Jobs for system maintenance tasks as they can have unintended consequences.
+
+For instance, scheduling a command to terminate idle connections with `pg_terminate_backend(pid)` can disrupt critical background processes like nightly backups. Often, there is an existing Postgres setting, such as `idle_session_timeout`, that can perform these common maintenance tasks without the risk.
+
+Reach out to [Supabase Support](https://supabase.com/support) if you're unsure if that applies to your use case.
diff --git a/apps/docs/content/guides/database/extensions/pg_cron.mdx b/apps/docs/content/guides/database/extensions/pg_cron.mdx
index 6b934fbbe97..680a7680351 100644
--- a/apps/docs/content/guides/database/extensions/pg_cron.mdx
+++ b/apps/docs/content/guides/database/extensions/pg_cron.mdx
@@ -1,194 +1,7 @@
---
id: 'pg_cron'
-title: 'pg_cron: Job Scheduling'
-description: 'pgnet: a simple cron-based job scheduler for PostgreSQL that runs inside the database.'
+title: 'pg_cron: Schedule Recurring Jobs with Cron Syntax in Postgres'
+description: 'pg_cron: schedule recurring Jobs with cron syntax in Postgres.'
---
-The `pg_cron` extension is a simple cron-based job scheduler for PostgreSQL that runs inside the database.
-
-
-
-pg_cron is not fully supported on Fly Postgres. Read more about this [Fly Postgres limitation here](/docs/guides/platform/fly-postgres#limitations).
-
-
-
-## Usage
-
-### Enable the extension
-
-
-
-
-1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard.
-2. Click on **Extensions** in the sidebar.
-3. Search for "pg_cron" and enable the extension.
-
-
-
-
-```sql
--- Example: enable the "pg_cron" extension
-create extension pg_cron with schema pg_catalog;
-
-grant usage on schema cron to postgres;
-grant all privileges on all tables in schema cron to postgres;
-
--- Example: disable the "pg_cron" extension
-drop extension if exists pg_cron;
-```
-
-
-
-
-### Syntax
-
-The schedule uses the standard cron syntax, in which \* means "run every time period", and a specific number means "but only at this time":
-
-```bash
- ┌───────────── min (0 - 59)
- │ ┌────────────── hour (0 - 23)
- │ │ ┌─────────────── day of month (1 - 31)
- │ │ │ ┌──────────────── month (1 - 12)
- │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
- │ │ │ │ │ Saturday, or use names; 7 is also Sunday)
- │ │ │ │ │
- │ │ │ │ │
- * * * * *
-```
-
-You can use `[1-59] seconds` as the cron syntax to schedule sub-minute jobs. This is available on `pg_cron` v1.5.0+; upgrade your existing Supabase project to use this syntax.
-
-Head over to [crontab.guru](https://crontab.guru/) to validate your cron schedules.
-
-### Scheduling system maintenance
-
-Be extremely careful when setting up `pg_cron` jobs for system maintenance tasks as they can have unintended consequences. For instance, scheduling a command to terminate idle connections with `pg_terminate_backend(pid)` can disrupt critical background processes like nightly backups. Often, there is an existing Postgres setting e.g. `idle_session_timeout` that can perform these common maintenance tasks without the risk.
-
-Reach out to [Supabase Support](https://supabase.com/support) if you're unsure if that applies to your use case.
-
-## Examples
-
-### Delete data every week
-
-Delete old data every Saturday at 3:30am (GMT):
-
-```sql
-select cron.schedule (
- 'saturday-cleanup', -- name of the cron job
- '30 3 * * 6', -- Saturday at 3:30am (GMT)
- $$ delete from events where event_time < now() - interval '1 week' $$
-);
-```
-
-### Run a vacuum every day
-
-Vacuum every day at 3:00am (GMT):
-
-```sql
-select cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM');
-```
-
-### Call a database function every 5 minutes
-
-Create a [`hello_world()`](https://supabase.com/docs/guides/database/functions?language=sql#simple-functions) database function and then call it every 5 minutes:
-
-```sql
-select cron.schedule('call-db-function', '*/5 * * * *', 'SELECT hello_world()');
-```
-
-### Call a database stored procedure
-
-To use a stored procedure, you can call it like this:
-
-```sql
-select cron.schedule('call-db-procedure', '*/5 * * * *', 'CALL my_procedure()');
-```
-
-### Invoke Supabase Edge Function every 30 seconds
-
-
-
-This requires `pg_cron` v1.5.0+ and the [`pg_net` extension](/docs/guides/database/extensions/pgnet) to be enabled.
-
-
-
-Make a POST request to a Supabase Edge Function every 30 seconds:
-
-```sql
-select
- cron.schedule(
- 'invoke-function-every-half-minute',
- '30 seconds',
- $$
- select
- net.http_post(
- url:='https://project-ref.supabase.co/functions/v1/function-name',
- headers:=jsonb_build_object('Content-Type','application/json', 'Authorization', 'Bearer ' || 'YOUR_ANON_KEY'),
- body:=jsonb_build_object('time', now() ),
- timeout_milliseconds:=5000
- ) as request_id;
- $$
- );
-```
-
-### Edit a job
-
-Changes the frequency of a job called `'vacuum'` to once every 5 minutes.
-
-```sql
-select cron.alter_job(
- job_id := (select jobid from cron.job where jobname = 'vacuum'),
- schedule := '*/5 * * * *'
-);
-```
-
-Full options for the `cron.alter_job()` function are:
-
-```sql
-cron.alter_job(
- job_id bigint,
- schedule text default null,
- command text default null,
- database text default null,
- username text default null,
- active boolean default null
-)
-```
-
-It is also possible to modify a job by using the `cron.schedule()` function, with the same job name. This will replace the existing job, in the manner of an upsert.
-
-### Unschedule a job
-
-Unschedules a job called `'nightly-vacuum'`
-
-```sql
-select cron.unschedule('nightly-vacuum');
-```
-
-### Viewing previously ran jobs
-
-View the last ten jobs that have ran
-
-```sql
-select
- *
-from cron.job_run_details
-order by start_time desc
-limit 10;
-```
-
-
-
-The records in cron.job_run_details are not cleaned automatically which will take up disk space in your database.
-
-
-
-## Resources
-
-- [`pg_cron` GitHub Repository](https://github.com/citusdata/pg_cron)
+See the [Supabase Cron docs](/docs/guides/cron).
diff --git a/apps/docs/content/guides/functions/schedule-functions.mdx b/apps/docs/content/guides/functions/schedule-functions.mdx
index 1dd5fb88ed2..f0d64f319c6 100644
--- a/apps/docs/content/guides/functions/schedule-functions.mdx
+++ b/apps/docs/content/guides/functions/schedule-functions.mdx
@@ -13,7 +13,7 @@ description: 'Schedule Edge Functions with pg_cron.'
>
-The hosted Supabase Platform supports the [`pg_cron` extension](/docs/guides/database/extensions/pgcron), a simple cron-based job scheduler for PostgreSQL that runs inside the database.
+The hosted Supabase Platform supports the [`pg_cron` extension](/docs/guides/database/extensions/pgcron), a recurring job scheduler in Postgres.
In combination with the [`pg_net` extension](/docs/guides/database/extensions/pgnet), this allows us to invoke Edge Functions periodically on a set schedule.
diff --git a/apps/docs/features/docs/GuidesMdx.utils.tsx b/apps/docs/features/docs/GuidesMdx.utils.tsx
index d21e7fe6e9e..aaef7455e70 100644
--- a/apps/docs/features/docs/GuidesMdx.utils.tsx
+++ b/apps/docs/features/docs/GuidesMdx.utils.tsx
@@ -1,7 +1,6 @@
import matter from 'gray-matter'
import { fromMarkdown } from 'mdast-util-from-markdown'
-import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm'
-import { toMarkdown } from 'mdast-util-to-markdown'
+import { gfmFromMarkdown } from 'mdast-util-gfm'
import { gfm } from 'micromark-extension-gfm'
import { type Metadata, type ResolvingMetadata } from 'next'
import { notFound } from 'next/navigation'
@@ -26,6 +25,7 @@ const PUBLISHED_SECTIONS = [
'ai',
'api',
'auth',
+ 'cron',
'database',
'deployment',
'functions',
diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx
index 9e116e883c9..dbee0c2a538 100644
--- a/apps/docs/layouts/MainSkeleton.tsx
+++ b/apps/docs/layouts/MainSkeleton.tsx
@@ -30,6 +30,10 @@ const levelsData = {
icon: 'database',
name: 'Database',
},
+ cron: {
+ icon: 'cron',
+ name: 'Cron',
+ },
api: {
icon: 'rest',
name: 'REST API',
diff --git a/apps/docs/public/img/guides/database/cron/cron-create.png b/apps/docs/public/img/guides/database/cron/cron-create.png
new file mode 100644
index 00000000000..0751b5c6186
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-create.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-edit.png b/apps/docs/public/img/guides/database/cron/cron-edit.png
new file mode 100644
index 00000000000..632d4692a0e
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-edit.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-history.png b/apps/docs/public/img/guides/database/cron/cron-history.png
new file mode 100644
index 00000000000..d65ef1f9a78
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-history.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-toggle.png b/apps/docs/public/img/guides/database/cron/cron-toggle.png
new file mode 100644
index 00000000000..54a7c4a4936
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-toggle.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-unschedule.png b/apps/docs/public/img/guides/database/cron/cron-unschedule.png
new file mode 100644
index 00000000000..10c6bb7275b
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-unschedule.png differ
diff --git a/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx b/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx
index f8c4a3afa48..752ee4eea1a 100644
--- a/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx
+++ b/apps/studio/components/interfaces/Integrations/Landing/Integrations.constants.tsx
@@ -117,7 +117,7 @@ const supabaseIntegrations: IntegrationDefinition[] = [
icon: ({ className, ...props } = {}) => (
),
- description: 'Schedule and automate tasks to run maintenance routines at specified intervals.',
+ description: 'Schedule recurring Jobs in Postgres.',
docsUrl: 'https://github.com/citusdata/pg_cron',
author: {
name: 'Citus Data',
diff --git a/apps/studio/static-data/integrations/cron/overview.md b/apps/studio/static-data/integrations/cron/overview.md
index dfb3bbbf833..b5a0283f737 100644
--- a/apps/studio/static-data/integrations/cron/overview.md
+++ b/apps/studio/static-data/integrations/cron/overview.md
@@ -1 +1 @@
-Supabase Cron uses the `pg_cron` Postgres extension, which is a simple cron-based job scheduler for Postgres that runs inside the database. It uses the same syntax as a regular cron, but it allows you to schedule Postgres SQL commands directly from the database.
+Supabase Cron uses the `pg_cron` Postgres extension, which is a recurring job scheduler in Postgres. It uses the same syntax as a regular cron, but it allows you to schedule Postgres SQL commands directly from the database.
diff --git a/apps/www/_blog/2024-12-04-cli-v2-config-as-code.mdx b/apps/www/_blog/2024-12-04-cli-v2-config-as-code.mdx
index a8cd8e66608..e8ca356e3ea 100644
--- a/apps/www/_blog/2024-12-04-cli-v2-config-as-code.mdx
+++ b/apps/www/_blog/2024-12-04-cli-v2-config-as-code.mdx
@@ -8,7 +8,7 @@ categories:
- product
tags:
- launch-week
-date: '2024-12-04'
+date: '2024-12-04T00:00:00'
toc_depth: 3
launchweek: '13'
---
diff --git a/apps/www/_blog/2024-12-04-supabase-cron.mdx b/apps/www/_blog/2024-12-04-supabase-cron.mdx
new file mode 100644
index 00000000000..9566886fa96
--- /dev/null
+++ b/apps/www/_blog/2024-12-04-supabase-cron.mdx
@@ -0,0 +1,142 @@
+---
+title: 'Supabase Cron'
+description: Schedule Recurring Jobs in Postgres
+author: ivasilov,oli_rice,saltcod
+image: launch-week-13/day-3-supabase-cron/og.jpg
+thumb: launch-week-13/day-3-supabase-cron/thumb.jpg
+categories:
+ - developers
+ - postgres
+tags:
+ - cron
+ - postgres
+date: '2024-12-04T00:00:01'
+toc_depth: 3
+launchweek: '13'
+---
+
+Today we're releasing [Supabase Cron](/modules/cron), a new Postgres Module that makes recurring Jobs simple and intuitive inside your database.
+
+It's designed to work seamlessly with the entire Supabase platform. Create recurring Jobs to run SQL snippets and call database functions, Supabase Edge Functions, and even remote webhooks.
+
+
+
+
+
+
+
+Supabase Cron is built on the powerful [`pg_cron`](https://github.com/citusdata/pg_cron) extension by the team at [Citus Data](https://github.com/citusdata).
+
+It's a Supabase policy to [support existing tools](https://supabase.com/docs/guides/getting-started/architecture#support-existing-tools) wherever possible, and the Citus Data team have generously licensed their extension with the OSI-compatible [PostgreSQL license](https://github.com/citusdata/pg_cron?tab=PostgreSQL-1-ov-file).
+
+We're very thankful to all the contributors and we look forward to continue working with the community.
+
+
+
+### What's a Cron?
+
+[**Cron**](https://en.wikipedia.org/wiki/Cron) is a tool for scheduling recurring tasks that run at specified intervals. These periodic tasks are called “Cron Jobs”. Common use-cases include:
+
+- **Maintenance:** delete or archive old data.
+- **Reporting and analytics:** save daily or weekly reports for analysis.
+- **Automation:** send periodic emails, like newsletters or reminders.
+- **Monitoring**: perform health checks on your database and log the results.
+- **Performance:** automate vacuuming tables and rebuilding indexes.
+
+Supabase Cron stores the scheduling logic within Postgres and runs your Jobs accordingly while integrating with the rest of the Supabase primitives - Dashboard, Edge Functions, and AI Assistant.
+
+## How Do You Use Supabase Cron?
+
+You can create Jobs either via the Dashboard or SQL.
+
+
+
+For this post we'll focus on the Dashboard. You can refer to the [documentation](https://supabase.com/docs/guides/cron/quickstart) for SQL.
+
+
+
+Within the Dashboard you can define schedules using standard cron syntax and the special `pg_cron` seconds syntax for sub-minute schedules or use natural language.
+
+
+
+## Job Types
+
+You can choose between four types of Jobs based on what you need to execute:
+
+
+
+### SQL Snippets
+
+Create an inline SQL query or command to run on your database periodically. Use this for tasks like:
+
+- Generating reports.
+- Cleaning up stale data.
+- Refreshing [Materialized Views](https://supabase.com/docs/guides/database/tables?queryGroups=database-method&database-method=sql#materialized-views).
+
+### Database Functions
+
+Call a Postgres function. This is useful for workflows, such as:
+
+- Batch processing operations.
+- Running periodic maintenance tasks.
+- Performing multi-step updates using transactions.
+
+### HTTP Requests (webhooks)
+
+Trigger an external HTTP endpoint. Use this for:
+
+- Starting external workflows.
+- Syncing data with third-party APIs.
+- Sending notifications to external systems.
+
+### Supabase Edge Functions
+
+Run a serverless function to execute custom logic. Examples include:
+
+- Creating embeddings.
+- Sending automated email updates.
+- Fetching external data and storing it in your database.
+
+These options cover a wide range of use cases, helping with everything from database management to external integrations.
+
+### Observe and Debug Jobs
+
+Wondering why a Job failed? You can view the history of all Jobs and their logs in the Dashboard. You can see when a Job started, how long it took, and what the result was.
+
+
+
+
+For a deeper dive, you can view Jobs in the [Logs Explorer](https://supabase.com/dashboard/project/_zvmkyvanngopzqaabmvx_/logs/pgcron-logs).
+
+
+### Try Supabase Cron today
+
+Getting started is easy:
+
+1. Visit the [Integrations page](https://supabase.com/dashboard/project/_/integrations) in your project.
+2. Enable the **Cron** Postgres Module.
+3. Create your first scheduled Job.
+
+
+
+
+
+We're looking forward to seeing how you use Supabase Cron to help automate your workflows!
diff --git a/apps/www/components/BrowserFrame.tsx b/apps/www/components/BrowserFrame.tsx
index 39cca627f22..5b944026a4d 100644
--- a/apps/www/components/BrowserFrame.tsx
+++ b/apps/www/components/BrowserFrame.tsx
@@ -4,21 +4,29 @@ import { cn } from 'ui'
interface Props extends PropsWithChildren {
className?: string
contentClassName?: string
+ hasFrameButtons?: boolean
}
-const BrowserFrame: React.FC = ({ children, className, contentClassName }) => {
+const BrowserFrame: React.FC = ({
+ children,
+ className,
+ contentClassName,
+ hasFrameButtons = true,
+}) => {
return (