Cron Expressions for Salesforce Apex Scheduler
Table of Contents
Salesforce Apex uses a 7-field cron format in System.schedule() that is similar to Quartz — it adds seconds as the first field, supports an optional year as the last field, and uses 1-based day-of-week numbering where Sunday = 1. Use our free cron generator to build the 5-field base, then adapt it to Salesforce format using the patterns below.
Salesforce also imposes hard limits: no more than 100 scheduled Apex jobs per org, and the minimum scheduling interval is 1 hour for most use cases.
Salesforce Apex Cron Format — 7 Fields
+------------- Seconds (0-59)
| +----------- Minutes (0-59)
| | +--------- Hours (0-23)
| | | +------- Day of month (1-31, ?, L, W, LW)
| | | | +----- Month (1-12 or JAN-DEC)
| | | | | +--- Day of week (1-7, SUN=1, MON=2...SAT=7, or SUN-SAT, ?, L, #)
| | | | | | +-- Year (optional, 1970-2099)
| | | | | | |
0 0 9 ? * 2 *
Used in Apex code as:
String cronExpr = '0 0 9 ? * 2 *'; // Every Monday at 9 AM
System.schedule('Weekly Report', cronExpr, new MySchedulableClass());
Critical difference from standard cron: Day-of-week uses 1-7 where 1=Sunday, 2=Monday, ..., 7=Saturday. Standard cron uses 0-6 where 0=Sunday, 1=Monday, ..., 6=Saturday. A Monday in standard cron is 1; in Salesforce Apex it is 2.
Common Salesforce Apex Cron Expressions
| Goal | Apex Expression | Notes |
|---|---|---|
| Every day at 9 AM | 0 0 9 * * ? * | ? in day-of-week = no restriction |
| Every weekday at 9 AM | 0 0 9 ? * 2-6 * | 2-6 = Mon through Fri in Apex |
| Every Monday at 9 AM | 0 0 9 ? * 2 * | 2 = Monday in Apex (not 1) |
| Every hour at :30 | 0 30 * * * ? * | Runs at :30 past every hour |
| First of month midnight | 0 0 0 1 * ? * | ? in day-of-week, 1 in day-of-month |
| Last day of month | 0 0 0 L * ? * | L = last day of month |
| Last Friday of month | 0 0 0 ? * 6L * | 6 = Friday, L = last occurrence |
| Second Monday of month | 0 0 9 ? * 2#2 * | 2 = Monday, #2 = second occurrence |
Day-of-week name aliases work identically: MON-FRI is the same as 2-6 in Salesforce Apex. Name aliases are more readable for team code reviews.
Converting a Standard Cron Expression to Salesforce Apex Format
Use our cron generator to build the standard 5-field expression, then convert:
- Add seconds field (0) at the start. Standard
0 9 * * *becomes0 0 9 * * ?. - Add
?to whichever day field you don't want to restrict. Salesforce requires exactly one of day-of-month or day-of-week to be?. - Adjust day-of-week numbers. Add 1 to standard cron numbers: standard Monday (1) → Apex Monday (2). Sunday is standard 0 → Apex 1.
- Optionally add year field (
*) at the end.
Example: Standard 0 9 * * 1-5 (9 AM weekdays) → Apex 0 0 9 ? * MON-FRI *
| Standard cron | Salesforce Apex |
|---|---|
0 9 * * * | 0 0 9 * * ? * |
0 9 * * 1-5 | 0 0 9 ? * MON-FRI * |
0 0 1 * * | 0 0 0 1 * ? * |
0 9 * * 1 | 0 0 9 ? * MON * |
*/30 * * * * | 0 0/30 * * * ? * |
Salesforce Apex Scheduler Limits and Gotchas
- 100-job limit: Each Salesforce org can have a maximum of 100 scheduled Apex jobs running simultaneously. This includes jobs scheduled by managed packages. Query current count with:
SELECT COUNT() FROM CronTrigger WHERE CronJobDetail.JobType = '7' - Minimum 1-hour interval: While the cron format supports per-minute scheduling, Salesforce documentation recommends against scheduling jobs more frequently than once per hour. Overly frequent jobs can trigger governor limits.
- Deleting scheduled jobs: Use
System.abortJob(jobId). Query the job ID withSELECT Id FROM CronTrigger WHERE CronJobDetail.Name = 'Your Job Name'. - Test class requirement: Scheduled Apex must be tested with
Test.startTest() / Test.stopTest()wrapping theSystem.schedule()call. The test framework executes the scheduled job synchronously withinstopTest(). - Time zone: Scheduled Apex runs in the org's default timezone as configured in Setup. Unlike Quartz, there is no per-job timezone setting.
Try It Free — No Signup Required
Runs 100% in your browser. No account, no install, no limits.
Open Free Cron GeneratorFrequently Asked Questions
What is the cron expression format for Salesforce System.schedule()?
Salesforce uses a 7-field format: "Seconds Minutes Hours Day-of-month Month Day-of-week [Year]". Day-of-week uses 1-based numbering where 1=Sunday, 2=Monday, ..., 7=Saturday — one higher than standard cron. Either day-of-month or day-of-week must be set to ? (no specific value). Example: "0 0 9 ? * 2 *" means every Monday at 9 AM.
How do I schedule an Apex class to run every Monday at 9 AM?
Use: System.schedule("Weekly Job", "0 0 9 ? * MON *", new MySchedulableClass()); The expression "0 0 9 ? * MON *" means: second=0, minute=0, hour=9, day-of-month=? (any), month=* (every), day-of-week=MON (Monday), year=* (every year). Your class must implement the Schedulable interface with an execute(SchedulableContext sc) method.
Can Salesforce Apex run a scheduled job more than once per hour?
Technically yes — the cron format supports per-minute intervals. However, Salesforce recommends against scheduling more frequently than once per hour to avoid governor limits. For high-frequency processing, use a Queueable or Batchable Apex class triggered by platform events or a message queue rather than over-scheduling cron jobs.

