Beating the 100-Scheduled-Job Limit in Salesforce
Learn how this approach efficiently manages the platform's 100-job limit while ensuring scalability and ease of maintenance.
Join the DZone community and get the full member experience.
Join For FreeSalesforce’s 100-scheduled-job limit can sneak up on you when your org scales. You might think 100 scheduled jobs sounds like plenty — until various business units need daily batch runs, monthly triggers, specialized reporting tasks, and more. Suddenly, you’re stuck trying to figure out how to add more time-based processes without hitting that cap.
To tackle this, I designed a dynamic scheduling framework that consolidates multiple jobs into just one. Instead of scheduling every single job separately, we rely on custom settings to instruct a “master” scheduled job which tasks to run and when.
Where the Problem Begins
Imagine a typical scenario in a growing Salesforce organization:
- The accounting department wants daily billing processes.
- The sales team schedules lead cleanup tasks every morning.
- Marketing has weekly data export runs.
Each job gets its own scheduled class, and pretty soon, your org is crowded with scheduled jobs that collectively exceed the 100-job limit.
The Dynamic Scheduling Framework
The idea is simple: Instead of scheduling 50+ jobs, you schedule one master job. That single job looks at custom-setting records that specify which jobs to run at what times. This way, you remain well within Salesforce’s scheduling limit.
1. Custom Settings for Job Records
Instead of relying on multiple scheduled jobs that quickly bump you into Salesforce’s 100-job limit, we use a single custom setting containing multiple job records. Each record has the following key fields:
- Active (Checkbox) – Indicates whether this particular job should be run at all. Only active jobs are processed.
- Class Name – The name of the Apex class if the job is a Batch, Queueable, or Schedulable.
- Flow API Name – If the job runs a flow, this field captures its API name.
- Minute Interval, Hour Interval, Day Interval – Determine how frequently (in minutes, hours, or days) the job should run.
- Start Time – When to begin scheduling this job.
- Last Run – The last time the job was actually executed.
- Last Run Status – A quick status indicator (e.g., “Success” or “Failed”).
- Last Run Exception – Captures any error message if the last run fails.
These fields let you manage the entire schedule and execution logic without changing your code — just update or add records as needed.
2. The “Master Job”
Rather than scheduling each job individually, schedule one “master job” to run at a short interval (commonly every 5 minutes). Here’s what it does:
- Fetch active jobs
- Queries all the custom settings records where
Active = true
.
- Queries all the custom settings records where
- Check timing
- For each record, the master job looks at
LastRun
and compares it with the current time plus the configured intervals (minute interval, hour interval, or day interval). - If it’s time to run (i.e., now is greater than or equal to
LastRun + Interval
), the master job triggers that specific job.
- For each record, the master job looks at
- Update LastRun
- After executing the job, the master job updates the record with the new
LastRun
, along with any resulting status or exceptions.
- After executing the job, the master job updates the record with the new
Thanks to this centralized logic, your org always stays well under the scheduled job limit.
3. Executing the Right Apex (or Flow)
Every job could be one of several types — Flow, Schedulable Apex, Batch Apex, or Queueable Apex. The master job checks your custom setting record to see:
- If Flow API name is populated:
- The master job runs the corresponding Flow using its API name.
- If Class Name is populated:
- The master job instantiates and executes the indicated class.
- It checks if the class implements Schedulable, Batchable, or Queueable and calls the correct method accordingly.
By doing this dynamically, you can easily add or remove different job types without writing a bunch of new code — just plug in the name or API reference in the custom setting.
Example Flow
- Master job kicks off (every 5 minutes)
- It’s 12:00 PM; the master job starts.
- Query the custom setting
- Finds all active jobs and compares
LastRun + (Minute/Hour/Day interval)
with the current time. - Let’s say a record called
Daily_LeadCleanup
has an hour interval of 24 hours and aLastRun
of 12:00 PM yesterday. Today at 12:00 PM, it’s due to run again.
- Finds all active jobs and compares
- Execution
- The master job notices
Class Name = “DailyLeadCleanupBatch”
. - It runs
Database.executeBatch
(newDailyLeadCleanupBatch()
).
- The master job notices
- Update record
- Once the job completes, the master updates
LastRun
to 12:00 PM today. - If it fails,
Last Run Status = “Failed”
andLast Run Exception
contains the error. Otherwise,Last Run Status = “Success”
.
- Once the job completes, the master updates
- Next cycle
- At 12:05 PM, the master job starts again.
Daily_LeadCleanup
won’t run now because its next run time is 12:00 PM tomorrow. But other jobs might be due, depending on their intervals.
- At 12:05 PM, the master job starts again.
Why This Works So Well
- No 100-job limit. Only one master job is actually scheduled; it orchestrates everything else.
- Flexible intervals. Each job can have its own minute/hour/day intervals without messing up the schedule.
- Easy maintenance. Turn jobs on or off by toggling Active. Tweak intervals simply by updating record fields.
- Unified error tracking. Logging exceptions and statuses in
Last Run Status
andLast Run Exception
makes troubleshooting easier. - Scalable. As your org grows, adding more tasks is simply a matter of creating new custom-setting records.
Conclusion
With this approach, you turn Salesforce’s scheduling constraints into a centralized, metadata-driven solution. One master job checks your custom setting every 5 minutes (or whatever interval you choose) and executes whichever tasks are due. If you’ve ever been frustrated by hitting the 100-scheduled-job ceiling, this framework offers a straightforward, sustainable way to keep your org’s automated processes humming.
Opinions expressed by DZone contributors are their own.
Comments