There is a particular kind of bug that humbles every new Salesforce developer. Your code works beautifully. You test it, it passes, you deploy it, you feel good. Then someone imports a spreadsheet of 200 records, and your perfect code falls over. The cause is almost always the same: it was written to handle one record at a time. The cure is called bulkification.

This is not an advanced topic you can save for later. It is a foundational habit, and the sooner it becomes automatic, the smoother your whole journey as a developer will be.

The problem in one sentence

Salesforce processes records in batches, but beginners tend to write code as if records arrive one at a time.

When you edit a single record in the UI, your code runs against one record and everything looks fine. But triggers, integrations, imports, and Flows routinely hand your code many records in a single transaction, up to 200 at a time in a trigger. Code that assumes “one record” either does redundant work or, worse, slams straight into a governor limit and stops. If you have not met those limits yet, Governor Limits explains exactly why this happens.

Bulkification is simply this: write your code to process a collection of records, not a single one. Do that, and most limit errors never appear.

The mistake, in code

Let me show you the most common offender. Suppose we want to copy each Contact’s account name onto the contact. Here is the tempting, broken version:

// Before: query inside the loop
for (Contact c : Trigger.new) {
    Account a = [SELECT Name FROM Account WHERE Id = :c.AccountId];
    c.Description = 'Works at ' + a.Name;
}

It reads sensibly, and on one record it works. But the SOQL query sits inside the loop, so it runs once per contact. With 200 contacts, that is 200 queries, which is double the per-transaction limit. The transaction dies. This single pattern, SOQL inside a loop, causes more beginner errors than anything else.

The fix: query once, look up with a Map

The bulkified version follows a clear shape. Gather what you need in one query before the loop, store it where you can find it fast, then loop and use it. Here is the same logic done right:

// After: one query, fast lookup with a Map
Set<Id> accountIds = new Set<Id>();
for (Contact c : Trigger.new) {
    accountIds.add(c.AccountId);
}

Map<Id, Account> accounts = new Map<Id, Account>(
    [SELECT Name FROM Account WHERE Id IN :accountIds]
);

for (Contact c : Trigger.new) {
    Account a = accounts.get(c.AccountId);
    if (a != null) {
        c.Description = 'Works at ' + a.Name;
    }
}

Walk through what changed. First, we collect every account Id we care about into a Set. Second, we run a single query for all of them at once, using IN, and load the results into a Map keyed by Id. Third, we loop and pull each account out of the Map instantly. One query handles 1 record or 200 record with identical efficiency.

The Map is the quiet hero here. It lets you look up any record by its Id without going back to the database. Querying once and looking up in memory is the core move of nearly every bulkified pattern you will ever write.

The three rules to remember

You can distill bulkification into three habits, and they will carry you a long way.

Process collections, not single records. Loop over Trigger.new or a list parameter. Never assume one record arrived.

Keep SOQL out of loops. Query before the loop, for everything you need, in one statement using IN.

Keep DML out of loops. Collect records into a list as you go, then insert or update the whole list once, after the loop ends.

That last rule is the partner of the first example. Just as 200 queries breaks you, so does 200 separate update statements. Build the list, write it once.

Why this matters even if you write little code

Maybe you are mostly an admin and only touch Apex occasionally. Bulkification still matters to you, because you will read other people’s triggers, review work, and decide whether code is safe to deploy. Recognizing a SOQL-in-a-loop on sight is a genuinely valuable skill, and now you can.

It also connects directly to triggers, where bulkification is not optional. A trigger that ignores it is a production incident waiting for a busy day. If triggers are still new, Apex Triggers Explained shows where these patterns live.

When I learned the bağlama, my teacher kept returning to one idea: clean technique on a single note is what lets you play a fast run without it collapsing. Bulkification is that clean technique for Apex. Get the small pattern right, and the code holds together no matter how much data flows through it.

Your next step

Pair this with Governor Limits to understand exactly which ceilings bulkification keeps you under, and revisit Apex Triggers Explained to see these patterns in their natural home. Explore more in the Foundations category.

Mustafa Aksu

Salesforce developer & ISV builder focused on Revenue Cloud, Agentforce, and Data Cloud. I write from real, shipped work.