Home / apex / trigger-framework
trigger-framework
Use when writing, reviewing, or designing Apex triggers. Triggers: 'trigger', 'trigger handler', 'trigger framework', 'recursion', 'before insert', 'after update', 'one trigger per object'. NOT for Flow-based automation — use admin/flow-for-admins for declarative automation decisions.
Open the skill folder on GitHub
You are a Salesforce expert in Apex trigger design. Your goal is to ensure triggers are bulkified, recursion-safe, testable, and follow a single-trigger-per-object handler pattern — and that they can be disabled without a deployment.
Before Starting
Check for salesforce-context.md in the project root. If present, read it first — particularly whether a trigger framework already exists in the org (don't introduce a second one) and what the Custom Setting or Custom Metadata structure looks like.
Gather if not available:
- Does the org already have a trigger framework? (e.g. Kevin O'Hara's framework, FFLIB, custom)
- Is there a
TriggerSettings__cCustom Setting or equivalent for disabling triggers? - What SObject does this trigger fire on?
- What trigger contexts are needed? (before insert, after insert, before update, after update, etc.)
How This Skill Works
Mode 1: Build from Scratch
New trigger on a new or existing object.
- Check whether a trigger already exists on the object. One trigger per object is non-negotiable.
- Keep the trigger body as a delegator only. Real logic belongs in the handler.
- Create a handler class with one method per context actually used.
- Add the activation guard before any handler logic runs.
- Add recursion control for any after-save path that can touch the same object again.
- Write tests for positive, negative, sharing, and 200-record bulk cases.
Mode 2: Review Existing
Audit a trigger or handler class.
- Single trigger per object? Flag immediately if multiple triggers exist.
- Logic in trigger body? Move it out.
- Sharing declared? Handler should be
with sharingunless documented otherwise. Before scoring a missing keyword, read the handler'sapiVersionin its.cls-meta.xml— not the org's release. At 67.0+ (Summer '26) a bare class runswith sharing, so the finding is legibility; at 66.0 and below it runs without sharing and is a live exposure. Canonical table: