Fix "Apex CPU Time Limit Exceeded" in Salesforce

By Prit Sakhvala, Salesforce Developer · Updated July 2026

"Apex CPU time limit exceeded" means your transaction used more than 10 seconds of CPU (60 seconds for async). Database time doesn't count — the culprit is computation: loops over large collections, nested trigger/Flow recursion, or inefficient code in triggers and managed packages. Find the hotspot in the debug log, then bulkify, cache with maps, or move work async.

What counts toward CPU time — and what doesn't

Counts toward CPUDoes NOT count
Apex statement execution (loops, string/JSON processing, math)SOQL query execution time (database)
Trigger logic — yours and managed packages'DML database time
Flow element execution, formulas, validation rules, workflowHTTP callout wait time
Declarative automation triggered by your DMLTime spent waiting on locks

This is why the error is confusing: the visible slow part of a transaction (a big query) is often free, while an innocent-looking loop is what burns the budget.

The usual suspects

  1. Loops over loops. Nested iteration over related records (O(n²) comparisons) is the single most common cause. 200 trigger records × 1,000 comparisons each is 200,000 iterations before you've done anything useful.
  2. Trigger recursion. An update trigger that performs updates re-fires automation. Two or three re-entries multiply all trigger CPU.
  3. Non-bulkified helper methods called once per record instead of once per batch.
  4. Record-triggered Flows stacking on triggers. Each Flow element costs CPU; a loop inside a Flow over hundreds of records adds up fast.
  5. Heavy string/JSON processing — serializing large payloads, regex over long text, building huge strings by concatenation.
  6. Managed package automation you can't see — but which absolutely bills to your transaction's CPU.

Finding the hotspot in the debug log

Every log line carries a nanosecond elapsed counter, e.g. (5348351). The manual method:

14:23:07.1 (120000000)|CODE_UNIT_STARTED|[EXTERNAL]|OpportunityTrigger on Opportunity trigger event AfterUpdate 14:23:09.8 (2830000000)|CODE_UNIT_FINISHED|OpportunityTrigger on Opportunity trigger event AfterUpdate

2,830,000,000 − 120,000,000 = 2.71 s wall time in that trigger. Do this for every CODE_UNIT pair, rank them, then drill into the worst one. Also check the summary at the end of the log:

LIMIT_USAGE_FOR_NS|(default)| Maximum CPU time: 9840 out of 10000 ******* CLOSE TO LIMIT

Doing this by hand across a 50,000-line log is exactly the tedium a debug log analyzer removes. ForceLens's Performance tab ranks code units by time consumed, its Timeline shows where the transaction's time physically went, and the Limits tab shows CPU consumption against the 10 s budget — parsed from the same log, in one click.

ForceLens Performance tab showing CPU time breakdown per code unit from a Salesforce debug log

Fixes that actually work

Frequently asked questions

What is the Apex CPU time limit in Salesforce?

10,000 ms (10 seconds) per synchronous transaction; 60,000 ms for asynchronous (batch, future, queueable). Exceeding it throws an uncatchable limit exception and rolls back the transaction. Full list: governor limits explained.

What does NOT count toward CPU time?

Database time: SOQL execution, DML database operations, and callout wait time are excluded. Computation — Apex statements, trigger and Flow logic, validation, managed package code — is what counts.

How do I find what's consuming CPU in a debug log?

Diff the elapsed-time counters between CODE_UNIT_STARTED/FINISHED pairs and check LIMIT_USAGE_FOR_NS at the end of the log — or let ForceLens's Performance and Timeline tabs compute the ranking automatically.

Can I catch the CPU limit exception in try/catch?

No. System.LimitException is uncatchable. Prevention — bulkification, recursion control, async offloading — is the only fix.

Find your CPU hotspot in seconds

Open the failing transaction's log in ForceLens and the Performance tab ranks every code unit by time consumed — free, local, no setup.

Add ForceLens to Chrome — Free