
Published originally in my GitHub profile: ApexTriggers
SUMMARY: these are 6 types of common triggers that cover estimated 70% of Apex development needs (*).
Types of triggers
There are 6 most basic types of triggers (there may be others but these are the ones most common in my experience):
- Trigger sets fields with values derived from other fields in the same record
- Trigger adds validation error messages using data from fields in the same record
- Trigger sets fields with values from other records
- Trigger sets fields with values on other records
- Trigger performs call outs to external web services or HTTP requests to receive data
- Trigger sends an email
In all examples below the triggers will call static methods on the helper class and follow the format below:

All helper classes below are implied to have static methods and set of ids to control recursion. The examples are intended to be as simple as possible and only to illustrate the concepts.
Different types of Apex triggers (Salesforce) and their helper classes
They are categorized according to where data comes from and goes to and their functional equivalent standard feature:

1 – Trigger that sets fields with values derived from other fields in the same record
This trigger does what a formula field would ideally do: compute an expression using other field values. Some expressions are not possible using formula functions or the resulting expression exceeds the formula size limit, hence the requirement for this trigger. For example, there is no formula field that calculates the extended internal rate of return (IRR or XIRR), which can only be calculated using Newton’s iterative method.

The above trigger consists of a simple loop over the new/updated records. In the loop, it computes a value from some fields and stores the result in another field.
2 – Trigger that adds validation error messages using data from fields in the same record
This trigger is similar to trigger #1 above, but it applies to validation. It does what a validation rule would ideally do: check values from one or more fields against a criteria. Some validation rules can’t be expressed using validation formula functions or the resulting expression exceeds the validation size limit or require values from more than one record, hence the need for this trigger.

Same as before: the trigger consists of a simple loop over the new/updated records. This time, it determines the cumulative percentage of all investments under a same account
3 – Trigger that sets fields with values from other records
This trigger does what a cross object formula field would ideally do: use values from other related records. Sometimes the requirement goes beyond what a simple lookup/master-detail relationship could accommodate, hence the need for this trigger.
The example below is adapted and simplified from a Field Service Lightning org. The client wanted a preferred resource automatically assigned to each work order. The resource needed to match the work order territory and be credentialed on the same service as the work order.


Notice that the pattern on the last 3 triggers was to start with a loop over the incoming records. Then it leverages data from them to take the next steps. In this case, the data was collected from the incoming records to perform a query on another object. This leads to the common trigger pattern loop-query-loop-update.
Another pattern is to build a map right after a query. The map is usually indexed not by Id but by one field or a combination of fields. Then the map is used as an in-memory lookup inside a loop.
4 – Trigger that sets fields with values on other records
This trigger simply propagates data from the incoming records to other objects in the org, usually to children records or to parent records. This may be accomplished via record-triggered flows too but it tends to be more straightforward and performant to implement it in a trigger.
The example below was adapted from a Sales org client. When an opportunity was closed, the client wanted to create 12 months worth of child records (Disbursement__c). Since the child records need the parent opportunity id, this trigger is after insert/update.

The example below is adapted from another Sales org client. When an opportunity product changed its status, the client wanted it to automatically sync the parent opportunity status.


These triggers almost always start with an initial loop over the incoming records but here we observe another pattern: it collects data from the incoming records, then use that data to query some other object, then loop over the queried data to perform some update. This loop-query-loop-update pattern is very common.
5 – Trigger that performs call outs to external web services or HTTP requests to receive data
This trigger collects data from the incoming records, calls out a web service passing that data as parameters, then updates one or more objects in the org. This requires the use of the @future(callout=true) annotation since callout from triggers are currently not supported.
The example below was adapted from a client org that needed the transportation distance and duration between one of their warehouses and their customers whenever the warehouse or the customer address was changed on the record. We leveraged the Distance Matrix API from Google.


This one was a departure from the pattern: instead of loop-query-loop-update, it was a loop callout plus query-loop-update.
6 – Trigger that sends emails related to incoming records
This trigger collects data from the incoming records, then sends an email linked to the record according to a criteria. Ideally this would be handled with a workflow alert or a record-triggered flow, but some criteria may be too complex to be implemented satisfactorily in a flow/rule.
In the example below, the client wanted to be notified when a quote belonging to a parent opportunity was changed to no longer be the opportunity’s only quote flagged as forecast.


That was another variation of the loop-query-loop-update: loop-query-loop-email.
(*) this is taken from personal experience working on hundreds of orgs over a period of 8+ years.
Leave a Reply