Apex Trigger Practice Problems: Bulk, Context, and a Handler
By Firus Hanov · · 7 min read
Five Apex trigger practice problems: before insert in bulk, one DML after insert, oldMap, a handler class, and a recursion guard. Free to read; Check and Run is Apex Path.

An Apex trigger practice problem is not "write a trigger that updates a field." That passes on one record and fails on two hundred. The problems worth doing are bulk, context-specific, and boring on purpose: before insert versus after insert, a handler class, and a recursion guard.
Do not start here. A trigger you cannot bulkify is a production incident. Pass Lists of Opportunities and Build a Case summary class first. Both are free to Check and Run.
The five problems
- Before insert, one field, two hundred rows. Set a description from the row in
Trigger.new. No query. No DML. Write your first before-insert trigger grades that shape. If your code saysTrigger.new[0], it is wrong even when the test inserts one row. - After insert, related records in one DML. A follow-up Task per Contact means a list of Tasks and one
insert, not an insert inside the loop. Create follow-up Tasks after Contact insert. - Only when the field changed.
Trigger.oldMaptells you the previous email. Firing the same work on every edit wastes limits and surprises users. React to a Contact email change. - The trigger is a router. The class does the work. A trigger that contains the business logic cannot be tested without inserting rows, and it cannot be reused. Move Opportunity logic to a handler.
- Stop the trigger from calling itself. An update inside an update trigger will run the trigger again. A static set of Ids is the usual guard. Stop recursive Account updates.
The shape to copy
This is the skeleton. It does nothing useful until you fill in the handler, and that is the point.
trigger ContactFollowUp on Contact (after insert) {
ContactFollowUp.handle(Trigger.new);
}
public with sharing class ContactFollowUp {
public static void handle(List<Contact> rows) {
List<Task> tasks = new List<Task>();
for (Contact row : rows) {
tasks.add(new Task(WhoId = row.Id, Subject = 'Follow up'));
}
if (!tasks.isEmpty()) insert tasks;
}
}
One query for the whole transaction, or none. One DML for the whole transaction. No Trigger.new[0]. No SOQL inside the for loop. Those three rules cover more failed trigger reviews than any framework.
How these get graded
Trigger drills deploy an Apex class and a trigger into your Developer org and run tests there. They do not grade a screenshot of the trigger editor. Production orgs are blocked. You need a Developer org, the same one from the anonymous Apex walkthrough.
Automate with triggers is free to read. Check and Run is Apex Path, $19 a month after a 7-day trial. The free path in front of it is Write Apex, then Think in classes. If the handler class above is hard to read, you are not behind on triggers. You are early on classes. Stay on the beginner problems until a class with a list parameter is easy.