No — the future method does NOT fire, and worse, the batch chunk throws an AsyncException and fails.
What’s happening step by step
- Batch Apex starts,
executeruns with a chunk of Opportunities. executeissuesupdate opportunities;- Salesforce fires the Opportunity update trigger.
- The trigger calls
MyClass.doAsyncWork(ids);— a@futuremethod. - The platform detects: “this is a future call inside a batch transaction” — throws:
System.AsyncException: Future method cannot be called from a future or batch method.
The chunk fails. The opportunities in that chunk are rolled back. The batch moves to the next chunk and the same thing happens. Every chunk fails. The future method never executes for any record touched by the batch.
The full failure chain
public class OpptySyncBatch implements Database.Batchable<sObject> {
public Database.QueryLocator start(Database.BatchableContext ctx) {
return Database.getQueryLocator('SELECT Id, StageName FROM Opportunity WHERE IsClosed = false');
}
public void execute(Database.BatchableContext ctx, List<Opportunity> scope) {
for (Opportunity o : scope) o.StageName = 'Qualification';
update scope; // triggers OpportunityTrigger
}
public void finish(Database.BatchableContext ctx) {}
}
trigger OpportunityTrigger on Opportunity (after update) {
Set<Id> ids = new Set<Id>();
for (Opportunity o : Trigger.new) ids.add(o.Id);
OpptyAsync.callExternal(new List<Id>(ids)); // <-- AsyncException
}
public class OpptyAsync {
@future(callout=true)
public static void callExternal(List<Id> ids) { /* never runs */ }
}
What the user sees:
AsyncApexJob.Status = 'Failed'(orCompletedwithNumberOfErrors > 0)- Every error message says “Future method cannot be called from a future or batch method”
- Zero records updated in the org
Why Salesforce blocks this
A batch processing 1 million records in 5,000 chunks could enqueue 5,000 future calls in seconds if this were allowed. That would either flood async capacity or trigger an outage-level fan-out. The rule is simple and absolute: batch transactions cannot enqueue future methods.
The same rule applies to future-from-future and future-from-batch — see the related questions.
Common interview follow-ups
- Will the batch retry the failed chunks? — No, Batch Apex doesn’t auto-retry. You’d re-run the batch manually after fixing the code.
- Does only DML inside
executecause it? — Any path fromexecute(orstart/finish) to a future call fails — whether it’s a direct call, a trigger handler invocation, a flow that calls Apex, anything. - What if the trigger guards against future calls in batch context? — Then the trigger doesn’t throw. See the next question for how to detect batch context.
Verified against: Apex Developer Guide — Batch Apex Limitations. Last reviewed 2026-05-17.