CRON_EXP is the cron expression — a space-separated string of time fields that tells the Apex scheduler when to run a job. It’s the second argument to System.schedule(jobName, cronExpression, instance).
The format
Salesforce uses a 6-field (or optionally 7-field) cron expression:
Seconds Minutes Hours Day-of-Month Month Day-of-Week [Year]
| Field | Allowed values | Special characters |
|---|---|---|
| Seconds | 0–59 | , - * / |
| Minutes | 0–59 | , - * / |
| Hours | 0–23 | , - * / |
| Day-of-Month | 1–31 | , - * ? / L W |
| Month | 1–12 or JAN–DEC | , - * / |
| Day-of-Week | 1–7 or SUN–SAT | , - * ? / L # |
| Year (optional) | 1970–2099 | , - * / |
The optional Year field gives you precise one-shot scheduling.
A handful of expressions
| Expression | Fires |
|---|---|
0 0 2 * * ? | 2:00 AM every day |
0 0 * * * ? | Top of every hour |
0 */15 * * * ? | Every 15 minutes |
0 0 8 ? * MON | Mondays at 8:00 AM |
0 0 0 1 * ? | Midnight on the 1st of every month |
0 0 12 ? * MON-FRI | Noon, weekdays only |
0 0 6 ? * 2#1 | 6 AM on the first Monday of each month |
0 30 14 ? * SAT,SUN | 2:30 PM, weekends only |
0 0 0 ? * 1L | Midnight on the last Sunday of each month |
The ? requirement
You must put ? in either Day-of-Month or Day-of-Week — never both, never neither. Reason: those two fields can conflict, so Salesforce makes you pick which one matters.
0 0 2 * * ?— “every day” (day-of-month = any, day-of-week = ignored)0 0 2 ? * MON— “Mondays” (day-of-month = ignored, day-of-week = Monday)
Resolution
The Apex scheduler resolves to the minute in practice. The Seconds field is accepted (and usually written as 0), but Salesforce doesn’t promise sub-minute precision — your job fires “at or after” the configured time, typically within a minute.
Where to put it
In Apex code:
System.schedule('Nightly Cleanup', '0 0 2 * * ?', new NightlyCleanupSchedulable());
In the Setup UI, you don’t type cron directly — you pick frequency, day, and time, and Salesforce generates the expression for you.
Quoting and timezones
- No quoting needed — pass the cron as a regular
String. - Timezone — Salesforce evaluates the expression in the timezone of the user who scheduled the job. If admin A in IST schedules
'0 0 2 * * ?'(2 AM IST), users in other timezones see it run at the equivalent local time.
What’s not standard cron
- No
@reboot,@daily, etc. macros — Salesforce only accepts the field form. - No “Last day of the month” without
L— useLin day-of-month. - No “every Nth weekday” —
#does similar (MON#2= second Monday).
Common interview follow-ups
- Is the seconds field required? — Yes, even though it’s almost always
0. - What’s the smallest interval? — Salesforce won’t fire more often than once a minute in practice — but you can construct cron that implies sub-minute firing.
- How do I run every 5 minutes? —
0 */5 * * * ?. The/step operator combined with*(any).
Verified against: Apex Developer Guide — Scheduled Apex (Cron Expressions). Last reviewed 2026-05-17.