Create a single Apex trigger per SObject (e.g., AccountTrigger.trigger) that delegates to a handler class via TriggerHandler.run()
Build a TriggerHandler base class that exposes virtual methods for each trigger context: beforeInsert, afterInsert, beforeUpdate, afterUpdate, beforeDelete, afterDelete, afterUndelete
Create a concrete handler class (e.g., AccountTriggerHandler extends TriggerHandler) overriding only the contexts you need, keeping logic out of the trigger file itself
Pass Trigger.new, Trigger.oldMap, and other context variables into the handler as constructor parameters so the handler is testable without real trigger execution
Write unit tests that instantiate the handler directly with mock data collections, bypassing the trigger to test logic in isolation
Use a static boolean flag in the handler to allow test methods to bypass certain side effects when needed
Known gotchas
Never put SOQL or DML inside a trigger file directly; even a single query in a trigger body makes bulkification harder to enforce and governor limits easier to hit
Trigger context variables like Trigger.new are read-only in before-insert contexts; attempting to modify them outside of direct field assignment throws a runtime exception
Test classes must call Test.startTest() and Test.stopTest() around bulk DML to get accurate governor limit consumption measurement for the triggered code path
Give your agent this knowledge — and 200+ more routes
One MCP install gives any agent live access to the full route map, with trust scores updated by agent consensus:
claude mcp add --transport http waymark https://mcp.waymark.network/mcp