In Salesforce, scheduling jobs at specific times is essential for automating repetitive tasks. However, static schedules can become cumbersome when managing multiple jobs with varying intervals. Static cron expressions also lack the flexibility needed for dynamic business needs, and Salesforce limits organizations to just 100 active scheduled jobs. To overcome these constraints, Let’s explore how to create a Dynamic Job Scheduling Framework in Salesforce, to manage multiple scheduled jobs.
In this blog, we’ll dive deep into the Dynamic Job Scheduling Framework: what it is, how it works, and why it’s a needed for automating scheduled jobs in a dynamic environment.
Why Dynamic Job Scheduling Framework ?
Traditionally, in Salesforce, Scheduling multiple tasks to run at specific times, dates, or days requires creating individual scheduled jobs for each task in the Setup menu. While this works for simple automation, it quickly becomes inflexible when business logic changes. If you need to modify an existing scheduled job class, you must delete the current job from Setup before creating a new one — a non-dynamic and time-consuming process.
Another limitation is Salesforce’s 100-scheduled-job limit, which restricts the number of active jobs you can have. For organizations that require more complex scheduling or have a growing list of tasks, this can be a significant bottleneck.
The Dynamic Job Scheduling Framework solves these problems. By setting up only one master scheduled job in Setup, all other jobs are defined and managed in custom metadata.
What Dynamic Job Scheduling Framework can do :
- Overcome the 100-job limit, as you can define and manage more jobs in custom metadata.
- Modify scheduling logic on-the-fly without having to delete or recreate scheduled jobs.
- Add or remove tasks as needed without worrying about Salesforce’s scheduled job limit.
- Maintain a centralized configuration to control all scheduled jobs, reducing the complexity of managing multiple jobs.
With this framework, you gain flexibility, scalability, and easier management of your scheduled jobs in Salesforce, ensuring that your automation can evolve as your business needs change.
Salesforce Scheduling Basics
Salesforce uses the Schedulable interface to schedule jobs. Once apex class implements this Schedulable interface, it can be executed at specific intervals (hourly, daily, weekly, etc.).
Check this basic example:
public class MySchedulableClass implements Schedulable {
public void execute(SchedulableContext sc) {
// your logic here
}
}Now in Salesforce, you can schedule a job in Anonymous Window:
String cronExp = '0 0 0 * * ?'; // runs daily at midnight
MySchedulableClass job = new MySchedulableClass();
System.schedule('My Job1', cronExp, job);
You can also do same from Set up, search for scheduled Job, Click on Schedule Apex and provide same details as above and Click Save.
However, when you need flexibility and customization, it’s better to rely on Dynamic Job Scheduling framework
Key elements of this Framework
The Dynamic Job Scheduling Framework leverages One Master Scheduled Job which are scheduled to run every hour and Custom Metadata to store rest of all the job schedules dynamically.
- Custom Metadata Configuration: This Custom metadata records are used to store details about which schedulable class to run & what time, day, week and month.
- Master Apex Scheduler: This Master Apex Scheduler which is scheduled to run every hour, get all custom metadata records, loop through each metadata record and evaluates whether the current time, day, or month matches the conditions in the metadata and execute schedulable class from that record.
- Schedulable Classes: All your Schedulable classes along with when it should run (what time, day, month) should be stored in custom metadata we configured above.
- Error Handling: If a scheduled job fails to meet the conditions or throws an error, proper error handling mechanisms ensure the framework doesn’t crash and provides meaningful logs.
A step-by-step guide to Create this Framework
Dynamic Job Scheduling framework – Overview

