Too Many DML Statements Error
Salesforce is a powerful Customer Relationship Management (CRM) platform used by businesses worldwide to manage customer relationships, streamline processes, and drive growth. With features like Salesforce Sales Cloud, Salesforce Marketing Cloud, and the wide array of tools offered by Salesforce Inc., companies can optimize their operations and enhance their customer interactions. However, even the most robust platforms come with their challenges. One common issue faced by Salesforce developers is the “Too Many DML Statements” error.
This error can be a significant roadblock, especially for those new to Salesforce development. It can disrupt workflows, lead to failed transactions, and even cause data inconsistencies. In this comprehensive guide, we will explore what this error is, its causes, and how you can prevent and resolve it. Whether you’re a seasoned Salesforce developer or just getting started with Salesforce CRM, this article will equip you with the knowledge and tools you need to handle this error efficiently.

Understanding the “Too Many DML Statements” Error
What Are DML Statements in Salesforce?
DML, or Data Manipulation Language, refers to the operations that modify the data stored in Salesforce objects. These operations include insert, update, delete, and upsert, among others. In the context of Salesforce, DML statements are used within Apex code to interact with the database.
For example, when you want to insert a new record into the Salesforce database, you would use a DML statement like:
Account newAccount = new Account(Name=’Acme Corporation’);
insert newAccount;
This code snippet creates a new account record with the name “Acme Corporation” and inserts it into the Salesforce database.
What Triggers the “Too Many DML Statements” Error?
Salesforce has established governor limits to ensure that the platform operates efficiently and fairly across all tenants. One such limit is the maximum number of DML statements that can be executed within a single transaction. As of the latest Salesforce release, this limit is set to 150 DML statements per transaction.
When your code exceeds this limit, Salesforce throws a “Too Many DML Statements” error. This error indicates that the transaction has attempted to perform more DML operations than allowed, which can cause performance issues or even bring down the system.
Common Scenarios Leading to This Error
There are several scenarios in which Salesforce developers might encounter the “Too Many DML Statements” error. Understanding these scenarios can help in diagnosing the problem quickly.
- Looping Through Records Without Proper Optimization
- One of the most common causes is when developers write code that loops through records and performs a DML operation on each iteration without considering the governor limits.
- Trigger Mismanagement
- If your Salesforce triggers are not managed correctly, they can lead to recursive DML operations, where a trigger invokes another trigger, leading to an infinite loop of DML statements.
- Complex Data Processing
- Processing large datasets with multiple related records often involves several DML operations, which can quickly add up and surpass the limit.
- Inefficient Bulk Operations
- Not using bulk processing techniques such as Database. insert(records, false) can result in excessive DML operations.
Why Is This Error Important to Address?
Ignoring the “Too Many DML Statements” error can have several negative consequences:
- Failed Transactions: The most immediate impact is that the transaction fails, which means that any data changes are rolled back. This can disrupt business processes and lead to data inconsistencies.
- Performance Issues: Excessive DML operations can slow down the system, affecting not just the transaction in question but potentially other operations as well.
- System Stability: If the error occurs frequently, it could indicate that your Salesforce instance is not optimized, leading to overall system instability.
Solutions to the “Too Many DML Statements” Error
Fortunately, there are several strategies you can employ to prevent and resolve this error. Here are 15 solutions, complete with code examples, to help you manage your DML statements effectively.
Bulkify Your Code
Bulkifying your code is one of the most effective ways to prevent the “Too Many DML Statements” error. Instead of performing a DML operation for each record individually, you can perform a single operation on a list of records.
Example:
List accountList = new List();
for(Integer i = 0; i < 100; i++) {
accountList.add(new Account(Name='Account ' + i));
}
insert accountList;
Use Collections Efficiently
Using collections like lists, maps, and sets can help reduce the number of DML statements by grouping records.
Example:
Map accountMap = new Map([SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%']);
for(Account acc : accountMap.values()) {
acc.Name = acc.Name + ' - Updated';
}
update accountMap.values();
Minimize the Use of Loops
Avoid performing DML operations inside loops. Instead, accumulate records in a collection and perform the DML operation outside the loop.
Example:
List contactsToUpdate = new List();
for(Contact con : [SELECT Id, LastName FROM Contact WHERE LastName = 'Smith']) {
con.LastName = 'Johnson';
contactsToUpdate.add(con);
}
update contactsToUpdate;
Use Future Methods for Asynchronous Processing
If you have a large number of records to process, consider using future methods to handle some of the DML operations asynchronously.
Example:
@future
public static void updateContacts(Set contactIds) {
List contactsToUpdate = [SELECT Id, LastName FROM Contact WHERE Id IN :contactIds];
for(Contact con : contactsToUpdate) {
con.LastName = 'Updated';
}
update contactsToUpdate;
}
Use Limits Class to Monitor DML Statements
Salesforce provides a Limits class that allows you to monitor the number of DML statements used in your transaction. You can use this to prevent exceeding the limit.
Example:
if(Limits.getDMLStatements() < Limits.getLimitDMLStatements()) {
update contactsToUpdate;
}
Optimize Triggers
Ensure that your triggers are optimized and do not cause recursive DML operations. Use static variables to prevent triggers from being invoked multiple times.
Example:
trigger AccountTrigger on Account (before insert, before update) {
if(TriggerHelper.isTriggerExecuted) return;
TriggerHelper.isTriggerExecuted = true;
// Trigger logic
}
public class TriggerHelper {
public static Boolean isTriggerExecuted = false;
}
Use Batch Apex for Large Data Sets
When dealing with large datasets, use Batch Apex to break down the processing into manageable chunks, thereby reducing the number of DML statements in a single transaction.
Example:
global class UpdateAccountBatch implements Database.Batchable {
global Database.QueryLocator start(Database.BatchableContext BC) {
return Database.getQueryLocator('SELECT Id, Name FROM Account');
}
global void execute(Database.BatchableContext BC, List scope) {
List accountsToUpdate = (List)scope;
for(Account acc : accountsToUpdate) {
acc.Name = acc.Name + ' - Updated';
}
update accountsToUpdate;
}
global void finish(Database.BatchableContext BC) {}
}
Leverage Queueable Apex
Queueable Apex is another asynchronous processing tool that can help manage large numbers of DML statements by processing them in smaller, more controlled batches.
Example:
public class UpdateContactsQueueable implements Queueable {
private List contactIds;
public UpdateContactsQueueable(List contactIds) {
this.contactIds = contactIds;
}
public void execute(QueueableContext context) {
List contactsToUpdate = [SELECT Id, LastName FROM Contact WHERE Id IN :contactIds];
for(Contact con : contactsToUpdate) {
con.LastName = 'Updated';
}
update contactsToUpdate;
}
}
Avoid Recursive Triggers
Recursive triggers can quickly lead to exceeding DML limits. Use a helper class or static variables to prevent recursion.
Example:
public class TriggerHelper {
public static Boolean isTriggerExecuted = false;
}
trigger ContactTrigger on Contact (before insert, before update) {
if(TriggerHelper.isTriggerExecuted) return;
TriggerHelper.isTriggerExecuted = true;
// Trigger logic
}
Optimize SOQL Queries
Efficient SOQL queries can reduce the number of records returned, which in turn reduces the number of DML operations required.
Example:
List<Account> accounts = [SELECT Id, Name FROM Account WHERE Name LIKE 'Acme%'];
Use @TestSetup Methods in Test Classes
When writing test classes, use the @TestSetup method to create test data once and use it across multiple test methods. This reduces the number of DML statements used during testing.
Example:
private class MyTestClass {
@TestSetup
static void setup() {
Account acc = new Account(Name='Test Account');
insert acc;
}
@IsTest
static void testMethod1() {
// Test logic using the Account created in @TestSetup
}
}