asynchronous Apex interview questions

Asynchronous Apex is one of the most frequently tested—and most commonly misunderstood—areas in Salesforce developer interviews. Whether you’re preparing for a Salesforce Developer, Tech Lead, or Architect role, interviewers expect you to clearly explain when and why to use @future, Queueable, and Batch Apex, how they differ, and how they behave under real-world governor limits and execution constraints.

 This guide is part of our broader Salesforce Interview Questions: The Complete Preparation Guide for Every Salesforce Role, which brings together role-specific, scenario-based interview questions across Admin, BA, Developer, Architect, Integration, and Leadership tracks. If you’re building a full interview prep strategy, make sure to explore related deep-dives on Apex interview questions, LWC interviews, Salesforce Architect system-design questions, and Admin and Flow scenario questions—all designed to mirror what hiring managers actually ask.

Why Asynchronous Apex Matters for Salesforce Developers

Asynchronous Apex allows Salesforce developers to run processes in the background, handle large data volumes, make external API callouts, and overcome governor limits. Whether you’re targeting the Platform Developer 1 certification or preparing for senior developer roles, mastering asynchronous Apex is essential.

Asynchronous Apex

Batch Apex Interview Questions (Questions 1-50)

Understanding Batch Apex Fundamentals

1. What are the governor limits in Asynchronous Apex?

Asynchronous Apex has higher governor limits compared to synchronous Apex:

  • Total number of SOQL queries: 200 (vs. 100 in synchronous)
  • Total number of records retrieved by SOQL: 50,000,000 (vs. 50,000)
  • Total heap size: 12 MB (vs. 6 MB)
  • Maximum CPU time: 60,000 milliseconds

2. Explain the three methods used in Batch Apex

Every Batch Apex class must implement three key methods:

  • Start Method: Collects the records or objects to be processed and divides them into batches

    global Database.QueryLocator start(Database.BatchableContext BC) {
        // Return query locator with records to process
    }
    
  • Execute Method: Processes each batch of records separately

    global void execute(Database.BatchableContext BC, List<SObject> scope) {
        // Process the batch of records
    }
    
  • Finish Method: Executes after all batches complete, ideal for post-processing operations

    global void finish(Database.BatchableContext BC) {
        // Send notifications, cleanup, or chain another batch
    }
    

3. How do you invoke a Batch Class?

Use the Database.executeBatch() method with optional batch size parameter:

Database.executeBatch(new BatchApexExample(), 100);

4. How to monitor Batch Apex execution?

Navigate to Setup > Apex Jobs to monitor or abort batch executions. You can also query the AsyncApexJob object programmatically.

5. What is Batch Chaining and what are its limits?

Batch chaining allows you to call one batch job from another’s finish method. You can chain a maximum of 5 batch jobs together.

global void finish(Database.BatchableContext BC) {
    // Chain another batch
    AccountBatch accBatch = new AccountBatch();
    Database.executeBatch(accBatch);
}

6. Which interface is required for Batch Apex?

Database.Batchable interface is required. If making callouts, also implement Database.AllowsCallouts.

7. Why use Batch Apex instead of regular Apex?

Batch Apex offers significant advantages:

  • Processes up to 50 million records (vs. 50,000)
  • Higher SOQL query limits (200 vs. 100 per transaction)
  • Larger heap size (12 MB vs. 6 MB)
  • Ideal for mass updates, data cleanup, and complex transformations

8. How many batch jobs can run simultaneously?

Salesforce allows 5 active batch jobs running concurrently. Additional jobs wait in the queue.

9. When should you choose Batch Apex over Data Loader?

Use Batch Apex when you need to:

  • Perform complex runtime calculations
  • Execute relationship queries
  • Make external API callouts for each record
  • Implement custom business logic that can’t be handled by static data
  • Automate regular data processing tasks

10. How many times does the execute method run for 1,234 records?

It depends on your batch size:

  • Formula: Total Records / Batch Size (round up)
  • Default batch size (200): 1,234 ÷ 200 = 7 executions
  • Custom batch size (100): 1,234 ÷ 100 = 13 executions

Batch Size and Configuration

11. What is the maximum batch size you can set?

Maximum batch size: 2,000 records

12. What is the minimum batch size?

Minimum batch size: 1 record

13. What is the default batch size?

Default batch size: 200 records (if not specified when calling Database.executeBatch())

14. What is the Apex Flex Queue?

The Apex Flex Queue holds batch jobs in a “Holding” status when the 5 concurrent execution slots are full. It can store up to 100 batch jobs waiting to be executed.

15. What is the maximum capacity of the Apex Flex Queue?

100 batch jobs can be held in the Apex Flex Queue at any time.

Advanced Batch Apex Concepts

16. Why should you chain batches from the finish method, not execute?

The execute method runs multiple times based on batch size and record volume. Calling another batch from execute would invoke it multiple times, which is inefficient and may hit governor limits.

