1. What is the Trigger Handler design pattern, and why is it considered a best practice at scale?
It centralizes all trigger logic into a single handler class per object, with the trigger itself only routing to context-specific methods (beforeInsert, afterUpdate, etc.). At scale, this avoids logic scattered across multiple triggers, makes unit testing easier since handler methods can be tested independently of a live trigger context, and gives one place to control execution order and recursion.
2. What is the Selector pattern in Apex, and what problem does it solve?
The Selector pattern centralizes all SOQL queries for a given object into a dedicated “selector” class, instead of scattering the same or similar queries across multiple classes. This avoids duplicated query logic, makes it easy to enforce field-level security and sharing consistently, and simplifies future query changes to a single place.
public class AccountSelector {
public static List<Account> getActiveAccounts() {
return [SELECT Id, Name FROM Account WHERE Active__c = true WITH SECURITY_ENFORCED];
}
}3. What is the Service Layer pattern in Apex?
A Service Layer class groups related business logic for a specific domain (e.g., OpportunityService) behind clear, well-named public methods, so that triggers, LWCs, and batch jobs all call the same central logic rather than duplicating business rules across multiple entry points.
4. What is dependency injection, and is it commonly used in Apex?
Dependency injection means providing a class with its dependencies (like a selector or service instance) from the outside rather than instantiating them internally, which makes unit testing easier through mocking. It’s less common in vanilla Apex than in languages like Java, but frameworks like fflib and Apex frameworks using the Application factory pattern implement it for more testable, decoupled code.
5. What is the Unit of Work pattern, and why is it useful in Apex?
The Unit of Work pattern batches multiple related DML operations (inserts, updates across different objects) into a single, coordinated commit, tracking the relationships between records so they’re all registered before one final “commit” call executes the DML in the correct dependency order. It reduces the risk of hitting DML statement limits and keeps complex multi-object operations transactionally consistent.
6. What is the difference between a REST callout and a SOAP callout in Apex?
A REST callout uses the Http, HttpRequest, and HttpResponse classes to send/receive typically JSON-based requests over standard HTTP verbs (GET, POST, PUT, DELETE). A SOAP callout uses a WSDL-generated Apex class (via Salesforce’s “Generate from WSDL” tool) to call a SOAP-based web service using strongly-typed method calls that mirror the WSDL’s operations.
7. How do you make a basic REST callout in Apex?
You construct an HttpRequest with an endpoint and method, send it via an Http instance, and inspect the returned HttpResponse:
HttpRequest req = new HttpRequest();
req.setEndpoint('https://api.example.com/data');
req.setMethod('GET');
req.setHeader('Authorization', 'Bearer ' + accessToken);
Http http = new Http();
HttpResponse res = http.send(req);
if (res.getStatusCode() == 200) {
Map<String, Object> result = (Map<String, Object>) JSON.deserializeUntyped(res.getBody());
}8. What is a Named Credential, and why is it preferred over hardcoding endpoint URLs and credentials?
A Named Credential stores an external system’s endpoint URL and authentication details securely at the org level, so Apex code references it by name instead of hardcoding sensitive values like API keys or passwords directly in code. This improves security, makes credentials easy to rotate without a code deployment, and centralizes authentication handling (including OAuth flows) outside of Apex logic.
9. What is a Remote Site Setting, and when is it required?
A Remote Site Setting whitelists an external domain that Apex is allowed to make callouts to; without registering the domain (or using a Named Credential, which handles this automatically), any callout to an unregistered endpoint throws an UnauthorizedEndpointException.
10. How do you handle a callout timeout gracefully in Apex?
You set a timeout explicitly on the HttpRequest (setTimeout(), in milliseconds, up to a max of 120,000ms) and wrap the callout in a try-catch to catch a CalloutException, allowing you to retry, log the failure, or notify the user instead of letting the transaction fail with an unhandled error.
req.setTimeout(10000);
try {
HttpResponse res = http.send(req);
} catch (CalloutException e) {
System.debug('Callout failed: ' + e.getMessage());
}11. What causes a “Too many SOQL queries” error in a complex, multi-trigger scenario, and how do you debug it?
This typically happens when multiple triggers or workflow-driven updates on related objects cascade into each other within the same transaction, each independently issuing SOQL queries that accumulate against the shared 100-query limit. Debugging usually involves checking debug logs for the query count at various points (via the Limits class) and consolidating queries into selector methods called once and reused across the transaction.
12. A batch job is processing millions of records but keeps timing out or hitting heap limits — what would you check first?
First, check whether the execute() method is doing unnecessary work per batch, like re-querying related data inside a loop instead of bulk-querying it once per batch. Also check the batch size (Database.executeBatch()’s second parameter) — reducing it can lower heap usage per execution, and verify the start() method’s QueryLocator isn’t selecting more fields than needed.
13. How would you design a system where multiple integrations update the same Salesforce object without triggers overwriting each other’s changes?
A common approach is to centralize all incoming update logic through a single Apex service layer (rather than separate trigger paths per integration), using the trigger handler pattern to control execution order, along with careful use of Trigger.isUpdate checks and field-level comparisons to avoid unnecessary re-processing or overwriting fields set by a different integration in the same transaction.
14. What would you do if a trigger update in a Batch Apex job causes a “field is not writeable” security error for some users?
This usually indicates the batch is running in a system context without appropriate field-level security enforcement, or the running user in a scheduled context lacks edit access to a specific field. You’d check whether Security.stripInaccessible() or explicit FLS checks are needed, or whether the batch class should run under a more appropriate user context via System.runAs() in tests, and review the actual running user’s permission set in production.
15. How do you optimize a SOQL query that’s slow on a large object with millions of records?
Ensure the WHERE clause filters on indexed fields (standard indexed fields, external IDs, or custom fields marked for indexing via a support case), avoid LIKE '%value%' patterns which can’t use an index efficiently, use selective filters to keep the query below the “non-selective query” threshold, and consider using LIMIT combined with pagination if only a subset of records is actually needed.
16. What is the difference between a selective and non-selective SOQL query?
A selective query filters using indexed fields and returns a small percentage of the total records in the object, allowing Salesforce’s query optimizer to use an index efficiently. A non-selective query — often one filtering on unindexed fields or using leading wildcards — forces a full table scan internally, which becomes increasingly slow as the object’s record count grows into the millions.
17. How would you design Apex code to safely handle a scenario where an external system sends duplicate webhook callouts?
You’d implement idempotency — for example, by having the external system pass a unique transaction/request Id, storing recently processed Ids (in a custom object or platform cache), and checking for that Id before processing a new payload, so a duplicate callout doesn’t create duplicate records or apply the same update twice.
18. What is Platform Cache, and how might it help in a high-volume integration scenario?
Platform Cache stores frequently accessed data in a fast, temporary, org-wide or session-based cache, reducing repeated SOQL queries for data that doesn’t change often (like configuration settings or reference data). In a high-volume integration, it can reduce query counts and improve performance by avoiding redundant lookups within and across transactions.
19. In an interview, how would you answer “How do you handle governor limit exceptions gracefully in production”?
A strong answer covers proactive prevention (bulkifying code, using selectors, monitoring query/DML counts via the Limits class during development) combined with reactive handling — wrapping risky operations in try-catch where feasible, logging detailed context when a LimitException does occur (since it can’t always be caught cleanly), and using Batch Apex or Queueable chaining to break up large operations before they approach a limit in the first place.
20. A hiring manager asks you to describe a real production issue you solved involving Apex — what should a strong answer include?
A strong answer names the specific symptom (e.g., an intermittent UNABLE_TO_LOCK_ROW error or a SOQL 101 limit failure under bulk load), explains the root cause you identified (e.g., DML inside a loop, or two processes updating the same parent record concurrently), describes the concrete fix (bulkifying the trigger, adding FOR UPDATE locking, or restructuring the batch size), and mentions how you verified the fix held up under a realistic data volume test — not just that it passed a single test case.