โ† Back to list

๐Ÿงต Async Apex Unleashed: @future, Queueable, and Batchable with Real Patterns

Whats this Async you speak off

Musa Ndlala ยท 2025-07-02 08:26 ยท 12 claps ยท 4.0 min read paywalled
#salesforce #asyncapex #queueable-apex #salesforce-dev #solid
Open on Medium โ†—
Wiki topics: CRM ยท Email & CRM

๐Ÿงต Async Apex Unleashed: @future, Queueable, and Batchable with Real Patterns

Whats this Async you speak off

๐Ÿ‘€ You know that momentโ€ฆ Youโ€™re building a powerful LWC or a Flow-powered approval engine. Everything looks clean โ€” until one save operation triggers 7 updates, 2 callouts, and maybe even a data sync to another org. Boom โ€” limits hit, errors logged, admins confused.

Thatโ€™s when you realize: You need async Apex.

๐Ÿง  My Learning Strategy: Stay Curious, Stay Sharp

Before we dive in โ€” hereโ€™s how I learn anything deeply and permanently.

๐Ÿ’ก I ask 5 simple questions:

  • What is [concept]?
  • When would you use it?
  • Where would you use it?
  • Why would you use it?
  • How would you use it?

This forces me to live in the discovery phase of learning โ€” not just absorbing answers, but asking better questions. It sharpens critical thinking, builds context, and makes the knowledge actionable.

๐Ÿ” What are @future, Queueable, and Batchable?

These are Salesforceโ€™s async superheroes โ€” each with a job:

โœ… When would you use them?

Use async Apex when:

  • Youโ€™re making callouts from a trigger or after DML
  • Need to avoid hitting SOQL/DML governor limits
  • Processing massive data sets
  • Want to defer, chain, or scale logic
  • Breaking heavy logic into modular jobs

higher

higher

๐ŸŒ Where would you use them?

  • Triggers offloading post-DML logic
  • LWC or Flow โ†’ Apex โ†’ Queueable chain
  • Scheduled jobs and background cleanup
  • API integrations or post-callout workflows
  • Data-intensive batch reports

๐Ÿ’ก Why would you use them?

โœ… Protect against limits โœ… Improve user experience โœ… Scale up background processing โœ… Clean separation of concerns โœ… Retryable, debuggable logic

๐Ÿ› ๏ธ How would you use them?

โœ… Interface-first โœ… SOLID principles โœ… One instance per context โœ… Async logic lives outside the main transaction

๐ŸŽฏ Real-World Scenario: Booking Management System

After inserting new Booking__c records, we want to: โœ… Check vehicle availability (callout) โœ… Queue updates & notify managers โœ… Batch-process usage data

1๏ธโƒฃ @future(callout=true) โ€” Fire-and-Forget Callout

๐Ÿ”น Interface

public interface IBookingCallout {
    void scheduleAvailabilityCheck(String bookingId);
}

๐Ÿ”น Implementation

public class BookingCallout implements IBookingCallout {
    @future(callout=true)
    public static void scheduleAvailabilityCheck(String bookingId) {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('callout:VehicleService/bookings/' + bookingId);
        req.setMethod('GET');
        HttpResponse res = new Http().send(req);
        System.debug(res.getBody());
    }

    public void scheduleAvailabilityCheck(String bookingId) {
        scheduleAvailabilityCheck(bookingId);
    }
}

2๏ธโƒฃ Queueable โ€” Chainable Background Logic

๐Ÿ”น Interface

public interface IBookingQueueHandler {
    void enqueueBookingUpdate(Set<Id> bookingIds);
}

๐Ÿ”น Implementation

public class BookingQueueHandler implements IBookingQueueHandler {
    public void enqueueBookingUpdate(Set<Id> bookingIds) {
        System.enqueueJob(new BookingQueueJob(bookingIds));
    }
}

public class BookingQueueJob implements Queueable {
    private final Set<Id> bookingIds;

    public BookingQueueJob(Set<Id> bookingIds) {
        this.bookingIds = bookingIds;
    }

    public void execute(QueueableContext context) {
        List<Booking__c> updates = [SELECT Id, Status__c FROM Booking__c WHERE Id IN :bookingIds];
        for (Booking__c b : updates) {
            b.Status__c = 'Queued';
        }
        update updates;
    }
}

3๏ธโƒฃ Batchable โ€” Mass Fleet Processing

๐Ÿ”น Interface

public interface IFleetBatchRunner {
    void runFleetUsageBatch();
}

๐Ÿ”น Implementation

public class FleetUsageBatchRunner implements IFleetBatchRunner {
    public void runFleetUsageBatch() {
        Database.executeBatch(new FleetUsageBatch(), 200);
    }
}

public class FleetUsageBatch implements Database.Batchable<SObject> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator([SELECT Id FROM Fleet__c]);
    }

    public void execute(Database.BatchableContext context, List<SObject> scope) {
        List<Fleet__c> fleetRecords = (List<Fleet__c>) scope;
        for (Fleet__c f : fleetRecords) {
            f.Usage_Status__c = 'Processed';
        }
        update fleetRecords;
    }

    public void finish(Database.BatchableContext context) {
        System.debug('Fleet usage report done.');
    }
}

[embed]

๐Ÿงช Test It Like You Mean It

@isTest
public class BookingQueueTest {
    @isTest static void testQueueLogic() {
        List<Booking__c> bList = [SELECT Id FROM Booking__c LIMIT 2];
        new BookingQueueHandler().enqueueBookingUpdate(new Map<Id, Booking__c>(bList).keySet());

        Test.startTest();
        System.enqueueJob(new BookingQueueJob(new Map<Id, Booking__c>(bList).keySet()));
        Test.stopTest();
        // Assert logic
    }
}

๐Ÿง  Bonus: Async Apex in a Real-World Orchestration Pattern

Imagine this in a real trigger or Flow-powered framework:

  • ๐Ÿ”ฅ Trigger inserts a Booking__c โ†’ delegates to service
  • ๐Ÿ” Service:

1.Triggers @future callout

2.Enqueues Queueable for post-save actions

3.Nightly scheduled class kicks off Batchable for reporting

๐ŸŽฏ Each task is isolated, reusable, testable. โš™๏ธ Easy to extend. ๐Ÿงช Safe to mock.

โœ… SOLID Design Highlights

๐Ÿ”š Conclusion

Async Apex isnโ€™t optional anymore โ€” itโ€™s how you build scalable, limit-safe systems in Salesforce.

When your app hits governor walls, or your integrations get complex โ€” donโ€™t hack your way out. Design your way out with @future, Queueable, and Batchable.

Just remember: โœ… One class per task โœ… Interface it โœ… Mock it โœ… Test it โœ… Scale it

Because true architects donโ€™t fear async. They orchestrate it. ๐ŸŽผ๐Ÿงต โ€” The SalesforceKlever way


๋ฉ”ํƒ€๋ฐ์ดํ„ฐ
post_id
e2a7dff45c21
slug
async-apex-unleashed-future-queueable-and-batchable-with-real-patterns-e2a7dff45c21
url
https://medium.com/@kmniroi/async-apex-unleashed-future-queueable-and-batchable-with-real-patterns-e2a7dff45c21
canonical_url
https://medium.com/@kmniroi/async-apex-unleashed-future-queueable-and-batchable-with-real-patterns-e2a7dff45c21
author_url
https://medium.com/@kmniroi
status
ok
fetched_at
2026-08-06 02:43:51