17. What’s the difference between QueryLocator and Iterable in Batch Apex?

  • Database.QueryLocator: Bypasses the 50,000 record SOQL limit, can query up to 50 million records
  • Iterable: Still subject to the 50,000 record SOQL governor limit, but offers more flexibility for custom data sources

18. What does “stateless” mean in Batch Apex?

By default, Batch Apex is stateless – each batch execution is a separate transaction. Instance variables don’t retain values between batches.

19. How does Database.Stateful work?

Implementing Database.Stateful allows instance member variables to maintain their values across all transactions. This is useful for counting or aggregating data across batches.

global class StatefulBatch implements Database.Batchable<sObject>, Database.Stateful {
    global Integer recordCount = 0;
    
    global void execute(Database.BatchableContext BC, List<sObject> scope) {
        recordCount += scope.size();
    }
}

20. When should you use Batch Apex instead of Queueable Apex?

Use Batch Apex when:

  • Processing more than 50,000 records
  • Need to divide work into multiple transactions
  • Dealing with large data volumes that require chunking

Use Queueable Apex when:

  • Processing smaller datasets
  • Need more flexibility than Future Methods
  • Want to chain jobs with complex logic

HTTP Callouts in Batch Apex

21. How do you use HTTP callouts in Batch Apex?

Implement the Database.AllowsCallouts interface:

global class CalloutBatch implements Database.Batchable<sObject>, Database.AllowsCallouts {
    // Your batch implementation
}

22. If one record fails in a batch of 200, what happens?

All 200 records in that batch will fail and be rolled back. However, the next batch will still execute normally.

23. Can you call a batch from another batch?

Yes, but only from the finish method to avoid governor limit violations.

24. Can you call a batch from the execute or start method?

No. Attempting to call Database.executeBatch() from start or execute methods throws:

System.AsyncException: Database.executeBatch cannot be called from a batch start, batch execute, or future method.

25. Can you call Batch Apex from triggers?

Yes, but use caution. Avoid calling batches on every trigger execution as you’re limited to 5 queued/active batch jobs at once.

Testing and Execution

26. How many times do start, execute, and finish methods run?

  • Start: Once per batch job
  • Execute: Multiple times based on batch size and total records
  • Finish: Once per batch job

27. Can you call Future Methods from Batch Apex?

No, Future Methods cannot be called from Batch Apex execute or start methods.

28. Can you call Queueable Apex from Batch Apex?

Yes, but limited to one System.enqueueJob() call per execute method to prevent explosive execution.

29. How do you test Batch Apex?

Wrap the batch execution between Test.startTest() and Test.stopTest():

@isTest
static void testBatch() {
    Test.startTest();
    Database.executeBatch(new MyBatchClass());
    Test.stopTest();
    // Assert results
}

30. How many records can you insert when testing Batch Apex?

Keep test records at or below the batch size (typically 200) since test methods execute only one batch synchronously.

Apex Flex Queue Management

31. What is the Apex Flex Queue?

A holding area for batch jobs that enables submission of up to 100 batch jobs for execution. Jobs in “Holding” status wait here before moving to “Queued” status.

32. Can you change the order of jobs in the Apex Flex Queue?

Yes, you can reorder jobs with “Holding” status using:

Boolean isSuccess = System.FlexQueue.moveBeforeJob(jobToMoveId, jobInQueueId);

33. What are the different job statuses in the Apex Flex Queue?

  • Holding: Job submitted and waiting for resources
  • Queued: Job ready for execution
  • Preparing: Start method is running
  • Processing: Execute method is running
  • Aborted: Job cancelled by user
  • Completed: Job finished (with or without failures)
  • Failed: System failure occurred

34. Can you queue 150 batch jobs simultaneously?

No. The Apex Flex Queue maximum is 100 jobs. Attempting to add the 101st job throws a LimitException.

35. Can you use FOR UPDATE in Database.QueryLocator?

No. Batch Apex automatically applies row locking, so FOR UPDATE is not allowed and will throw an exception.

36. Can you query related records using Database.QueryLocator?

Yes, but subqueries can slow batch processing. Consider performing subqueries separately within the execute method for better performance.

Batch Apex Code Examples

37. Can you write a Batch Apex blueprint?

global class MyBatchClass implements Database.Batchable<sObject> {
    
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name FROM Account');
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope) {
        // Process each batch
        for(Account acc : scope) {
            // Your logic here
        }
    }
    
    global void finish(Database.BatchableContext bc) {
        // Post-processing operations
    }
}

38. What happens if an error occurs on the 395th record in a 200-batch-size job?

The first batch (records 1-200) completes successfully and commits. The second batch (records 201-400), containing record 395, fails entirely and rolls back. Subsequent batches continue execution.

39. How do you stop a running Batch job?

Use the job ID returned by Database.executeBatch():

Id batchJobId = Database.executeBatch(new MyBatch());
System.abortJob(batchJobId);

40. Can you call Future Methods from Batch classes?

Future Methods are designed for different use cases and cannot be called from Batch Apex. For callouts, use Database.AllowsCallouts interface instead.

Aggregate Queries and Special Cases

