Use of @future method in loop
Why is this an issue?
This rule identifies instances where a method annotated with @future is called inside a loop.
Salesforce imposes a strict governor limit on the number of future method invocations allowed in a single transaction (currently 50). Invoking a future method within a loop creates a high risk of exceeding this limit, which results in a System.LimitException: Too many future calls and causes the transaction to fail.
Even if the loop count is low, this pattern indicates a lack of bulkification, leading to inefficient processing and harder-to-maintain code.
Examples
Example of incorrect code: The following code calls the async method once for every record in the list.
public void processAccounts(List<Account> accounts) {
for (Account acc : accounts) {
// Violation: Calling a @future method inside a loop
doAsyncCallout(acc.Id);
}
}
@future(callout=true)
public static void doAsyncCallout(Id accountId) {
// Logic to process single account
}
Example of correct code: The following code bulkifies the operation by collecting IDs and making a single async call.
public void processAccounts(List<Account> accounts) {
Set<Id> accountIds = new Set<Id>();
for (Account acc : accounts) {
accountIds.add(acc.Id);
}
// Fix: Call the @future method once outside the loop
if (!accountIds.isEmpty()) {
doAsyncCallout(accountIds);
}
}
@future(callout=true)
public static void doAsyncCallout(Set<Id> accountIds) {
// Logic to process the list of accounts
}
How can I fix violations?
To fix this violation, you must bulkify the future method.
Modify the
@futuremethod to accept a collection (e.g.,List<Id>,Set<Id>, orList<String>) instead of a single primitive value. Note: Future methods cannot accept sObjects as arguments.Update the calling logic to iterate through the data, collect the necessary IDs or values into a list, and invoke the future method once after the loop finishes.
When should I disable this rule?
You may consider dismissing specific violations if you are strictly iterating over a bounded collection that is guaranteed to be small (e.g., a hardcoded list of 2 or 3 items) and you intentionally require separate asynchronous transactions for each item.
Resources
