Salesforce Dictionary - Free Salesforce GlossarySalesforce Dictionary
All errors
Apex

You have exceeded the maximum number of scheduled Apex jobs (100)

Salesforce caps each org at 100 scheduled Apex jobs in the queue at a time. Once you hit 100, scheduling a new job fails. Audit `CronTrigger` for stale jobs; abort or consolidate before scheduling more.

Also seen asmaximum number of scheduled Apex jobs·100 scheduled jobs·schedule limit·ScheduleException

The 100-job cap counts every Apex class scheduled with System.schedule(...). If your org has been running for years, old jobs accumulate — schedules created during pilots, testing, abandoned features.

Audit existing scheduled jobs

SELECT Id, CronJobDetail.Name, NextFireTime, State
FROM CronTrigger
WHERE CronJobDetail.JobType = '7'   -- Scheduled Apex
ORDER BY CronJobDetail.Name

(JobType = '7' is Scheduled Apex; other JobTypes are Batch, Future, etc.)

The result shows your job count. Over 90 = warning territory.

Abort stale jobs

List<CronTrigger> jobs = [
    SELECT Id, CronJobDetail.Name FROM CronTrigger
    WHERE CronJobDetail.JobType = '7'
];
for (CronTrigger ct : jobs) {
    if (ct.CronJobDetail.Name.startsWith('Old_')) {
        System.abortJob(ct.Id);
    }
}

System.abortJob removes a job immediately. Other jobs are unaffected. Once aborted, the slot frees and you can schedule a new one.

Fix: consolidate schedules

If you have 50 hourly jobs, consider one master scheduler that calls all of them:

public class MasterScheduler implements Schedulable {
    public void execute(SchedulableContext ctx) {
        Database.executeBatch(new JobA());
        System.enqueueJob(new JobB());
        new JobC().run();
    }
}

One job in the queue, multiple jobs execute. Cleaner, easier to monitor, doesn't bump against the 100 cap.

Fix: use Queueable chains for one-time deferred work

System.schedule(...) is for recurring schedules. For "run X in 5 minutes" you don't need a schedule:

System.scheduleBatch(new MyBatch(), 'OneTimeRun_' + System.now().getTime(), 5);

Or use enqueueJob with a delay flag. These don't accumulate persistent CronTrigger rows.

A subtle source: scheduled tests in test classes

@isTest static void testScheduling() {
    System.schedule('Test_' + DateTime.now().getTime(), '0 0 1 * * ?', new MyJob());
    Test.startTest();
    Test.stopTest();
}

Tests sometimes fire System.schedule and forget to abort in the teardown. Each test run accumulates one more CronTrigger row. After enough test runs, you blow the cap.

Fix: always wrap in Test.startTest() / Test.stopTest(). The platform automatically aborts test-context schedules when the test ends.

When the org has too many job runs in flight

Different cap, similar feel. The org allows 5 concurrently running scheduled jobs. If five are simultaneously executing, the next scheduled fire-time is queued. Long-running jobs blocking new ones can manifest as "schedule limit exceeded" though that's misnamed — it's actually the in-flight cap.

Keep individual scheduled jobs short; offload heavy work to Batch Apex called from the schedulable.

Related dictionary terms