Collect first. Query once. Work in memory.
Start with the whole collection
A record saved from a form can make a trigger look deceptively simple. An import exercises a different path: many records arrive together. Build for that case from the beginning.
Process every record in Trigger.new. When you need related data, collect the relevant IDs in a Set<Id>, query outside the loop, and index the results with a map. Salesforce describes this collection-based approach in its bulk trigger guide.
A small pattern you can reuse
This original example fills an empty contact description with its account name before insertion. It leaves an existing description alone and handles contacts without an account. Install it only in a practice org where this behavior makes sense.
trigger ContactAccountNote on Contact (before insert) {
Set<Id> accountIds = new Set<Id>();
for (Contact person : Trigger.new) {
if (person.AccountId != null) {
accountIds.add(person.AccountId);
}
}
if (accountIds.isEmpty()) return;
Map<Id, Account> accounts = new Map<Id, Account>([
SELECT Id, Name FROM Account
WHERE Id IN :accountIds
WITH USER_MODE
]);
for (Contact person : Trigger.new) {
Account company = accounts.get(person.AccountId);
if (company != null && String.isBlank(person.Description)) {
person.Description = 'Account: ' + company.Name;
}
}
}A before trigger can change the incoming records directly; it does not need a second update statement. If you are modifying other records, collect those changes and perform DML outside the loop.
Check the edges, too
For this example, test a mixed batch: contacts sharing an account, contacts with no account, and contacts with descriptions already supplied. Assert that every relevant record changed and every unrelated value stayed intact.
The query deliberately uses user mode. A user who cannot read a requested object or field can receive a permission error; an account excluded by sharing will not appear in the map. Decide whether that behavior fits your business process. See our permissions article before adapting the example.
Go a little deeper.
Official references behind this note:
Examples are for learning. Validate them in a practice org against your API version, permissions, validation rules, and existing automation.