41. Can you use aggregate queries in Batch Apex?

Aggregate queries don’t support queryMore(), so they cannot be used with Database.QueryLocator. The error message states: “Aggregate query does not support queryMore(), use LIMIT to restrict the results to a single batch.”

42. What’s the difference between Database.Batchable and Database.BatchableContext?

  • Database.Batchable: The interface your class implements to define it as a batch job
  • Database.BatchableContext: A context variable passed to methods containing runtime information like the job ID

43. What happens if you rename the execute method?

The class won’t compile. You’ll get: “Class must implement the method: void Database.Batchable<SObject>.execute(Database.BatchableContext, List<SObject>)”

44. Can you call a Future Method from a Batch job indirectly?

Yes, by calling a web service from the execute method, which then invokes the Future Method. This is a workaround since direct calls are not allowed.

45. What is BatchableContext and why do you need it?

Database.BatchableContext stores runtime information like the job ID, allowing you to track and monitor the batch job execution programmatically.

46. Can you define methods other than start, execute, and finish?

You can define helper methods, but the three interface methods (start, execute, finish) must be implemented.

47. Why are Batch classes declared as global?

The global access modifier makes the class accessible from anywhere, including managed packages and external code.

48. What’s the difference between insert and Database.insert?

  • insert: Throws an exception if any record fails; all records roll back
  • Database.insert: Allows partial success; returns results showing which records succeeded/failed

49. When should you use Database.Stateful?

Use Database.Stateful when you need to maintain state across batches, such as counting total records processed or accumulating values for final reporting.

50. Is the finish method asynchronous?

No, the finish method is synchronous. Only the execute method runs asynchronously in the job queue.

Future Methods Interview Questions (Questions 51-72)

Future Methods Fundamentals

51. What makes callouts possible from Batch Apex?

Implement Database.AllowsCallouts interface at the class level and perform callouts from the execute method (not start method, which would hit limits quickly).

52. Can you make callouts from the start method?

Technically yes, but it’s not recommended. The start method runs once for the entire job, making it unsuitable for bulk callouts. Use the execute method instead to distribute callouts across batches.

53. Can you call Queueable Apex from Batch Apex?

Yes, from the finish method. Queueable jobs can be enqueued after batch completion for additional processing.

54. Can you call one batch from another?

Yes, but only from the finish method to avoid governor limit violations.

55. How do you get records in a batch without querying?

Use an Iterable approach: Pass records from Batch A’s finish method to Batch B’s constructor, then return them via the Iterable interface in the start method.

56. How do you run a Future Method?

Annotate a static void method with @future:

@future
public static void processInFuture() {
    // Asynchronous logic here
}

57. What are primitive values and why must Future Methods accept only primitives?

Primitives (Integer, Boolean, String, etc.) are immutable and simple. SObjects can change between method invocation and execution, causing data inconsistencies. Pass record IDs instead and query fresh data inside the Future Method.

58. How do you call a Future Method?

Simply invoke it like any static method:

MyClass.processInFuture();

59. What are common use cases for Future Methods?

  1. Running code asynchronously in the background
  2. Avoiding mixed DML errors (setup vs. non-setup objects)
  3. Making web service callouts from triggers
  4. Performing long-running operations without blocking users

60. What are Future Method limitations?

  1. Cannot call one Future Method from another
  2. Only accept primitive parameters
  3. No guaranteed execution order
  4. Cannot return values

61. Write the syntax of a Future Method

global class FutureClass {
    @future
    public static void myFutureMethod() {
        // Asynchronous operations
    }
}

62. How do you pass SObjects to Future Methods?

You can’t pass SObjects directly. Instead, pass record IDs and query for current data inside the Future Method:

@future
public static void processRecords(List<Id> recordIds) {
    List<Account> accounts = [SELECT Id, Name FROM Account WHERE Id IN :recordIds];
    // Process accounts
}

63. How do you make callouts from Future Methods?

Add callout=true parameter:

@future(callout=true)
public static void makeCallout(String endpoint) {
    HttpRequest req = new HttpRequest();
    req.setEndpoint(endpoint);
    // Complete callout logic
}

64. Can you call Future Methods from triggers?

Yes, but add checks to prevent recursive calls and avoid hitting limits (50 future calls per transaction).

65. How do you avoid “Future method cannot be called from a future method” error?

Use System.isFuture() and System.isBatch() to check context before invoking:

if (!System.isFuture() && !System.isBatch()) {
    MyClass.futureMethod();
}

66. How many Future Methods can be defined in a class?

Unlimited. There’s no restriction on the number of Future Methods per class.

67. What’s the workaround for calling a Future Method from another Future Method?

Create a web service that contains the Future Method invocation, then call that web service.

68. How do Future Methods help avoid mixed DML errors?

Future Methods run in a separate transaction. Perform setup object DML (User, Profile) synchronously, then use a Future Method for non-setup object DML (Account, Contact).

public static void handleMixedDML() {
    // Synchronous: Insert Account
    insert new Account(Name='Test');
    
    // Asynchronous: Insert User
    createUserFuture('test@example.com');
}