Steps to Create Dynamic Job Scheduling Framework
Step-1 : Create Custom Metadata
First, create a Custom Metadata Type called Dynamic_Scheduled_Class_Config__mdt. This metadata type will store:
- The Schedulable Class API Name to execute
- The Month, Day of the Week, Day of the Month, and Hour to run the job
Therefore, Let’s create Dynamic Scheduled Class Config‘s Custom Fields as shown below :
Step-2 : Create Master Scheduler Class :- DynamicJobSchedulingManager
public without sharing class DynamicJobSchedulingManager implements Schedulable{
public void execute(SchedulableContext sc) {
//get all ScheduledClassConfig Custom Metadata records
List<Dynamic_Scheduled_Class_Config__mdt> schClassList = [
SELECT Id, DeveloperName, Schedulable_Class_API_Name__c,
What_Month_To_execute__c, What_Day_of_Month_to_Execute__c,
What_Day_To_Execute__c, What_Hour_To_Execute__c
from Dynamic_Scheduled_Class_Config__mdt
WHERE Is_Active__c = true];
checkToRunSchedulersOneByOne(schClassList, sc);
}
private void checkToRunSchedulersOneByOne(List<Dynamic_Scheduled_Class_Config__mdt> schClassList, SchedulableContext sc){
for (Dynamic_Scheduled_Class_Config__mdt scheduledClassDetail : schClassList) {
if (RunThisSchedulerNow(scheduledClassDetail)) {
try {
Type targetClass = Type.forName(scheduledClassDetail.Schedulable_Class_API_Name__c);
if (targetClass != null) {
Object classInstance = targetClass.newInstance(); // Create an instance of the class
// Check if the class has the Schedulable interface
if (classInstance instanceof Schedulable) {
Schedulable schedulableInstance = (Schedulable) classInstance;
schedulableInstance.execute(sc);
}
else {
system.debug('A class ' + scheduledClassDetail.Schedulable_Class_API_Name__c + ' doesnt implement Schedulable interface');
}
} else {
system.debug('A class ' + scheduledClassDetail.Schedulable_Class_API_Name__c + ' doesnt exist');
}
} catch (Exception ex) {
system.debug('Error Message: ' + ex.getMessage());
}
}
else{
system.debug('No scheduled class to run at this time');
}
}
}
private Boolean RunThisSchedulerNow(Dynamic_Scheduled_Class_Config__mdt rec){
Boolean checkToRunSchedulableClass = false;
//Map to convert month number to month name
Map<Integer, string> mapMonths = new Map<Integer, string>{
1=> 'JAN',2=> 'FEB',3=> 'MAR',4=> 'APR',5=> 'MAY',6=> 'JUN',
7=> 'JUL',8=> 'AUG',9=> 'SEP',10=> 'OCT',11=> 'NOV',12=> 'DEC'};
//Get current hour, month, day of month and day of week
Integer currentHour = System.now().hour();
String currentMonth = mapMonths.get(System.now().month());
Integer dayOfMonth = System.now().day();
String dayofWeek = System.now().format('EEE');
String dayToday = dayofWeek.toUpperCase();
String runOnMonth = String.valueOf(rec.What_Month_To_execute__c);
String runOnDayofWeek = String.valueOf(rec.What_Day_To_Execute__c);
Integer runOnDayofMonth = rec.What_Day_of_Month_to_Execute__c !='NoValue' ? Integer.valueOf(rec.What_Day_of_Month_to_Execute__c):32;
Integer runAtHour = Integer.valueOf(rec.What_Hour_To_Execute__c);
checkToRunSchedulableClass = ((runOnDayofWeek == dayToday && runAtHour == currentHour) ||
(runOnDayofWeek == dayToday && runOnMonth == currentMonth && runAtHour == currentHour) ||
(runOnMonth == currentMonth && runOnDayofMonth == dayOfMonth && runAtHour == currentHour) );
return checkToRunSchedulableClass;
}
}Let’s break down this code into pieces:
DynamicJobSchedulingManagerclass implements Schedulable interface so we can schedule it to every hour via CRON [ 0 0 * * * ? ]. check out here How to build Cron in Salesforce- First of All, it will fetch only Active custom metadata records of Dynamic_Scheduled_Class_Config. each of these record stores a schedulable class and when to run it.
- Once we have all Active metadata records, method
checkToRunSchedulersOneByOne(...)will be called,- Inside this method, For each record, Call
RunThisSchedulerNow(...)to decide if scheduler class should run Now. - If yes, Loads the class dynamically using Type.forName(…) & ensure it implements Schedulable.
- If anything fails (e.g., class not found, class doesn’t implement Schedulable), it logs a debug message.
- Inside this method, For each record, Call
- Inside
RunThisSchedulerNow(...)- It will decide whether a job should be run now based on
- Current month, day of the month, day of the week, and hour.
- Compare them with metadata values : WhatMonth, WhatDay …
- It returns true if any of the following match:
- Day of week & hour match [ e.g. 1 AM every Sunday]
- Day of week, month, & hour match [ e.g. 6 PM every Sunday in March, April]
- Day of month, month & hour match. [ e.g. 5 AM on 15th of every month]
- It will decide whether a job should be run now based on
Example Use Case
Business Scenario :
You’re running an e-commerce Platform where certain jobs needs to run on specific days of month/week or at different time based on several factors (like, weekly inventory updates, monthly financial reports)
Here are some frequent tasks :
- SendWeeklySalesReportJob : it sends weekly reports every week on Monday 7 AM.
- UpdateQuarterlyLoyaltyDiscountsJob : Update Discount for loyal customer quarterly .
You have decide to use Dynamic Job Scheduling Framework to handle to multiple scheduled tasks you have and its frequency can also be changed any time.
Here is how it will work :
- First task this to schedule our Master Scheduler class : DynamicJobSchedulingManager to run at every hour. So that every hour, this master scheduler check if current time matches any configured scheduler in custom metadata
- Now, we need to Set up metadata records Dynamic Scheduled Class Config to define specific Jobs we have above.
- Go to this custom metadata & create new records as follow

All Metadata Records for Scheduled Class Config :

3. Now Once you created metadata records for all scheduled Jobs, Our Master Scheduler class wakes up every hour and query this metadata & check if current time matches any specified time from metadata, it will execute that scheduler class right away.
Consideration
- This Frameworks’s Master Scheduler is running at every hour, Currently Salesforce Cron expression does not support every minute scenario, Therefore, this framework does not work in case your need to run your task at certain minutes of hour.
- This framework is best suited for scenarios with complex or frequently changing scheduled tasks, where managing multiple schedulable classes manually becomes inefficient. It offers flexibility and central control through metadata, reducing the need for frequent code changes. For simple or static schedules, native Salesforce scheduling may be more straightforward.
Summary
- Building a Dynamic Scheduler Framework in Salesforce is a powerful way to automate and schedule jobs based on flexible, customizable configurations. This approach offers increased maintainability, scalability, and flexibility for organizations with complex scheduling needs.
- By leveraging Custom Metadata, you can make job scheduling a breeze and tailor it according to your specific needs !




