Imagine a doorbell wired straight into your house. Every time someone steps onto the porch, it rings, automatically, without anyone deciding to ring it. An Apex trigger works the same way. You wire it to an object once, and from then on it runs by itself whenever a record changes.

This is one of those Salesforce concepts that sounds intimidating and turns out to be approachable. Let me take you through what a trigger is, when it fires, and the one habit that will keep your triggers from turning into a tangle.

What a trigger is

A trigger is a piece of Apex code attached to a specific object that runs automatically when records on that object are created, changed, or removed. You do not call it. Salesforce calls it for you, every single time the event happens.

Triggers fire around database events. The main ones are insert (a record is created), update (a record is changed), and delete (a record is removed). For each of these, you can choose to run your code before the change is saved or after it is saved.

That before-or-after choice matters. Use before when you want to adjust the record itself, like setting a field value, because the record is not locked in yet. Use after when you need to do something with related records or trust that the record now has an Id. A good rule of thumb: change this record in before, react to it elsewhere in after.

The trigger context

When a trigger fires, Salesforce hands it a set of context variables describing what just happened. The one you will reach for most is Trigger.new.

Trigger.new is a list of the records being processed. Notice the word list. Even if a single record changed, it arrives in a collection, and this detail shapes everything about how you write trigger code. We will come back to that.

Here is a tiny example. When an Account is created, we stamp a default rating if none was provided:

trigger AccountDefaults on Account (before insert) {
    for (Account acc : Trigger.new) {
        if (acc.Rating == null) {
            acc.Rating = 'Warm';
        }
    }
}

Read it slowly. The trigger is on the Account object, firing before insert. We loop over Trigger.new, and for each Account with no rating, we set one. Because this is a before trigger, we just change the field directly and Salesforce saves it for us. No update statement needed.

If the Apex syntax here feels unfamiliar, start with Your First Apex Class first. Triggers make far more sense once basic Apex reads comfortably.

One trigger per object

Here is a piece of advice that will save you real pain later. Keep one trigger per object.

Salesforce lets you create several triggers on the same object, but it does not promise the order they run in. Two triggers on Account might fire in any sequence, and that unpredictability causes bugs that are miserable to track down. The widely accepted practice is a single trigger per object that delegates its logic to a separate handler class. You do not need to build that pattern today, but plant the seed now: one trigger, one object.

A trigger is plumbing, not logic. Keep one per object, keep it thin, and let it hand the real work to a class you can read and test.

Always think in collections

Remember Trigger.new being a list? This is the single most important thing to internalize about triggers.

When a user edits one record in the UI, your trigger receives one record. But when an import, an integration, or a Flow updates 200 records at once, your trigger receives all 200 in a single run. Code that quietly assumes “one record at a time” works fine in testing and then breaks in production the moment real volume arrives.

The fix is a habit called bulkification, writing every trigger to handle a whole collection cleanly. It is worth understanding early, and I cover it fully in Bulkification. For now, just notice that the example above loops over Trigger.new rather than assuming a single record. That loop is the beginning of the right instinct.

When a trigger, and when not

Not everything needs code. Salesforce gives you powerful point-and-click automation through Flow, and for many tasks it is the better choice. Reach for a trigger only when the logic is genuinely too complex for clicks, when you need precise control over timing, or when performance at high volume demands it.

For routine field updates, sending an email, or simple branching logic, a Flow is usually faster to build, easier for an admin to maintain, and perfectly capable. I lay out how to make that call in Flow, Apex, or Clicks?. The mark of a good developer is not writing more code, it is knowing when not to.

When I started, I reached for code reflexively because it felt like “real” engineering. The teacher in me eventually won out: the best solution is the one the next person can understand and maintain. Sometimes that is a trigger. Often it is a Flow.

Your next step

Build your Apex foundation first with Your First Apex Class, then make trigger code production-ready by reading Bulkification. When you are deciding whether you even need a trigger, Flow, Apex, or Clicks? will steer you. Find 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.