@future
public static void createUserFuture(String email) {
    // Insert User
}

69. How do you trace Future Method execution?

Future Methods don’t return job IDs. Query AsyncApexJob using filters like MethodName or JobType:

List<AsyncApexJob> jobs = [
    SELECT Id, Status, MethodName 
    FROM AsyncApexJob 
    WHERE MethodName = 'futureMethod' 
    AND JobType = 'Future'
];

70. How do you test Future Methods?

Wrap the Future Method call in Test.startTest() and Test.stopTest():

@isTest
static void testFutureMethod() {
    Test.startTest();
    MyClass.futureMethod();
    Test.stopTest();
    // Verify results
}

71. Can you call Future Methods from Schedulable Apex?

Yes, Future Methods can be invoked from scheduled jobs.

72. Why are Future Methods static and void?

  • Static: You can call them without instantiating the class
  • Void: They run asynchronously in the future, so returning a value wouldn’t make sense for current execution context

Queueable Apex Interview Questions (Questions 73-100)

73. What advantages does Queueable Apex have over Future Methods?

Queueable Apex offers several improvements:

  • Non-primitive types: Can pass SObjects and custom Apex types
  • Monitoring: Returns a job ID for tracking via AsyncApexJob
  • Job chaining: Can chain jobs for sequential processing
  • Better structure: More organized with the Queueable interface
Id jobId = System.enqueueJob(new MyQueueableClass());
// Track progress
AsyncApexJob jobInfo = [
    SELECT Id, Status, NumberOfErrors 
    FROM AsyncApexJob 
    WHERE Id = :jobId
];

74. Which interface is used for Queueable Apex?

The Queueable interface.

75. What methods are required in Queueable Apex?

Only the execute(QueueableContext context) method is required.

76. How many jobs can you chain from a Queueable job?

You can add only one child job per parent job to avoid excessive nesting.

77. How many Queueable jobs can you enqueue in one transaction?

You can add up to 50 jobs to the queue using System.enqueueJob() in a single transaction.

78. How do you use the job ID to track a Queueable job?

Query the AsyncApexJob object:

AsyncApexJob jobInfo = [
    SELECT Status, NumberOfErrors 
    FROM AsyncApexJob 
    WHERE Id = :jobID
];

79. Can you make callouts from Queueable jobs?

Yes, implement the Database.AllowsCallouts interface:

public class MyQueueable implements Queueable, Database.AllowsCallouts {
    public void execute(QueueableContext context) {
        // Make HTTP callouts
    }
}

80. What happens if you call System.enqueueJob() multiple times?

After 50 calls in one transaction, you’ll get: “LimitException: Too many queueable jobs added to the queue: 51”

81. What are Queueable Apex limitations?

  • Maximum 50 jobs per transaction
  • Maximum chain depth of 5 (4 child jobs + 1 parent) in Developer/Trial orgs
  • Cannot chain Queueable jobs in test methods

82. Write a Queueable Apex blueprint

public class MyQueueableClass implements Queueable {
    private List<Id> recordIds;
    
    public MyQueueableClass(List<Id> ids) {
        this.recordIds = ids;
    }
    
    public void execute(QueueableContext context) {
        // Process records
        List<Account> accounts = [
            SELECT Id, Name 
            FROM Account 
            WHERE Id IN :recordIds
        ];
        // Update logic here
    }
}

83. What is QueueableContext?

An interface implemented internally by Apex that contains the job ID. Access it via context.getJobId():

public void execute(QueueableContext context) {
    Id jobId = context.getJobId();
}

84. How do you enqueue a Queueable job?

Id jobId = System.enqueueJob(new MyQueueableClass());

85. How do you process 200 records in batches of 100 using Queueable Apex?

Queueable Apex doesn’t support batch processing like Batch Apex. It processes all records in a single execution context. Consider using Batch Apex for true batching.

86. Can you chain a job with callouts from one without?

Yes, callouts are allowed in chained Queueable jobs.

87. How do you test Queueable chaining?

You cannot chain Queueable jobs in tests. Write separate test methods for each chained job and add Test.isRunningTest() checks:

public void execute(QueueableContext context) {
    // Process current job
    
    if (!Test.isRunningTest()) {
        System.enqueueJob(new NextQueueableJob());
    }
}

88-100. Additional Queueable Interview Questions

[Content continues with more advanced Queueable scenarios…]

Schedulable Apex Interview Questions (Questions 101-115)

101. What is Apex Scheduler?

The Apex Scheduler allows you to schedule Apex classes to run at specific times, ideal for daily or weekly maintenance tasks using Batch Apex.

102. Which interface is used for Schedulable Apex?

The Schedulable interface.

103. What method must Schedulable Apex implement?

The execute(SchedulableContext sc) method.

104. What parameters does System.Schedule accept?

Three parameters:

  1. Job name (String)
  2. CRON expression (String)
  3. Schedulable class instance
