Study guide
9.4 Schedulable Apex & Job Orchestration
Salesforce Certified Platform Developer I Exam
Track your progress as you read
Finished sections get a check mark.
1 Introduction & Exam Overview
1.1 Current Exam Facts 1.2 Blueprint Weights & Study Strategy
2 Platform Fundamentals
2.1 Multi-Tenant Architecture & Shared Resources 2.2 MVC Mapping on the Lightning Platform 2.3 Declarative vs Programmatic Decisions 2.4 Agentforce for Developers: Use Cases & Limitations
3 Data Modeling & Schema
3.1 Objects, Fields & Schema Design 3.2 Relationship Types & Implications 3.3 Schema Design Impact on Apex 3.4 Data Import & Export for Development
4 Platform Data Features
4.1 Formula Fields & Roll-Up Summaries 4.2 Core CRM Objects & Standard Schema 4.3 AppExchange Extensions & Platform Boundaries
5 Declarative Process Automation
5.1 Record-Triggered Flows & Declarative Automation 5.2 Approval Processes & Business Rules 5.3 When to Use Apex vs Declarative Tools
6 Apex Language Basics
6.1 Variables, Constants & Apex Data Types 6.2 Lists, Sets & Maps 6.3 Control Flow & Exception Handling 6.4 Classes, Interfaces & OOP Patterns
7 SOQL, SOSL & DML
7.1 SOQL Query Fundamentals 7.2 SOSL Search Fundamentals 7.3 DML Operations & Bulkification 7.4 Governor Limits & Transaction Boundaries
8 Apex Triggers & Order of Execution
8.1 Trigger Structure & Context Variables 8.2 Bulk Trigger Patterns & Best Practices 8.3 Save Order of Execution 8.4 Recursion, Cascading & Transaction Control
9 Asynchronous Apex
9.1 @future Methods 9.2 Queueable Apex 9.3 Batch Apex 9.4 Schedulable Apex & Job Orchestration
10 Security, Events & Schema Access
10.1 Sharing, FLS, CRUD & Injection Prevention 10.2 Platform Events Publish & Subscribe 10.3 Programmatic Schema Access (Describe)
11 Visualforce
11.1 Visualforce Pages & Markup 11.2 Standard, Custom Controllers & Extensions 11.3 Visualforce in Lightning Experience
12 Lightning Components
12.1 Lightning Component Framework Benefits 12.2 Aura Component Structure & Resources 12.3 Lightning Web Components Fundamentals 12.4 LWC Data Access: Wire, Imperative & Events
13 UI Composition & Apex Integration Patterns
13.1 Composing UI in Lightning Apps 13.2 UI Security, Performance & Accessibility Patterns 13.3 Apex Actions for Flow, LWC, and Agentforce
14 Apex Testing
14.1 Testing Framework & Coverage Requirements 14.2 Writing Unit Tests for Triggers & Classes 14.3 Test Data Strategies & Isolation 14.4 Executing Tests & Execute Anonymous Differences
15 Debugging & Developer Tools
15.1 Debug Logs & Monitoring 15.2 Developer Console, CLI, VS Code & Workbench 15.3 Sandboxes, Scratch Orgs & Environment Strategy
16 Deployment & Release
16.1 Change Sets & Metadata Deployment 16.2 Unlocked Packages, Metadata API & Salesforce DX 16.3 Release Readiness & Credential Maintenance
9.4 Schedulable Apex & Job Orchestration
Key Takeaways Explain This Topic AI
Implement Schedulable and use System.schedule with a cron expression to run Apex on a schedule
Scheduled jobs commonly launch Batch Apex (or enqueue Queueable) from the execute method for heavy work
Cron strings define second, minute, hour, day-of-month, month, day-of-week, optional year—one-time and recurring patterns both appear on exams
Manage jobs in Setup (Scheduled Jobs / Apex Jobs); abort or reschedule carefully in production
Test with System.schedule between Test.startTest and Test.stopTest; design orchestration as schedule → batch → queueable chains when needed
Last updated: August 2026
9.4 Schedulable Apex & Job Orchestration
Quick Answer: Schedulable Apex implements Schedulable and is registered with System.schedule(jobName, cronExp, schedulableInstance) . On fire, execute(SchedulableContext) runs—typically to Database.executeBatch or System.enqueueJob . Use cron for recurring or one-time runs, manage jobs in Setup , and test with startTest/stopTest . Orchestration chains schedule → batch → queueable for reliable multi-step automation.
Not all async work is user-triggered. Nightly cleanups, hourly syncs, and monthly rollups need a clock. Schedulable Apex is the platform timer; combined with Batch and Queueable it becomes a full job orchestration toolkit tested on Platform Developer I.
- The Schedulable Interface public class NightlyAccountReviewSched implements Schedulable {
- public void execute(SchedulableContext sc) {
- // Keep this method thin: start the real work asynchronously
- Database.executeBatch(new AccountIndustryBatch(), 200);
- }
- }
Best practice: Do not put massive SOQL/DML directly in Schedulable.execute if a Batch or Queueable is more appropriate. The scheduled execute is a kickoff —especially when data volume is large.
You can still run modest logic inline for tiny maintenance tasks, but exam and production guidance favor launching Batch/Queueable for non-trivial work so governors and monitoring stay clear.
- System.schedule and Cron Expressions String cron = '0 0 2 * * ?'; // 02:00:00 every day
- String jobName = 'Nightly Account Review';
- Id jobId = System.schedule(jobName, cron, new NightlyAccountReviewSched());
- Cron field order (Salesforce)
- Position Field Common values
- 1 Seconds 0–59
- 2 Minutes 0–59
- 3 Hours 0–23
4 Day of month 1–31 or ?
5 Month 1–12 or JAN–DEC
6 Day of week 1–7 or SUN–SAT or ?
7 Year (optional) e.g. 2026
Special characters you should recognize:
- * — every value
- ? — no specific value (used for day-of-month or day-of-week when the other is specified)
- , — list ( 1,15 )
- — range ( MON-FRI )
- / — increments ( 0/15 minutes = every 15 minutes starting at 0)
- Examples: 0 0 2 * * ? → every day at 2:00:00 AM
- 0 30 9 ? * MON-FRI → 9:30:00 AM on weekdays
- 0 0 0 1 * ? → midnight on the 1st of each month
- 0 0/30 * * * ? → every 30 minutes
- 0 0 12 8 8 ? 2026 → one-shot noon on Aug 8, 2026 (with year)
Day-of-month vs day-of-week: Specify one and put ? in the other. Specifying both concretely is a common cron mistake that fails scheduling.
Job name uniqueness: System.schedule job names must be unique among scheduled jobs; reusing a name without aborting the old job causes errors.
One-Time vs Recurring Jobs
- Style How
- Recurring Cron with wildcards/increments ( 0 0 2 * * ? )
- One-time Cron fixed to a future datetime (optionally with year), or schedule once and abort after run
Near-term delay Some designs use a cron a few minutes ahead as a poor-man’s delay; Queueable/future is usually better for “run soon after this transaction”
For “run after this save,” prefer Queueable/@future , not Schedulable. Schedulable is for calendar-driven execution.
- Scheduled Jobs Launching Batch (Core Pattern) public class ContactCleanupSched implements Schedulable {
- public void execute(SchedulableContext sc) {
- // Optional: use sc.getTriggerId() to correlate the scheduled job
- Id batchId = Database.executeBatch(new ContactCleanupBatch(), 200);
- System.debug('Started batch: ' + batchId);
- }
- }
Why this pattern dominates:
Schedule provides the clock.
Batch provides volume-safe chunking.
finish on the batch can enqueue Queueable for notifications or callouts that do not need full batch machinery. // Inside batch finish
- public void finish(Database.BatchableContext bc) {
- System.enqueueJob(new CleanupReportQueueable(bc.getJobId()));
- }
- Orchestration Patterns (Schedule → Batch → Queueable)
- Pattern 1 — Nightly pipeline
Schedulable fires at 2 AM.
Batch A processes object 1.
finish starts Batch B for object 2.
Final finish enqueues Queueable to call out a “success” webhook or email.
Each stage is a separate async boundary with its own governors and monitoring row in Apex Jobs.
Pattern 2 — Hourly delta sync
Schedulable every hour → Batch with QueryLocator filtered by LastModifiedDate = LAST_N_HOURS:1 → Queueable callouts per failed Id list stored in Stateful or custom object.
Pattern 3 — Multi-step with Queueable only
When volume is low, Schedulable → Queueable chain (step1 → step2) without Batch. Prefer this when QueryLocator scale is unnecessary.
Pattern 4 — Guardrails
Before executeBatch , query whether a job of the same type is already Processing to avoid stacking duplicate nightly runs after long overruns. Store “last successful run” on a custom settings/metadata-backed config if business rules require exact windows.
Management in Setup
Admins and developers manage jobs in Setup:
- Scheduled Jobs — view cron-based jobs, next fire time, abort schedules
- Apex Jobs — monitor Batch, Queueable, future, and related async execution status
Programmatic management includes System.abortJob(jobId) for scheduled or async jobs when you have the appropriate Id (scheduled job Id from schedule , or AsyncApexJob Id).
Operational tips the exam may frame as best practice:
- Use clear job names including purpose and environment
- Document cron in business time zones carefully (org time zone matters)
- Abort and reschedule rather than silently stacking duplicates
- Prefer idempotent batch logic so a rerun after failure is safe
- Testing Scheduled Classes @IsTest
- private class NightlyAccountReviewSchedTest {
- @IsTest
- static void schedulesAndRunsKickoff() {
- // Arrange data the batch will see
- insert new Account(Name = 'Sched Test');
- String cron = '0 0 0 15 3 ? 2099'; // far-future one-time style expression
- Test.startTest();
- String jobId = System.schedule(
- 'Test Nightly Account Review',
- cron,
- new NightlyAccountReviewSched()
- );
- Test.stopTest();
- // After stopTest, scheduled execute is forced in test context
- // Assert batch effects or that AsyncApexJob rows exist as appropriate
- System.assertNotEquals(null, jobId);
- }
- }
Testing facts:
System.schedule in tests still needs startTest/stopTest so the scheduled execute runs in the test’s async flush.
You do not wait until 2099 for the cron to fire in a unit test—the test framework executes the scheduled job at stopTest when scheduled inside the test boundary.
Assert outcomes of the kicked-off batch/queueable, not only that schedule returned an Id.
For callouts in downstream jobs, set mocks before stopTest.
Combining with Other Async Types (Decision Matrix)
- Triggering need Mechanism
- User save / trigger side effect Queueable or @future
- Calendar / recurring Schedulable
- Large record volume Batch (often from Schedulable)
- Flexible multi-step with state Queueable chain
- Mass volume multi-object Batch chain via finish
- Callout-heavy small sets Queueable + AllowsCallouts
- Callout-heavy large sets Batch + AllowsCallouts + small scope
- Common Exam Traps
Putting millions of rows of DML directly in Schedulable.execute instead of Batch.
Wrong cron: day-of-month and day-of-week both set without ? .
Expecting Schedulable to return processed data to a Visualforce page synchronously—scheduled work is async; the page cannot wait on tonight’s job.
Confusing System.schedule (Schedulable) with System.enqueueJob (Queueable) or Database.executeBatch (Batchable).
Forgetting that scheduled jobs count toward org async limits and concurrent batch limits—design spacing and scope accordingly.
Using Schedulable for work that must run immediately after DML in the same user flow —use Queueable/future instead.
- End-to-End Mental Model [Clock] System.schedule → Schedulable.execute
- ↓
- [Volume] Database.executeBatch → start → execute* → finish
- ↓
- [Flex] System.enqueueJob → Queueable.execute → (optional chain)
- ↓
- [Watch] AsyncApexJob / Setup Apex Jobs / Scheduled Jobs
If you can sketch that pipeline and pick the correct interface for each box, you are ready for orchestration items on the exam.
Closing Checklist for Chapter 9
@future: static void, primitives/Ids only, callout=true, no future-to-future, test with start/stop.
Queueable: rich state, job Id, chaining, AllowsCallouts, post-commit workhorse.
Batch: start/execute/finish, QueryLocator at scale, scope + per-execute governors, Stateful, finish chaining.
Schedulable: cron clock, thin execute, launch batch/queueable, Setup management, test schedule inside start/stop.
Asynchronous Apex is how Lightning Platform apps stay responsive while still processing callouts, mixed DML, and org-scale data—choose the lightest tool that fits the volume and sequencing requirements.