CronTrigger is the standard Salesforce object that represents a scheduled job. Every time you call System.schedule(...), a CronTrigger record is created. It stores the schedule’s cron expression, when it last fired, when it’ll fire next, how many times it’s run, and a link to the user who created it.
Useful fields
SELECT Id, CronExpression, TimesTriggered,
NextFireTime, PreviousFireTime, EndTime,
StartTime, State,
CronJobDetail.Name, CronJobDetail.JobType,
CreatedBy.Name, CreatedDate
FROM CronTrigger
| Field | Meaning |
|---|---|
CronExpression | The 6 or 7-token cron string (e.g., 0 0 2 * * ?) |
TimesTriggered | How many times this schedule has fired |
NextFireTime | When it will fire next (null if no future fires) |
PreviousFireTime | When it last fired |
StartTime, EndTime | Bounds of the schedule’s validity |
State | WAITING, ACQUIRED, EXECUTING, PAUSED, BLOCKED, etc. |
CronJobDetail.Name | The friendly name you passed to System.schedule |
CronJobDetail.JobType | 7 for Apex Scheduled, 9 for Anonymous Apex, etc. |
Common queries
How many scheduled jobs are there?
SELECT COUNT() FROM CronTrigger
What’s scheduled today?
SELECT CronJobDetail.Name, NextFireTime, PreviousFireTime, CronExpression
FROM CronTrigger
WHERE NextFireTime >= TODAY AND NextFireTime < TOMORROW
ORDER BY NextFireTime
Which scheduled jobs have failed recently?
-- CronTrigger doesn't track failures directly — check AsyncApexJob
SELECT Id, ApexClass.Name, Status, ExtendedStatus, CompletedDate
FROM AsyncApexJob
WHERE JobType = 'ScheduledApex' AND Status = 'Failed' AND CreatedDate = LAST_N_DAYS:7
CronTrigger vs CronJobDetail
These are two related objects:
| Object | Purpose |
|---|---|
CronTrigger | One row per scheduled instance — the schedule itself |
CronJobDetail | The “type” record — typically one for each unique scheduled job name |
The relationship: CronTrigger.CronJobDetailId → CronJobDetail.Id. The Name on CronJobDetail is the friendly name you passed to System.schedule. Most queries use them together.
The Setup UI
Setup → Scheduled Jobs shows all CronTrigger records as a list. Each row links to:
- The Apex class scheduled
- The cron expression
- Next fire time
- A Manage link to view, Del link to delete (which aborts the schedule)
Programmatic operations on CronTrigger
// Get the trigger Id from inside a Schedulable
Id triggerId = ctx.getTriggerId();
// Abort a scheduled job
System.abortJob(triggerId);
// Count scheduled jobs
Integer count = [SELECT COUNT() FROM CronTrigger];
// Find scheduled jobs for a specific Apex class — this is more complex,
// CronTrigger doesn't directly link to the class. You query AsyncApexJob:
SELECT ApexClassId, ApexClass.Name FROM AsyncApexJob
WHERE JobType = 'ScheduledApex' AND Status IN ('Queued', 'Processing')
Limits to know
| Limit | Value |
|---|---|
Scheduled jobs in an org (CronTrigger rows) | 100 |
| Apex Flex Queue (separate) | 100 (batch jobs only) |
CronTrigger is one of the few standard objects with a fixed row limit at the org level.
Common interview follow-ups
- Can I create
CronTriggerrecords directly? — No, they’re system-managed. UseSystem.schedule. - Can I update a
CronTrigger? — No. Abort and reschedule. - Does
CronTriggersurvive sandbox refresh? — No — schedules don’t transfer. You re-schedule after refresh.
Verified against: Object Reference — CronTrigger. Last reviewed 2026-05-17.