Apex heap limit differences between synchronous and asynchronous transactions
0 reputation · 19 Mar 2022, 16:45 UTC
0 reputation · 19 Mar 2022, 16:45 UTC
A design is being evaluated for bulk processing that keeps data in memory during an Apex transaction. The documented capability is the Apex heap size governor limit, which caps in-memory data per transaction and is enforced separately for synchronous and asynchronous contexts. Heap usage is measured per transaction and includes variables, collections and deserialized sObjects, with memory reclaimed only at transaction end and no developer-exposed compaction or garbage collection control.
There is uncertainty about exact current limits and how heap is accounted for with large collections and JSON deserialization. Platform Cache and external data access do not directly increase Apex heap, but data retrieved into Apex variables does count toward the limit. Static variables are scoped per transaction and do not persist heap across invocations.
What is the documented heap size limit for synchronous Apex versus asynchronous Apex such as Queueable and Batch execute in the current release? How is heap accounted for when a large JSON payload is deserialized into a List of sObjects held for the duration of the transaction? Does retrieving data from Platform Cache increase Apex heap only when the data is copied into Apex variables?
34775 reputation · 20 Mar 2022, 02:57 UTC
Confirmed facts (from Salesforce Governor Limits):
When a JSON payload is deserialized into a List<sObject>, the memory used by the list elements, their fields, and the internal overhead of the list and objects all count toward the heap limit. The limit is checked after the deserialization completes; if the total exceeds the transaction’s heap limit, a System.LimitException is thrown.
Retrieving a value from Platform Cache does not consume heap until the cached value is assigned to an Apex variable (e.g., String cached = Cache.Org.get('key');). At that point the variable’s contents are added to the heap usage.
System.debug('Heap used: '+ Limits.getHeapSize() +' bytes');
System.debug('Heap limit: '+ Limits.getLimitHeapSize() +' bytes');
execute method to see the per‑chunk limit reset.If you encounter unexpected limit exceptions, please share the heap size logged via Limits.getHeapSize() at the point of failure so we can confirm whether the limit was exceeded.
Use comments to ask for clarification. Post a solution as an answer.
34,775 reputation · 20 Mar 2022, 01:11 UTC
One nuance often missed is that the Apex heap limit counts the actual memory allocated for collections, which includes the internal backing array’s capacity, not just the number of elements you have added. For example, a List<sObject> initialized with new List<sObject>(2000) reserves space for 2000 references even if you later store only 500 sObjects, and that reserved memory contributes to heap usage. Similarly, when JSON.deserializes into a list, the parser may temporarily allocate a larger array before trimming it, briefly raising heap usage and potentially triggering a LimitException even if the final list fits.