Cron Jobs — Reference
The Cron Jobs surface is the platform's scheduled-task plane. It owns every recurring job that SGEN runs against itself — retention sweeps, backup snapshots, cache warm-ups, search index rebuilds, queued email dispatch, analytics rollups, and any operator-defined task on a recurring schedule. Anything that runs without an operator clicking a button traces back to a record managed here.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or scoping a scheduled workflow. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Cron Jobs live under the Tools module in SG-Admin. The module renders three primary views — the job list, the job create / edit form, and the run-history drawer — and exposes a small set of write operations for create, edit, enable / disable, manual trigger, and delete.
The module is paired by convention: one half renders the views and prepares the data, the other half handles writes and returns AJAX responses. Engineers reading the source will see this split across two controller files; the reference below describes the combined surface as it appears to a calling integration.
A second surface — system jobs — lives alongside operator-defined jobs in the same list, distinguished by a source = system marker. System jobs are platform-owned (retention, backup, cache warm-up) and cannot be deleted from the operator UI, only enabled / disabled. They are described on this page because they share the same render, schema, and trigger path as operator jobs.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Tools → Cron Jobs
- URL prefix:
/sg-admin/cron-jobs/ - View templates:
application/views/Admin/CronJobs/
┌──────────────────────────────────────────────────────────────────────────┐│ SG-Admin → Tools → Cron Jobs [+ New job] │├──────────────────────────────────────────────────────────────────────────┤│ Name Schedule Last run Next run Status ││ ────────────────── ───────────── ───────────── ────────── ─────────││ Backup snapshot daily 02:00 14 hr ago ✔ in 10 hr active ││ Activity retention weekly Sun 2 days ago ✔ in 5 days active ││ Cache warm-up hourly 42 min ago ✔ in 18 min active ││ Search reindex daily 04:00 yesterday ✔ in 8 hr active ││ Email queue flush every 5 min 3 min ago ✘ in 2 min active ││ Vendor sync daily 06:00 never in 12 hr disabled ││ ││ [⋯ Edit] [⋯ Run now] [⋯ History] [⋯ Enable/Disable] │└──────────────────────────────────────────────────────────────────────────┘Actions
The Cron Jobs surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List and filter
Returns the scheduled jobs visible to the current operator, paginated, with name / schedule / last-run / next-run / status columns. Supports column sort, free-text filter across name, and source filter (operator / system / all). The last-run column shows a success or failure marker alongside the timestamp; the next-run column computes from the schedule expression.
Create job
Opens an empty create form. Required fields: name, schedule expression, task target (a registered task slug from the task catalog), enabled flag. Optional fields cover description, max-runtime ceiling, retry policy (none / once / exponential), notification target on failure, and per-environment scope. On submit, the surface validates the schedule expression, validates the task slug against the catalog, persists the record, and computes the first next_run_at.
Edit job
Loads an existing record into the same form shape used for create, pre-populated. Submit replaces the stored definition with the posted values. Editing the schedule expression recomputes next_run_at from the current time forward. Editing the task target does not retroactively rewrite history — past runs remain attributed to the prior target.
Enable and disable
A focused write path. Toggles the enabled flag on the record. A disabled job does not execute on its schedule and does not advance next_run_at. Re-enabling recomputes next_run_at from the current time forward — the surface does not back-fire missed runs.
Run now
A manual trigger. Executes the job immediately, outside the schedule, and records the run in history with trigger = manual. The job's regular schedule continues unchanged; next_run_at is not affected. Used during debugging or when an operator needs an immediate retention sweep / cache warm / backup. System jobs accept manual triggers the same as operator jobs.
View run history
Opens a drawer showing the trailing N runs (configurable, default 50). Each row carries start time, duration, result (success / failure / timeout), output excerpt, and the trigger that fired it (schedule / manual / retry). Failures expand to the full error payload. Used during incident review when the question is "did this job run, and what did it do?"
Delete job
Hard-removes an operator-defined record. Run history is preserved under the historical name (the row remains queryable via the history view even after the parent record is gone). System jobs cannot be deleted — the delete action returns a structured rejection on system rows.
Engineering note — deleting a job does not stop a run already in flight. The in-flight run completes, records its result, and the parent record is then absent. Integrations that need to halt a running job should disable it first, wait for the in-flight run to drain, then delete.
Data model
A cron job record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
name | string | Operator-set display name. Not unique. |
schedule | string | Schedule expression. Standard 5-field cron or platform-specific shorthand (hourly, daily 02:00, weekly Sun). |
task_slug | string | Registered task identifier. Validated against the task catalog. |
source | enum | operator (operator-defined) or system (platform-owned). |
enabled | boolean | When false, the scheduler skips this row. |
max_runtime | integer | Seconds. Run exceeds this → killed and recorded as timeout. |
retry_policy | enum | none, once, exponential. |
notify_on_failure | string | Operator identifier or email. Optional. |
environment | enum | production, staging, sandbox, all. |
last_run_at | timestamp | Set on every run completion. |
last_run_result | enum | success, failure, timeout, skipped. |
next_run_at | timestamp | Computed forward from schedule. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit. |
/5 *) and platform shorthand (every 5 min, daily 02:00, weekly Sun 04:00). The surface normalizes both into the same internal representation; reads return the format the operator wrote.Task catalog. The task_slug references a registered task — the unit of work the scheduler invokes. Tasks are registered by the platform itself (system tasks) and by integrations. The list of registered tasks is queryable from the create form's dropdown.
Run history. Each completed run writes a separate history row keyed by (job_id, run_id). History rows survive deletion of the parent job — useful for forensic review of jobs that have since been removed.
CRON JOB RECORD├── id integer primary key├── name string operator-set├── schedule string cron or shorthand├── task_slug string registered catalog entry├── source enum operator | system├── enabled boolean scheduler skip flag├── max_runtime integer seconds before timeout├── retry_policy enum none | once | exponential├── notify_on_failure string operator id or email├── environment enum production | staging | sandbox | all├── last_run_at timestamp run completion time├── last_run_result enum success | failure | timeout | skipped├── next_run_at timestamp computed from schedule└── timestamps created_at, updated_at↓ each execution writesRUN HISTORY ROW├── run_id unique per execution├── started_at, completed_at, duration├── result success | failure | timeout├── trigger schedule | manual | retry└── output captured stdout/stderr excerptPermissions
Access to the Cron Jobs surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Cron Jobs surface.
Layer 2 — per-action capability. Within SG-Admin, each Cron Jobs action checks a capability associated with the calling operator's role. The default role configuration ships with three roles — Administrator, Editor, Viewer — and the capability map is:
| Capability | Administrator | Editor | Viewer |
|---|---|---|---|
| List jobs | ✔ | ✔ | ✔ |
| View run history | ✔ | ✔ | ✔ |
| Create job | ✔ | — | — |
| Edit job | ✔ | — | — |
| Enable / disable (operator job) | ✔ | — | — |
| Enable / disable (system job) | ✔ | — | — |
| Run now (operator job) | ✔ | ✔ | — |
| Run now (system job) | ✔ | — | — |
| Delete (operator job) | ✔ | — | — |
Self-protection rules. An operator cannot delete a system job. The surface returns a structured rejection naming the system-job protection. An operator cannot schedule a job whose task_slug is not in the registered catalog — the create / edit form rejects the unknown slug at submit.
Audit. Every write — create, edit, enable, disable, manual trigger, delete — emits an Activity Log entry. Each completed run also emits an entry with source = cron, recording the job name, result, and duration. The audit trail therefore covers both the management actions and the executions themselves.
TIME SOURCE OPERATOR ACTION│ │▼ ▼┌──────────────┐ ┌──────────────────┐│ scheduler │ │ "Run now" button ││ next_run_at │ │ (manual trigger) ││ matches now │ └────────┬─────────┘└──────┬───────┘ ││ │└──────────┬───────────────┘▼┌────────────────────┐│ enabled = true ? │ no → skip + record└─────────┬──────────┘│ yes▼┌────────────────────┐│ task executes │ bounded by max_runtime└─────────┬──────────┘│▼┌────────────────────┐│ result captured │ success | failure | timeout└─────────┬──────────┘│▼run-history row written│▼Activity Log entry (source = cron)│▼on failure → notify_on_failure target│▼next_run_at advanced (schedule, not manual)Related references
- Settings — Reference. Owns the default retry policy, the default max-runtime ceiling, the registered task catalog editor, and the per-environment scheduler enable flag. Changes there reshape what Cron Jobs can run.
- Activity Log — Reference. Source of management-action and execution audit trails. Every job write and every run completion emits an entry there.
- Cache — Reference. Cache warm-up sweep and cache eviction sweep are system cron jobs. Their schedules are editable here; their task logic lives in the Cache module.
- Backups — Reference. Daily backup snapshot is a system cron job. Disabling it stops automatic snapshots — restores remain available from any prior snapshot.
- Notifications — Reference. The
notify_on_failuretarget resolves to a notification preference there. Failure notification format follows the notification template surface. - Exports — Reference. Async export jobs reuse the cron infrastructure for scheduled / recurring exports. Each scheduled export is a Cron Jobs row whose task target is an exports task slug.
- Automations — Reference. Automation triggers that fire on a schedule are implemented as Cron Jobs rows. Edit them here; edit the automation logic there.
/docs/cron-jobs.