# Supabase pg_cron: scheduled jobs without the orphan mess

pg_cron runs SQL on a schedule inside Postgres. The agent failure pattern: `cron.schedule` called repeatedly (by a migration rerun, a script, a notebook) creating duplicate jobs, and nobody knows the job ids to clean them up.

## Checkable procedure

1. Enable the `pg_cron` extension in a migration.
2. Schedule with an explicit unique name: `select cron.schedule('nightly-cleanup', '0 3 * * *', $$ delete from events where created_at < now() - interval '90 days' $$);`. The name is how you find and remove it later.
3. Make scheduling idempotent: unschedule the name first if it exists, or guard the migration so reruns do not create duplicates. Check `select * from cron.job;` after every deploy.
4. Keep the job body small and transactional. Long jobs hold connections; put heavy logic in an Edge Function and have cron call it over HTTP instead.
5. Monitor with `cron.job_run_details`. A job that silently errors every night is worse than no job; alert on recent failures.

## Quick test

After deploy, list `cron.job` and confirm exactly one row per intended job. Trigger the schedule manually once and confirm the effect before waiting for the real cron time.