Skip to main content

SF-0353 · Coding · Medium

Write a sample code utilizing a future method?

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

Here’s a clean, realistic future method that handles the most common interview ask: re-query records by Id, transform them, and post to an external system.

The code

public class AccountSyncService {

    /**
     * Sync accounts to the downstream ERP system.
     * Called from triggers, batch jobs, or controllers.
     */
    @future(callout=true)
    public static void syncToErp(List<Id> accountIds) {
        if (accountIds == null || accountIds.isEmpty()) return;

        // 1) Re-query for fresh data (future methods cannot take sObjects)
        List<Account> accounts = [
            SELECT Id, Name, AccountNumber, Industry, AnnualRevenue, BillingCountry
            FROM Account
            WHERE Id IN :accountIds
        ];

        if (accounts.isEmpty()) return;

        // 2) Build the payload
        Http http = new Http();
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:ERP_Credentials/v1/accounts/bulk');
        req.setMethod('POST');
        req.setHeader('Content-Type', 'application/json');
        req.setTimeout(60000);
        req.setBody(JSON.serialize(accounts));

        // 3) Send and handle response
        try {
            HttpResponse resp = http.send(req);
            if (resp.getStatusCode() >= 200 && resp.getStatusCode() < 300) {
                logSuccess(accounts);
            } else {
                logFailure(accounts, resp.getStatusCode(), resp.getBody());
            }
        } catch (CalloutException e) {
            logFailure(accounts, 0, e.getMessage());
        }
    }

    private static void logSuccess(List<Account> accs) {
        List<Erp_Sync_Log__c> logs = new List<Erp_Sync_Log__c>();
        for (Account a : accs) {
            logs.add(new Erp_Sync_Log__c(
                Account__c = a.Id,
                Status__c = 'Success',
                Synced_At__c = Datetime.now()
            ));
        }
        insert logs;
    }

    private static void logFailure(List<Account> accs, Integer status, String body) {
        List<Erp_Sync_Log__c> logs = new List<Erp_Sync_Log__c>();
        for (Account a : accs) {
            logs.add(new Erp_Sync_Log__c(
                Account__c = a.Id,
                Status__c = 'Failed',
                Error_Code__c = status,
                Error_Body__c = body?.left(32000),
                Synced_At__c = Datetime.now()
            ));
        }
        insert logs;
    }
}

How a trigger invokes it

trigger AccountTrigger on Account (after insert, after update) {
    Set<Id> idsToSync = new Set<Id>();
    for (Account a : Trigger.new) {
        Account old = Trigger.isUpdate ? Trigger.oldMap.get(a.Id) : null;
        Boolean changed = Trigger.isInsert
            || a.Name != old.Name
            || a.AnnualRevenue != old.AnnualRevenue;
        if (changed) idsToSync.add(a.Id);
    }
    if (!idsToSync.isEmpty()) {
        AccountSyncService.syncToErp(new List<Id>(idsToSync));
    }
}

The points an interviewer is checking

PointWhat it looks for
staticRequired — future methods cannot be instance methods
voidRequired — future methods cannot return values
@future(callout=true)Allows HTTP callouts
List<Id> parameterAvoids the sObject restriction
Re-query insideGuarantees fresh data
Named CredentialNo hardcoded secrets
BulkifiedOne call for many records, not 200 calls
Logged outcomesYou can’t return the response, so persist it

A minimal version

If they want it shorter:

public class HelloFuture {
    @future
    public static void sayHi(List<Id> ids) {
        List<Contact> cs = [SELECT Id, FirstName FROM Contact WHERE Id IN :ids];
        for (Contact c : cs) System.debug('Hi ' + c.FirstName);
    }
}

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