Heap size reached in Apex Batch

Prerequisites: Apex batch, Collections, Database.Stateful, Salesforce Architecture

Heap memory is runtime memory which keeps the state of the variables until the program execution completes. Built on a multi-tenant architecture, Salesforce can’t give away unlimited heap memory to its users, and the limit is set to 12MB as it is an asynchronous job. If the heap memory usage exceeds more than the specified threshold, then “Heap Size Limit Reached” error occurs during runtime.  This limit is mainly hit as the interface: database.stateful handles a vast collection of data. The Apex batch as a whole can process up to 50 million records, 10 thousand records per batch and only 10 thousand batches in 24 hours with a state heap limit of 12 MBs. Reaching close to these limits are not ideal.

Database.stateful is a marker which can be defined in a batch class to maintain the states or values of certain variables in heap memory. Batch class may call the execute method more than once depending upon the batches identified.

Now, each execute method call results in a separate apex transaction. During rolling over from one apex transaction, i.e., Finishing one execute method call and starting a new one, the garbage collector  clears all variables and collections of the previous call.

But if you use Stateful, then the variable or collection doesn’t lose the values in it during rolling over to a different apex transaction or are marked not to be cleared by the garbage collector. A Batch will generally run slower when the Database.Stateful marker interface is used. The serializing and deserializing of state between the execute calls also affects performance.


– Please try not to lift more than 10 thousand records in each collection(list or map) during a transition between states.

– Often use the Clear method to clear out data when it is not required anymore from Stateful collections.

– If you see that a collection is getting very large, you can try segregating data into groups and process one group in one batch class and remaining groups in some other batch classes. You can also use batch chaining for processing all groups one by one.

– You can use relation build data, i.e., Fetch one record from queryLocator and then fetch other related data from that record in the execute method. As each batch behaves as a separate program with heap size being used as a database for them.

– Keep track of heap size with every ending execute and maintain accordingly using this code:

    Integer HeapSizeWhenStartingExecute = Limits.getHeapSize();

   Integer AdditionalHeapSizeUsed = Limits.getHeapSize() – HeapSizeWhenStartingExecute;

and save it temporarily to some temporary Object when you are close to hitting the limits.

Cheers if you find these suggestions useful!