Skip to main content

Salesforce Apex Debugging: Interactive Debugger, Breakpoints, & Log Inspection

In plain words: Debugging in Salesforce means pausing your running Apex code at specific lines (breakpoints) or reading execution history (debug logs) to inspect variables, find logic errors, and fix bugs without guessing.

Diagnosing unexpected errors, null pointer exceptions, and governor limit spikes in Apex requires structured troubleshooting tools. Salesforce equips developers with both interactive debugging (stepping through code in real time) and historical log analysis (tracing execution events after runtime). Understanding how to configure these tools speeds up development and improves software quality.

1. Understanding Interactive Debugging vs. Debug Logs

Salesforce provides two primary approaches to investigate Apex execution:

  • Apex Debugger (Interactive): Allows you to pause live execution in sandbox or scratch org environments, step through lines of code, inspect in-memory call stacks, and evaluate variable values dynamically.
  • Apex Replay Debugger & Debug Logs: A free, log-based alternative that records transaction logs on the Salesforce platform and allows you to "replay" the execution step-by-step locally within modern IDEs like VS Code.

2. Setting Breakpoints & Stepping Through Execution

Breakpoints instruct the execution engine to pause before running a specific line of code. Once paused, you can inspect the current state and step through execution using standard debugging commands:

  • Step Into (F5): Advances to the next line of code, entering inside method calls or helper classes to inspect nested logic.
  • Step Over (F6): Executes the current line of code and moves to the next line in the same method without stepping into internal method implementations.
  • Step Out (F7): Completes execution of the active method and returns control to the calling method.
  • Continue / Resume (F8): Resumes uninterrupted code execution until the program reaches the next active breakpoint or finishes the transaction.
Real-World Example: Inspecting Variables in a Batch or Service Layer
Placing a breakpoint inside business logic to verify collection state before performing DML:
public with sharing class OpportunityService {
    public static void applyDiscount(List<Opportunity> oppList) {
        for (Opportunity opp : oppList) {
            // SET BREAKPOINT ON LINE BELOW:
            Decimal discountFactor = calculateFactor(opp.Amount);
            
            if (discountFactor > 0) {
                opp.Amount = opp.Amount - (opp.Amount * discountFactor);
            }
        }
        update oppList;
    }

    private static Decimal calculateFactor(Decimal amount) {
        if (amount == null || amount <= 0) {
            return 0;
        }
        return amount > 100000 ? 0.15 : 0.05;
    }
}
360 Debugging Toolkit Card:
  • Developer Console: Built-in browser tool best suited for quick Anonymous Apex execution and viewing raw text logs.
  • VS Code + Salesforce Extension Pack: Industry standard for Apex Replay Debugger, setting conditional breakpoints, and local source tracking.
  • Debug Log Retention: Salesforce retains debug logs for up to 24 hours, storing up to 1,000 MB per org.
  • Log File Cap: Individual debug logs are capped at 20 MB. Logs exceeding this size are truncated.

3. Capturing and Analyzing Apex Debug Logs

When interactive debugging is not feasible—such as troubleshooting production issues or analyzing asynchronous batch jobs—debug logs provide the complete execution trail.

  • Configure Trace Flags: Navigate to Setup > Debug Logs and create a Trace Flag for your automated process, specific user, or Apex class.
  • Select Granular Log Levels: Adjust categories such as Apex Code, Database, Callouts, and Validation from NONE to FINEST depending on the depth of diagnostics required.
  • Analyze Execution Flow: Search for critical events like USER_DEBUG, SOQL_EXECUTE_BEGIN, DML_BEGIN, and LIMIT_USAGE to spot performance bottlenecks.

4. Common Traps & Debugging Best Practices

Developer Trap: Excessive Logging and Log Truncation
Setting log filters to FINEST on large batch processes or trigger loops can quickly trigger Log Truncation (the 20 MB per-file limit). When a log is truncated, critical failure points and stack traces at the end of the transaction are lost. Set logging levels to INFO or DEBUG for general monitoring.
Core Rule: Never rely solely on System.debug() strings in production code. Use the Apex Replay Debugger with VS Code to inspect the complete variable state without polluting code with temporary log statements.
  • Always Debug in Sandboxes: Never run invasive debugging sessions, test transactions, or data rollbacks directly in a production organization.
  • Use Structured Debug Levels: Structure custom logging with specific log levels (e.g., System.debug(LoggingLevel.ERROR, ...)) so you can filter out noise during log reviews.
  • Clean Up Trace Flags: Remove active trace flags after resolving issues to preserve org log storage and avoid hitting daily log generation caps.

Summary

Effective debugging is essential for maintaining resilient Salesforce applications. By combining the interactive inspection of the Apex Debugger and Replay Debugger with targeted trace flags and structured debug logs, developers can isolate bugs quickly, optimize performance, and keep custom business logic running smoothly.