Docs

Cron jobs

Run a function, call an HTTPS endpoint or run SQL on a schedule, in your own time zone, with retries, overlap control and a run history.

Updated Oct 26, 2026

A cron job runs something on a schedule: a deployed function, an HTTPS request to any public URL, or one SQL statement on your database. Each run is a durable background job with retries, a timeout and a history (succeeded, failed, skipped, missed), so a job never runs twice for the same time even when several servers see it due.

Scheduleexpression + timezoneDue slot claimedexactly onceBackground jobtries, timeout,overlap ruleFunctioncontext.scheduleHTTPS requestvia the egressproxySQL statementservice-role key

#Schedule expressions

Five fields — minute hour day-of-month month day-of-week — or a macro. The console and sov functions schedules preview show the next runs before you save.

ExpressionRuns
*/5 * * * *Every 5 minutes
@hourly (0 * * * *)At the start of every hour
0 9 * * MON-FRIAt 09:00 on weekdays
30 2 1 * *At 02:30 on the 1st of every month
0 9 1 * MONAt 09:00 on the 1st and on every Monday (day of month and day of week together mean either)
@daily, @weekly, @monthly, @yearlyMidnight every day, Sunday, 1st, 1 January
  • Lists 1,15, ranges 1-5, steps */10, 10-50/20 and 5/15 (from 5, every 15); names JAN–DEC and SUN–SAT; 7 is Sunday too.
  • Dates that never happen (0 0 30 2 *) are refused when you save; rare ones (0 0 29 2 *) are fine.
  • Time zones: pick any IANA zone (Asia/Kolkata, Europe/London, America/New_York); the default is UTC. Daylight saving is handled: a time skipped when clocks go forward runs once just after the change (02:30 runs at 03:30), a time that happens twice runs once — except expressions with * in the hour field, which keep their interval through the repeated hour.

#Create a cron job

sov functions schedules preview '0 9 * * MON-FRI' --tz Asia/Kolkata
sov functions schedules create '0 3 * * *' -f cleanup --tz Asia/Kolkata --overlap skip --name "Nightly cleanup"
sov functions schedules create @hourly --url https://hooks.example.com/ping -H 'Authorization: @secret:HOOK_TOKEN'
sov functions schedules create '*/15 * * * *' --sql 'SELECT refresh_leaderboard()' --timeout 20
sov functions schedules run <schedule-id>        # run it now
sov functions schedules runs <schedule-id>       # history

#Targets

TargetSettingsHow it runs
Functionfunction_name, payload (the event)Like a background call. context.caller.role is "schedule"; context.schedule has id, name, scheduled_at, manual, attempt; context.idempotency_key is sched:<id>:<slot>.
HTTPSurl, method, headers, body, timeout_secLeaves through the egress proxy: public host names only (private, loopback and metadata addresses are refused). A non-2xx answer is a failed try; the status and the first 2 KB of the answer are kept.
SQLsql, params, key_secretOne SELECT / INSERT / UPDATE / DELETE (call a database function with SELECT my_job()) through your project's SQL API with the service-role key stored as the secret key_secret (default SOVARIA_SERVICE_ROLE_KEY). It runs as your project's database role — never a superuser — with statement_timeout set to the job's timeout.

#Retries, timeouts and overlap

  • Tries per run (max_attempts, default 3, up to your plan's tries per event): a failed try is retried with backoff; the last failure is kept under Dead letters.
  • Timeout (timeout_sec): lowers the run's limit below the function's or plan's; for SQL it is the statement timeout.
  • Overlap — allow (default) runs every slot; skip skips a slot while the previous run is still going and logs it as Skipped.
  • Run now queues one run immediately without changing the regular times (it follows the overlap rule).
  • Slots missed while the scheduler was down are logged once as Missed, and the latest one runs late — they are not replayed one by one.

#Secrets

Never put a key in a payload, header or body: write {"$secret": "NAME"} instead. The value is filled in when the job runs (from the function's secrets for functions, the project and environment secrets for HTTPS and SQL), and logs show only the name. Plain values under names like password, token or api_key are shown as [redacted]; sending [redacted] back on an edit keeps what is stored. Payloads are at most 256 KB.

#Environments and the kill switch

A schedule belongs to the environment it was made in and runs that environment's function; staging never lists or changes production's schedules. Deleting a function removes its schedules in that environment only. If Sovaria support switches background runs off for an organization (abuse, a runaway loop), its slots are skipped and logged until they are switched back on.

#Compared with Supabase Cron

SovariaSupabase Cron (pg_cron + pg_net)
TargetsFunction, HTTPS, SQLSQL, database function, HTTP, Edge Function
Time zonesAny IANA zone, DST-awareUTC only
Retries and timeoutsPer job, with dead lettersNone built in
Overlap controlskip per jobNone
Run now, preview, readable summaryYesNo
HistoryStatus incl. skipped and missed, duration, tries, response preview, logsStatus and output
Secrets$secret references, redacted in logsVault lookups in SQL

#Plans

FreeProUltraTeamEnterprise
Cron jobs per project (fn.cron_jobs)2251005002,000
Tries per run (fn.trigger_max_attempts)38101215

Each run counts as one invocation (fn.invocations_month) and, for functions, its compute. Run history is kept as long as your plan keeps function logs (fn.log_retention_hours). See Plan limits.

#Coming from Firebase or Supabase?

PlatformWhat this is called there
FirebaseScheduled functions (onSchedule) and Cloud Scheduler
SupabaseSupabase Cron (pg_cron, pg_net)
SovariaCron jobs

Moving an existing app? Migrate from Supabase or Firebase imports users (with their passwords), data, files and rules.