String jobName = 'Daily Account Update';
String cronExp = '0 0 0 * * ?'; // Midnight daily
MySchedulableClass instance = new MySchedulableClass();
String jobId = System.schedule(jobName, cronExp, instance);

105. How do you test Scheduled Apex?

Wrap the System.schedule() call in Test.startTest() and Test.stopTest():

@isTest
static void testScheduler() {
    Test.startTest();
    String jobId = System.schedule('Test Job', '0 0 0 * * ?', new MyScheduler());
    Test.stopTest();
    // Verify execution
}

106. What are Schedulable Apex governor limits?

  • Maximum 100 scheduled Apex jobs at one time
  • Maximum 250,000 scheduled Apex executions per 24 hours

107. Can you make callouts from Scheduled Apex?

Synchronous callouts are not supported from Scheduled Apex. Workarounds:

  1. Use @future(callout=true) method
  2. Execute a Batch Apex job (which supports callouts via Database.AllowsCallouts)

108. How do you monitor scheduled jobs?

Query the CronTrigger object:

CronTrigger job = [
    SELECT Id, CronJobDetail.Name, CronJobDetail.JobType, NextFireTime
    FROM CronTrigger 
    WHERE CronJobDetail.Name = 'Daily Account Update'
];

109. Example: Schedule a Batch Apex job

global class ScheduleBatchJob implements Schedulable {
    global void execute(SchedulableContext sc) {
        String soql = 'SELECT Id, Name FROM Account WHERE Active__c = true';
        AccountBatch batch = new AccountBatch(soql);
        Database.executeBatch(batch, 200);
    }
}

110. What does System.schedule() return?

It returns the CronTrigger job ID as a String:

String jobId = System.schedule('Merge Job', cronExp, schedulerInstance);

111. How do you get the count of scheduled jobs programmatically?

Query CronTrigger and CronJobDetail:

Integer count = [SELECT COUNT() FROM CronTrigger WHERE CronJobDetail.JobType = 'Apex'];

112. Can you update a class with active scheduled jobs via UI?

No, the Salesforce UI blocks updates. However, you can deploy updates using the Metadata API.

113. Does Scheduled Apex run in system mode?

Yes, Scheduled Apex executes in system mode – all classes run regardless of user permissions.

114. Workaround for callouts in Scheduled Apex

Call an @future(callout=true) method from the Scheduled Apex, or execute a Batch Apex job with Database.AllowsCallouts:

global class ScheduledCallout implements Schedulable {
    global void execute(SchedulableContext sc) {
        // Option 1: Future method
        MyClass.makeCalloutFuture();
        
        // Option 2: Batch with callouts
        Database.executeBatch(new CalloutBatch());
    }
}

115. Schedulable Apex limitations

  1. Maximum 100 scheduled jobs at once
  2. Maximum 250,000 executions per 24 hours
  3. No synchronous callouts allowed

Advanced Scenarios and Real-World Examples (Questions 116-150)

Handling Large-Scale Data Operations

116. How many callouts can you make from Batch Apex?

100 callouts per batch execution. Each execution of the execute method is a separate transaction with a 100-callout limit.

117. Scenario: You need to make 200 callouts in a Batch job

Solution: Track callouts and chain batch jobs:

global class CalloutBatch implements Database.Batchable<sObject>, Database.AllowsCallouts {
    private Integer calloutCount = 0;
    
    global void execute(Database.BatchableContext BC, List<SObject> scope) {
        for(SObject record : scope) {
            if(calloutCount < 100) {
                makeCallout(record);
                calloutCount++;
            }
        }
    }
    
    global void finish(Database.BatchableContext BC) {
        if([SELECT COUNT() FROM Account WHERE Status__c != 'Processed'] > 0) {
            Database.executeBatch(new CalloutBatch(), 100);
        }
    }
}

118. How do you pass parameters to Queueable Apex?

Use the constructor:

public class MyQueueable implements Queueable {
    private String recordId;
    private String message;
    
    public MyQueueable(String id, String msg) {
        this.recordId = id;
        this.message = msg;
    }
    
    public void execute(QueueableContext context) {
        Account acc = [SELECT Id FROM Account WHERE Id = :recordId];
        acc.Description = message;
        update acc;
    }
}

119. How do you pass parameters to Future Methods?

Pass primitive types only:

@future
public static void updateAccount(String accountId, String description) {
    Account acc = [SELECT Id FROM Account WHERE Id = :accountId];
    acc.Description = description;
    update acc;
}

120. How do you schedule a Queueable job?

Combine Schedulable Apex with Queueable:

public class ScheduleQueueable implements Schedulable {
    public void execute(SchedulableContext sc) {
        System.enqueueJob(new MyQueueableJob());
    }
}

// Schedule it
String cronExp = '0 0 2 * * ?'; // 2 AM daily
System.schedule('Nightly Queueable', cronExp, new ScheduleQueueable());

Real-World Scenario Questions

121. Scenario: Nightly synchronization of opportunities with external system (Marketo)

