Managing the Heap in Salesforce.com
August 16th, 2010
With the Spring ’10 release, Salesforce.com removed the limit on the number of items a collection can hold. So now, instead of ensuring that your collections contain no more than 1000 items, you have to monitor your heap size. Here are some strategies on how to write Apex scripts that run within these limits.
First of all, what is the heap? Dynamic memory allocation (also known as heap-based memory allocation) is the allocation of memory storage for use in a computer program during the runtime of that program. In Apex the heap is the reference to the amount of memory used by your reachable objects for a given script and request. When you create objects in your Apex code, memory is allocated to store these objects.
As with many other things in Force.com, there are governors and limits that prevent you from hijacking the heap and degrading the performance of other running applications. The heap limit is calculated at runtime and differs on how your code is invoked:
- Triggers – 300,000 bytes
- Anonymous Blocks, Visualforce Controllers, or WSDL Methods – 3,000,000 bytes
- Tests – 1,500,000 bytes
These limits also scale with trigger batch sizes:
- For 1-40 records, the normal limits apply
- For 41-80 records, two times the normal limits apply
- For 81-120 records, three times the normal limits apply
- For 121-160 records, four times the normal limits apply
- For 161 or more records, five times the normal limits apply
Luckily Salesforce.com increased the heap size limits in Summer ’10 but you still may run into some issues. Here are a few things you can do to write heap-friendly code.
Watch the Heap
When your scripts run you can view the heap size in the debug logs. If you notice your heap approaching the limit, you will need to investigate why and try to refactor your code accordingly.

Use the Transient Keyword
Try using the “Transient” keyword with variables in your controllers and extensions. The transient keyword is used to declare instance variables that cannot be saved, and shouldn’t be transmitted as part of the view state for a Visualforce page.
Use Limit Methods
Use heap limits methods in your Apex code to monitor/manage the heap during execution.
- Limits.getHeapSize() – Returns the approximate amount of memory (in bytes) that has been used for the heap in the current context.
- Limits.getLimitHeapSize() – Returns the total amount of memory (in bytes) that can be used for the heap in the current context.
// check the heap size at runtime
if (Limits.getHeapSize > 275000) {
// implement logic to reduce
}
One strategy to reduce heap size during runtime is to remove items from the collection as you iterate over it.
Put Your Objects on a Diet
If the objects in your collection contain related objects (i.e., Account objects with a number of related Contacts for each) make sure the related objects only contain the fields that are actually needed by your script.
Use SOQL For Loops
SOQL “for” loops differ from standard SOQL statements because of the method they use to retrieve sObjects. To avoid heap size limits, developers should always use a SOQL “for” loop to process query results that return many records. SOQL “for” loops retrieve all sObjects in a query and process multiple batches of records through the use of internal calls to query and queryMore.
1 2 3 4 5 6 7 8 | for (List<Contact> contacts : [select id, firstname, lastname
from contact where billingState = 'NY']) {
// implement your code to modify records in this batch
// commit this batch of 200 records
update contacts;
} |
Note: There used to be a strategy for dealing with heap intensive scripts by moving them asynchronous, @Future methods. However, since the heap limits were increased in Summer ’10 this is no longer a reason to simply use @Future method as the limits are the same.
Any other ideas on how to effectively manage the heap?
Categories: Apex, Salesforce













“One strategy to reduce heap size during runtime is to remove items from the collection as you iterate over it.”
Depends on the type of loop you are using. This will work:
List letters = new List{‘a’,'b’,'c’};
for(Integer i = 0; i < letters.size() + 1; i++){
letters.remove(0);
}
But this will thrown and exception, 'List cannon be modified during iteration":
List letters = new List{‘a’,'b’,'c’};
Integer count = 0;
for(String s : letters){
letters.remove(count);
count++;
}
First like above should be:
for(Integer i = 0; i < letters.size(); i++){
Once again nice post Jeff..
Just to add what Jason mentioned, we can “clear” the lists that we are done using and we are going forward doing some more stuff in our class or trigger.
myList.clear();
Won’t variables marked transient still have memory allocated for them? Or does the viewstate count double for the heap (once for the variable itself, once as it is included in the viewstate) ?
If we mark the variables as transient, cant we use them on multiple pages with same controller?
To avoid “‘List cannon be modified during iteration”, I create a new collection on runtime from the old one and then remove the old collection.
Hi Jeff,
Can u help me please
my code is given below
if(salesOrderList.size()>0){
System.debug(‘salesOrderList.size(): ‘ + salesOrderList.size());
integer i = 0;
List lst = new List();
for(Sales_Order__c S : salesOrderList){
integer d1 = i/2;System.Debug(‘sanjeeb: d1: ‘ + d1);
integer res = i – (2*d1);System.Debug(‘sanjeeb: res: ‘ + res);
string color = ”; Error Line Apex heap size too large: 3000621
if(res == 0){
color = ‘#D2EFF8′;
}else{
color = ‘#1797CO’;
}
if(S.Sales_Order_Line_Items__r.size() > 0)
i++;
for(Sales_Order_Line_Item__c LI : S.Sales_Order_Line_Items__r){
WrapperClass WC = new WrapperClass(S, LI);
WC.BGColor = Color;
WC.ForeColor = ‘Black’;
lstW.add(WC);
}
}
}
Here I am not creating a collection as per my assumtion. I am setting this value as blank each time in loop still getting error. Is transient is needed here while it is a local variable.
Thank
Vijay
sorry Jeff.. Error line is
integer res = i – (2*d1);
Hey Jeff I have solve my issue …
There is no issue in given code
Thanks