A scheduled Apex class must implement the System.Schedulable interface. The interface has exactly one method:
public interface Schedulable {
void execute(SchedulableContext ctx);
}
That’s the whole contract. Your class becomes schedulable the moment it provides that one method.
Minimal example
public class HelloScheduler implements Schedulable {
public void execute(SchedulableContext ctx) {
System.debug('Hello from the scheduler at ' + Datetime.now());
}
}
Schedule it with:
System.schedule('Hello', '0 0 * * * ?', new HelloScheduler());
What SchedulableContext is
SchedulableContext is the context object passed to execute. It has one useful method:
public interface SchedulableContext {
Id getTriggerId();
}
getTriggerId() returns the CronTrigger Id — the record that represents the schedule itself. Use it to inspect the schedule or modify it from within execute:
public void execute(SchedulableContext ctx) {
CronTrigger ct = [
SELECT CronExpression, TimesTriggered, NextFireTime
FROM CronTrigger WHERE Id = :ctx.getTriggerId()
];
System.debug('Times triggered: ' + ct.TimesTriggered);
}
Common combinations
A class can implement Schedulable together with other interfaces:
// Schedulable + Batchable — one class is both
public class NightlyCleanup implements
Database.Batchable<sObject>,
Schedulable
{
public void execute(SchedulableContext ctx) {
Database.executeBatch(this, 200);
}
public Database.QueryLocator start(Database.BatchableContext ctx) { /* ... */ }
public void execute(Database.BatchableContext ctx, List<sObject> scope) { /* ... */ }
public void finish(Database.BatchableContext ctx) {}
}
Apex distinguishes the two execute methods by parameter type — SchedulableContext vs Database.BatchableContext. No compiler conflict.
What the interface gives you
When you implement Schedulable:
| Capability | Source |
|---|---|
System.schedule(jobName, cron, instance) works | Type compatibility |
| The job appears in Setup → Scheduled Jobs | Platform auto-registration |
The job creates a CronTrigger record | Platform |
| Up to 100 such jobs allowed in the org | Platform limit |
getTriggerId() returns the schedule’s record Id | Interface contract |
Common mistakes
- Forgetting to make
executepublic — protected/private won’t work. - Wrong return type — must be
void. - Wrong parameter type — must be
SchedulableContext, notSchedulableContext[]or anything else. - Trying to take constructor params for the schedule itself — the schedule is configured via
System.schedule, not the constructor.
Common interview follow-ups
- Which package is the interface in? —
Systemnamespace.System.SchedulableandSchedulableare equivalent. - Can a single class be scheduled multiple times? — Yes — each
System.schedulecall creates a separateCronTrigger. - Can the scheduled class be virtual / abstract? — Yes, but the concrete subclass is what you actually schedule.
Verified against: Apex Developer Guide — Schedulable Interface. Last reviewed 2026-05-17.