Fix "Apex Heap Size Too Large" in Salesforce
"Apex heap size too large" means your transaction held more than 6 MB of data in memory (12 MB async). The heap is everything your variables reference — query results, collections, strings, JSON, Blobs. The fix is holding less at once: SOQL for-loops, leaner field lists, chunked processing, or Batch Apex.
What the heap actually is
Every object your Apex code creates or references during a transaction lives on the heap: sObject lists from queries, maps you build, strings you concatenate, deserialized JSON structures, Blob contents. When the total exceeds the limit, Salesforce throws System.LimitException: Apex heap size too large — which, like all limit exceptions, cannot be caught.
Heap is shared across all namespaces in the transaction (like CPU time), so managed package allocations count against you too. See the full picture in governor limits explained.
The usual suspects
- Materializing big query results.
List<Account> all = [SELECT ... FROM Account]on a large object loads every record and field into memory at once. - Querying fields you don't use — especially long text areas and rich text fields, which can be 100 KB+ per record.
- String concatenation in loops. Each
s += chunkcreates a new string; building CSVs or HTML this way multiplies memory. - JSON of large payloads.
JSON.serialize/deserializeof big structures temporarily doubles the data (source + result both on heap). - Blobs and attachments. Reading file bodies into Apex is the fastest way to blow 6 MB.
- Collections that never shrink — accumulating results across iterations instead of processing and clearing.
Finding heap hotspots in the debug log
Three techniques, cheapest first:
1. The limits summary
LIMIT_USAGE_FOR_NS|(default)|
Maximum heap size: 5892411 out of 6000000 ******* CLOSE TO LIMIT
Confirms heap is the problem and how close you are. ForceLens's Limits tab shows this as a progress bar the moment the log opens.
2. Checkpoint logging
System.debug('Heap after query: ' + Limits.getHeapSize() + ' / ' + Limits.getLimitHeapSize());
// ... suspect operation ...
System.debug('Heap after transform: ' + Limits.getHeapSize());
Bracket suspect operations with these and read the USER_DEBUG lines — the jump between checkpoints is your hotspot.
3. HEAP_ALLOCATE events
With ApexCode at FINEST, the log emits HEAP_ALLOCATE events with byte counts and line numbers. Extremely detailed but extremely verbose — combine with a class-scoped trace flag (see debug log levels) to keep the log under the 20 MB cap.
Fixes that work
- SOQL for-loops.
for (Account a : [SELECT Id, Name FROM Account WHERE ...]) { ... }processes records in 200-record batches internally instead of holding the full list. The single biggest heap fix. - Query only needed fields. Drop unused columns, especially long text areas.
- Batch Apex for volume. Each
execute()gets a fresh transaction, a fresh heap, and the 12 MB async budget. - Stream, don't accumulate. Process each chunk and let it go out of scope; call
list.clear()on working collections; set large variables tonullwhen done. - Careful with JSON. Deserialize into typed classes containing only fields you need, not
Map<String, Object>of the whole payload. - Keep file bodies out of Apex. Where possible, work with ContentVersion IDs and links rather than reading Blob bodies.
- Visualforce note: mark controller variables you don't need across postbacks as
transientto keep them out of the serialized view state.
Frequently asked questions
What is the Apex heap size limit?
6 MB per synchronous transaction, 12 MB for asynchronous (batch, future, queueable). Exceeding it throws an uncatchable limit exception.
What fills up the heap?
Query results held in lists, big strings, JSON serialization of large payloads, Blob/file bodies, and ever-growing collections — including allocations made by managed packages in your transaction.
How do I check heap usage?
Limits.getHeapSize() checkpoints logged with System.debug; the "Maximum heap size" line in LIMIT_USAGE_FOR_NS; and HEAP_ALLOCATE events at ApexCode FINEST.
How do I fix heap errors from large queries?
Use SOQL for-loops so records process in chunks, query fewer fields, or move to Batch Apex where each chunk gets a fresh 12 MB heap.
Spot heap pressure instantly
Open the log in ForceLens — the Limits tab shows heap against its budget as a progress bar, next to CPU, SOQL and DML. Free and local.