Solution: Use Scheduled Batch Apex

  1. Scheduler schedules the batch to run nightly
  2. Start Method: Query opportunities updated in last 24 hours
  3. Execute Method: Make callouts to Marketo for each batch
  4. Finish Method: Send summary email
global class OpportunitySyncBatch implements Database.Batchable<sObject>, Database.AllowsCallouts, Database.Stateful {
    global Integer successCount = 0;
    global Integer failCount = 0;
    
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([
            SELECT Id, Name, Amount, StageName 
            FROM Opportunity 
            WHERE LastModifiedDate = LAST_N_DAYS:1
        ]);
    }
    
    global void execute(Database.BatchableContext bc, List<Opportunity> scope) {
        for(Opportunity opp : scope) {
            try {
                syncToMarketo(opp);
                successCount++;
            } catch(Exception e) {
                failCount++;
            }
        }
    }
    
    global void finish(Database.BatchableContext bc) {
        sendSummaryEmail(successCount, failCount);
    }
}

Why not Data Loader?

  • Requires manual intervention
  • No automation capabilities
  • Limited error handling
  • Cannot make API callouts

122. When to use Batch Apex instead of Queueable Apex?

Use Batch Apex for:

  • Processing millions of records
  • Need to chunk data into manageable batches
  • Higher governor limits required

Use Queueable Apex for:

  • Near real-time processing
  • Smaller datasets
  • Need to pass complex objects
  • Require job chaining

123. Scenario: Real-time order synchronization with ShipStation

Solution: Use Queueable Apex triggered from Order trigger

trigger OrderTrigger on Order (after insert, after update) {
    for(Order ord : Trigger.new) {
        System.enqueueJob(new SyncOrderToShipStation(ord.Id));
    }
}

public class SyncOrderToShipStation implements Queueable, Database.AllowsCallouts {
    private Id orderId;
    
    public SyncOrderToShipStation(Id ordId) {
        this.orderId = ordId;
    }
    
    public void execute(QueueableContext context) {
        Order ord = [SELECT Id, OrderNumber, TotalAmount FROM Order WHERE Id = :orderId];
        // Make callout to ShipStation
        syncToShipStation(ord);
    }
}

Why Queueable over Batch/Future?

  • Near real-time processing (immediately after order creation)
  • Can pass complex objects
  • Better monitoring than Future Methods
  • Supports job chaining for multi-step processes

124. Database.QueryLocator vs Iterable

Database.QueryLocator:

  • Processes up to 50 million records
  • Uses SOQL queries
  • Ideal for Salesforce data
global Database.QueryLocator start(Database.BatchableContext bc) {
    return Database.getQueryLocator('SELECT Id, Name FROM Account');
}

Iterable:

  • Processes up to 50,000 records
  • More flexible for external data sources
  • Custom logic for data retrieval
global Iterable<Account> start(Database.BatchableContext bc) {
    List<Account> accounts = getAccountsFromExternalSystem();
    return accounts;
}

125. How do you schedule a Batch Apex job?

Two methods:

Method 1: System.scheduleBatch()

String cronExp = '0 0 1 * * ?'; // 1 AM daily
MyBatchClass batch = new MyBatchClass();
System.scheduleBatch(batch, 'Nightly Batch Job', 60); // 60-minute delay

Method 2: Schedulable Apex + Database.executeBatch()

global class ScheduleBatch implements Schedulable {
    global void execute(SchedulableContext sc) {
        Database.executeBatch(new MyBatchClass(), 200);
    }
}
System.schedule('Daily Batch', '0 0 1 * * ?', new ScheduleBatch());

Governor Limits in Detail

126. What are complete governor limits for Batch Apex?

  • Batch jobs in Apex Flex Queue: 100
  • Active/Queued batch jobs: 5
  • Records per batch execution: 50,000
  • Maximum batch size: 2,000
  • Default batch size: 200
  • Callouts per transaction: 100
  • Transaction time limit: 60 seconds
  • SOQL queries: 200
  • Total records by SOQL: 50 million

127. Real-world use cases for Batch Apex

  1. Data Synchronization: Sync with Marketo, SAP, or other systems
  2. Data Cleanup: Archive old records, remove duplicates
  3. Mass Updates: Update millions of records across objects
  4. Complex Calculations: Recalculate field values based on business logic
  5. Data Migration: Move data between orgs or systems

128. Can you reorder batch jobs in the Apex Flex Queue?

Yes, but only jobs with “Holding” status. Use:

System.FlexQueue.moveBeforeJob(jobToMove, targetJob);

Or reorder via the Apex Flex Queue interface in Setup.

129. What is Database.RaisesPlatformEvents?

This interface allows Batch Apex to publish Platform Events during execution:

global class EventBatch implements Database.Batchable<sObject>, Database.RaisesPlatformEvents {
    global void execute(Database.BatchableContext bc, List<SObject> scope) {
        // Process records and publish events
        EventBus.publish(new My_Event__e(Status__c = 'Processed'));
    }
}

130. What is the significance of the scope parameter?

The scope parameter defines how many records are passed to the execute method at once. It helps manage governor limits by breaking large datasets into manageable chunks (maximum 2,000 records).

