Why Async Apex?
Synchronous Apex runs in the same transaction as the triggering operation and shares its governor limits. When you need to make a callout from a trigger, process large data volumes, or run long-running operations without blocking the user, you need asynchronous Apex.
@future Methods — Simplest Option
Use when: You need a simple fire-and-forget operation — most commonly making a callout from a trigger context, which is not allowed synchronously.
Limitations:
- Parameters must be primitive types (no SObject parameters)
- Cannot be called from another
@futureor a Batch context - Cannot be chained — one fires and that is it
- No monitoring or progress tracking in Salesforce
Governor limits: 50 @future calls per transaction; 250,000 calls per 24 hours per org.
Queueable Apex — The Flexible Middle Ground
Use when: You need to pass non-primitive parameters (such as SObjects or collections), chain jobs sequentially, or monitor execution from the Apex Jobs page.
Advantages over @future:
- Accepts any parameter type via the constructor
- Can chain up to 5 jobs (more in sandboxes) using
System.enqueueJob()from insideexecute() - Visible and cancellable in the Apex Jobs monitor
Governor limits: 50 jobs enqueued per transaction; same 250,000 daily limit as @future.
Batch Apex — Large Data Volumes
Use when: You need to process more than 50,000 records, or you want to chunk a large dataset into manageable pieces with a configurable batch size.
How it works: Implement Database.Batchable with three methods — start() returns a query locator, execute() processes each chunk, finish() runs post-processing. Each chunk gets its own governor limit set.
Limitations: Callouts are only allowed if you also implement Database.AllowsCallouts. Maximum 5 active batch jobs at once.
Quick Decision Rule
Simple callout from a trigger → @future. Pass objects or chain jobs → Queueable. Process 50,000+ records → Batch Apex.