Skip to main content

SF-0404 · Concept · Medium

Which all types of classes or asynchronous processes we can schedule?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

Only classes that implement Schedulable can be passed directly to System.schedule. Batch Apex, Queueable, and future methods cannot be scheduled on their own — but they can run from inside a Schedulable’s execute method.

Directly schedulable

Apex typeImplements Schedulable?Schedulable directly?
Schedulable classYesYes
Batch Apex (Database.Batchable)No (unless also implements Schedulable)No (unless dual-implements)
QueueableNoNo
@future methodNoNo
TriggerN/ANo

The pattern: Schedulable wraps the work

The almost-universal real-world pattern is:

  1. Write a Schedulable class.
  2. In its execute(SchedulableContext), kick off Batch / Queueable / future / direct work.
  3. Schedule the Schedulable.
public class NightlyJob implements Schedulable {
    public void execute(SchedulableContext ctx) {
        // Choice 1: kick off a Batch
        Database.executeBatch(new MyBigBatch(), 200);

        // Choice 2: enqueue a Queueable
        // System.enqueueJob(new MyQueueable());

        // Choice 3: do work directly (small jobs only)
        // List<Lead> leads = [...];
    }
}

System.schedule('Nightly', '0 0 2 * * ?', new NightlyJob());

Convenience: System.scheduleBatch for Batch one-shots

For “run this batch once after N minutes”:

System.scheduleBatch(new MyBigBatch(), 'Retry MyBatch', 30, 200);

Salesforce auto-generates a Schedulable wrapper. The batch runs once and the schedule self-terminates. Useful for retries.

Dual-implementing Schedulable + Batchable

One class can be both:

public class NightlyCleanup implements
    Database.Batchable<sObject>,
    Schedulable
{
    // Schedulable.execute — fires from the schedule
    public void execute(SchedulableContext ctx) {
        Database.executeBatch(this, 200);
    }

    // Batchable.execute — fires per chunk
    public void execute(Database.BatchableContext ctx, List<sObject> scope) {
        // ... process chunk
    }
    public Database.QueryLocator start(Database.BatchableContext ctx) { /* ... */ }
    public void finish(Database.BatchableContext ctx) {}
}

System.schedule('Nightly', '0 0 2 * * ?', new NightlyCleanup());

Apex distinguishes the two execute methods by their parameter types. The Schedulable execute calls Database.executeBatch(this, ...) to kick off the batch lifecycle.

What you can call from a Schedulable’s execute

ActionAllowed from Schedulable.execute?
Database.executeBatchYes
System.enqueueJob (Queueable)Yes
@future method callYes (Schedulable counts as sync for this rule)
HTTP callout directlyNo — must go through Queueable or @future(callout=true)
Heavy DML / SOQLYes, but bounded by sync governor limits
EmailYes

The callout caveat

Schedulable.execute itself does not support callouts. If your scheduled work needs a callout:

public class CalloutSchedule implements Schedulable {
    public void execute(SchedulableContext ctx) {
        System.enqueueJob(new CalloutQueueable());
    }
}

public class CalloutQueueable implements Queueable, Database.AllowsCallouts {
    public void execute(QueueableContext ctx) {
        // ... HTTP callouts here
    }
}

Limits to know

LimitValue
Scheduled jobs in an org100
System.schedule calls per transaction250
One scheduled job can fire multiple timesYes (recurring schedules)
Each fire counts against daily async limitYes

Common interview follow-ups

  • Can I schedule a Queueable? — Not directly. Wrap it in a Schedulable and enqueue from execute.
  • Can I schedule a method instead of a class? — No. Schedule the class; the method called is always execute.
  • Can a Schedulable schedule itself? — Yes — it can call System.schedule for a new instance. Useful for one-shot patterns, but watch for runaway loops.

Verified against: Apex Developer Guide — Scheduled Apex. Last reviewed 2026-05-17.