Error Handling in Asynchronous Apex

131. How do you handle errors in Batch Apex?

Use try-catch blocks and track results:

global void execute(Database.BatchableContext bc, List<Account> scope) {
    List<Database.SaveResult> results = Database.update(scope, false);
    
    for(Integer i = 0; i < results.size(); i++) {
        if(!results[i].isSuccess()) {
            // Log error
            System.debug('Error on record: ' + scope[i].Id);
            for(Database.Error err : results[i].getErrors()) {
                System.debug('Error: ' + err.getMessage());
            }
        }
    }
}

132. Can you call Schedulable Apex from Future Methods?

Yes, you can schedule up to 100 jobs from a Future Method.

133. What happens if you exceed 50 future method calls?

Salesforce throws: “System.LimitException: Too many future calls: 51”

134. Can you call Batch Apex from Future Methods?

No, Database.executeBatch() cannot be called from Future Methods due to restrictions on mixing asynchronous operations.

135. Can you call Queueable from Future Methods?

Yes, but limited to one enqueueJob call per future method.

Advanced Mixed DML and Data Integrity

136. Handling mixed DML errors with Future Methods

public class MixedDMLHandler {
    public static void createUserAndAccount() {
        // Insert non-setup object first
        Account acc = new Account(Name='Test Account');
        insert acc;
        
        // Use Future Method for setup object
        createUserFuture('test@example.com', 'Test', 'User');
    }
    
    @future
    public static void createUserFuture(String email, String firstName, String lastName) {
        Profile p = [SELECT Id FROM Profile WHERE Name='Standard User' LIMIT 1];
        User u = new User(
            Email = email,
            FirstName = firstName,
            LastName = lastName,
            ProfileId = p.Id,
            Username = email,
            Alias = firstName.substring(0,5),
            TimeZoneSidKey = 'America/New_York',
            LocaleSidKey = 'en_US',
            EmailEncodingKey = 'UTF-8',
            LanguageLocaleKey = 'en_US'
        );
        insert u;
    }
}

137. Data migration scenario: 10 million records from legacy system

global class DataMigrationBatch implements Database.Batchable<sObject>, Database.Stateful {
    global Integer totalProcessed = 0;
    global Integer totalErrors = 0;
    
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator([
            SELECT Id, Name, LegacyId__c 
            FROM Account 
            WHERE LegacyId__c != null
        ]);
    }
    
    global void execute(Database.BatchableContext bc, List<Account> scope) {
        // Data cleansing and transformation
        for(Account acc : scope) {
            acc.Name = cleanseData(acc.Name);
            acc.Industry = transformIndustry(acc.Industry);
        }
        
        Database.SaveResult[] results = Database.update(scope, false);
        
        for(Database.SaveResult sr : results) {
            if(sr.isSuccess()) {
                totalProcessed++;
            } else {
                totalErrors++;
            }
        }
    }
    
    global void finish(Database.BatchableContext bc) {
        sendMigrationReport(totalProcessed, totalErrors);
    }
    
    private String cleanseData(String data) {
        // Cleansing logic
        return data;
    }
    
    private String transformIndustry(String industry) {
        // Transformation logic
        return industry;
    }
}

138. Sequential processing with Queueable chaining

Scenario: Calculate commissions → Update records → Send notifications

public class CalculateCommissionJob implements Queueable {
    public void execute(QueueableContext context) {
        // Calculate commissions
        List<SalesRep__c> reps = [SELECT Id, Sales__c FROM SalesRep__c];
        for(SalesRep__c rep : reps) {
            rep.Commission__c = rep.Sales__c * 0.10;
        }
        update reps;
        
        // Chain next job
        System.enqueueJob(new SendNotificationJob());
    }
}

public class SendNotificationJob implements Queueable {
    public void execute(QueueableContext context) {
        // Send notifications
        List<SalesRep__c> reps = [SELECT Id, Email__c, Commission__c FROM SalesRep__c];
        for(SalesRep__c rep : reps) {
            sendCommissionEmail(rep);
        }
    }
}

139. Weekly campaign performance report

global class WeeklyCampaignReport implements Schedulable {
    global void execute(SchedulableContext sc) {
        // Query campaign data
        List<Campaign> campaigns = [
            SELECT Id, Name, NumberOfLeads, NumberOfConvertedLeads,
                   ExpectedRevenue, ActualCost
            FROM Campaign
            WHERE CreatedDate = LAST_N_DAYS:7
        ];
        
        // Generate report
        String report = generateReport(campaigns);
        
        // Send email
        Messaging.SingleEmailMessage email = new Messaging.SingleEmailMessage();
        email.setToAddresses(new String[]{'marketing@company.com'});
        email.setSubject('Weekly Campaign Performance Report');
        email.setPlainTextBody(report);
        Messaging.sendEmail(new Messaging.SingleEmailMessage[]{email});
    }
    
    private String generateReport(List<Campaign> campaigns) {
        // Report generation logic
        return 'Report content';
    }
}

// Schedule it
System.schedule('Weekly Campaign Report', '0 0 8 ? * MON', new WeeklyCampaignReport());

140. Multi-step data processing with Queueable chaining

public class ValidateDataJob implements Queueable {
    private List<Id> recordIds;
    
    public ValidateDataJob(List<Id> ids) {
        this.recordIds = ids;
    }
    
    public void execute(QueueableContext context) {
        // Validation logic
        List<Customer__c> customers = [SELECT Id, Email__c, Phone__c FROM Customer__c WHERE Id IN :recordIds];
        
        for(Customer__c cust : customers) {
            if(!isValidEmail(cust.Email__c)) {
                cust.Email__c = '';
            }
        }
        update customers;
        
        // Chain score calculation
        System.enqueueJob(new CalculateScoreJob(recordIds));
    }
}

public class CalculateScoreJob implements Queueable {
    private List<Id> recordIds;
    
    public CalculateScoreJob(List<Id> ids) {
        this.recordIds = ids;
    }
    
    public void execute(QueueableContext context) {
        // Score calculation
        List<Customer__c> customers = [SELECT Id, PurchaseHistory__c FROM Customer__c WHERE Id IN :recordIds];
        
        for(Customer__c cust : customers) {
            cust.Score__c = calculateScore(cust);
        }
        update customers;
        
        // Chain notification
        System.enqueueJob(new SendNotificationJob(recordIds));
    }
}

141-150. Additional Advanced Topics

These questions cover topics like:

  • Platform Events integration
  • Complex error handling strategies
  • Performance optimization techniques
  • Best practices for production deployments
  • Monitoring and debugging asynchronous processes
  • Integration patterns with external systems

Prepare for Your Salesforce Platform Developer 1 Certification

Master Asynchronous Apex and More with My Comprehensive Course

Ready to take your Salesforce development skills to the next level? While these 150+ interview questions provide solid preparation, mastering Asynchronous Apex requires hands-on practice and comprehensive understanding.

Introducing: Salesforce Certified Platform Developer I Course (LWC & Aura)

Enroll in the Platform Developer 1 Course Now

Quick Reference: Choosing the Right Asynchronous Method

Requirement Recommended Method
Process millions of records Batch Apex
Simple background processing Future Methods
Complex chaining logic Queueable Apex
Scheduled tasks Schedulable Apex
Real-time processing Queueable Apex
Make callouts from triggers Future Methods or Queueable
Avoid mixed DML Future Methods
Pass complex objects Queueable Apex
Need job monitoring Queueable or Batch Apex

Key Takeaways

  1. Batch Apex is ideal for processing large data volumes (up to 50 million records)
  2. Future Methods handle simple asynchronous tasks and avoid mixed DML errors
  3. Queueable Apex offers flexibility with complex object passing and job chaining
  4. Schedulable Apex automates recurring tasks on a set schedule
  5. Understanding governor limits is crucial for all asynchronous methods
  6. Each method has specific use cases – choose based on your requirements

Additional Resources

Official Salesforce Documentation

Recommended Learning Path

  1. Complete the Platform Developer 1 Course
  2. Practice with Trailhead modules on Asynchronous Apex
  3. Build personal projects implementing each asynchronous method
  4. Take practice exams
  5. Schedule your certification exam

Conclusion

Mastering Asynchronous Apex is essential for every Salesforce Developer. Whether you’re preparing for interviews, working toward your Platform Developer 1 certification, or building enterprise Salesforce applications, understanding these concepts deeply will set you apart.

These 150+ interview questions cover everything from basics to advanced scenarios. Review them regularly, practice coding examples, and most importantly, gain hands-on experience by building real applications.

Ready to accelerate your Salesforce career?

Enroll in the Complete Platform Developer 1 Course and master Asynchronous Apex with expert guidance.

About the Author

This comprehensive guide is designed to help Salesforce developers at all levels master Asynchronous Apex. Whether you’re just starting your Salesforce journey or preparing for advanced certifications, these interview questions will prepare you for real-world development challenges.

FAQ Section

Q: How long does it take to master Asynchronous Apex? A: With focused study and practice, you can become proficient in 4-6 weeks. The Platform Developer 1 course provides structured learning to accelerate this timeline.

Q: What’s the most commonly asked Asynchronous Apex interview question? A: Questions about when to use Batch Apex vs. Queueable Apex and how to avoid governor limits are extremely common.

Q: Can I use these concepts in real projects immediately? A: Absolutely! Start with simple Future Methods, then progress to Queueable and Batch Apex as complexity increases.

Q: Is the Platform Developer 1 certification worth it? A: Yes! It’s a valuable credential that demonstrates your Apex programming skills and opens doors to better opportunities and higher salaries.

Q: How often are asynchronous methods used in production? A: Very frequently! Almost every enterprise Salesforce org uses Batch Apex for data processing and Queueable/Future methods for integrations.

Ready to become a Salesforce Asynchronous Apex expert? Start your journey today!

Share:

Recent Posts