Governance patterns for orgs where Apex triggers and record-triggered Flows both run on the same object: field-write conflict prevention, single-entry-point consolidation, recursion guards across automation types, and automation inventory. Use when inheriting a mixed-automation org, adding a Flow to an object that already has triggers, or resolving silent field-overwrite bugs. NOT for save order of execution — use apex/order-of-execution-deep-dive. NOT for Flow-only patterns — use flow/record...
Scanned 9/6/2026
Install to Claude Code
npx -y skills add PranavNagrecha/AwesomeSalesforceSkills --skill trigger-and-flow-coexistence --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Trigger And Flow Coexistence?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/pranavnagrecha-trigger-and-flow-coexistence)More formats (shields.io, HTML) on the badges page.
---
name: trigger-and-flow-coexistence
description: "Governance patterns for orgs where Apex triggers and record-triggered Flows both run on the same object: field-write conflict prevention, single-entry-point consolidation, recursion guards across automation types, and automation inventory. Use when inheriting a mixed-automation org, adding a Flow to an object that already has triggers, or resolving silent field-overwrite bugs. NOT for save order of execution — use apex/order-of-execution-deep-dive. NOT for Flow-only patterns — use flow/record-triggered-flow-patterns."
category: apex
salesforce-version: "Spring '25+"
well-architected-pillars:
- Reliability
- Operational Excellence
triggers:
- "how to manage triggers and flows on the same object without conflicts"
- "trigger and flow both updating the same field and overwriting each other"
- "before-save flow and before trigger running in unpredictable order"
- "adding a new record-triggered flow to an object that already has apex triggers"
- "automation inventory for objects with mixed trigger and flow automation"
- "recursion between after-save flow and after trigger causing infinite loop"
tags:
- trigger-and-flow-coexistence
- automation-governance
- field-conflict
- recursion
- order-of-execution
inputs:
- "Object name and list of all active automations (triggers, flows, workflow rules, process builder)"
- "Description of the field-write conflict or recursion symptom"
- "Whether the org has a single-trigger-per-object pattern or multiple triggers"
outputs:
- "Automation inventory matrix documenting every automation on the object, its type, timing, and field writes"
- "Conflict analysis identifying field-write collisions and execution-order risks"
- "Refactoring plan to eliminate or guard against coexistence problems"
dependencies: []
version: 1.0.0
author: Pranav Nagrecha
updated: 2026-04-06
---
# Trigger And Flow Coexistence
This skill activates when an org has both Apex triggers and record-triggered Flows on the same object and needs to prevent silent conflicts, field-overwrite bugs, or recursion loops. It provides governance patterns for inventorying mixed automation, detecting field-write collisions, and establishing guard clauses that work across automation types.
---
## Before Starting
Gather this context before working on anything in this domain:
- Which object has both triggers and Flows? List every active automation by name, type (before trigger, after trigger, before-save Flow, after-save Flow), and the fields each one reads or writes.
- Is there a single-trigger-per-object handler pattern already in place, or are there multiple trigger files on the same object?
- What is the symptom: a field being silently overwritten, an unexpected recursion loop, a governor limit error, or an automation that appears to not fire at all?
---
## Core Concepts
### Before-Save Timing Is Determinate
Before-save record-triggered Flows execute at **step 3** of the order of execution. Apex before triggers execute at **step 4**. These are separate, consecutively numbered steps in the Apex Developer Guide, so the relative order is fixed and documented: the Flow runs first, the trigger runs second.
The practical consequence for coexistence: if a before-save Flow and a before trigger both write the same field, **the before trigger's value is the one that persists** — on every transaction, in every org, regardless of deployment order. The symptom "the Flow's value keeps disappearing" is fully explained by step order; it is not intermittent and not environment-dependent.
This still makes overlapping field writes the most common source of coexistence bugs — but the bug is a silent, *predictable* overwrite, not a race. Diagnose it by reading the step map, and fix it by giving the field one owner (or by making the later writer conditional). Do not add guards, retries, or ordering hacks intended to defeat nondeterminism that does not exist.
### After-Save Flow Placement
After-save Flows run at step 14 in the order of execution, after workflow rules (step 11), escalation rules (step 12), and Process Builder / workflow-launched Flows (step 13) — including any re-invocation of before update and after update triggers caused by a workflow field update. This means an after-save Flow sees field values that may have been modified by a workflow field update that re-fired triggers. Conversely, DML performed inside an after-save Flow will re-enter the order of execution and fire triggers again, creating a recursion path that is invisible to trigger-only recursion guards.
### Single Entry-Point Principle
The Salesforce Well-Architected framework recommends a single automation entry point per object per timing slot. In practice this means either triggers or Flows own a given timing slot on a given object, not both. Coexistence is a tolerated legacy state, not a recommended architecture. The goal of this skill is to make coexistence safe while planning consolidation.
### Field Ownership Model
Each writeable field on an object should have at most one automation that sets its value during a given timing slot. When multiple automations write the same field at the same timing, you have a field-write collision. The field ownership model is a simple matrix: rows are fields, columns are automations, cells indicate read (R) or write (W). Any column with two or more W entries at the same timing is a conflict.
---
## Common Patterns
### Pattern 1: Field Ownership Registry
**When to use:** Any object with two or more automations that write fields during the same timing slot.
**How it works:**
1. Create a spreadsheet or metadata document listing every field on the object that is written by any automation.
2. For each field, record which automation writes it and at which timing (before-save, after-save).
3. Flag any field with more than one writer at the same timing as a conflict.
4. Resolve conflicts by moving one writer to a different timing, consolidating both writes into a single automation, or using a guard clause to ensure only one writer executes.
**Why not the alternative:** Without an explicit registry, developers add automations that silently overwrite each other. Nothing in the platform reports the collision — the later step simply wins and no error is raised. The registry is what makes an otherwise invisible conflict visible.
### Pattern 2: Cross-Automation Recursion Guard
**When to use:** An after trigger performs DML that re-enters the save and fires Flows, or an after-save Flow performs DML that fires triggers, causing a recursion loop.
**How it works:**
```apex
public class AutomationControl {
// Static flag visible to triggers; Flow can read via Invocable
public static Boolean flowOriginatedSave = false;
public static Boolean triggerOriginatedSave = false;
@InvocableMethod(label='Check If Trigger Originated Save')
public static List<Boolean> isTriggerOriginated(List<String> unused) {
return new List<Boolean>{ triggerOriginatedSave };
}
}
```
In the trigger handler, set `AutomationControl.triggerOriginatedSave = true` before performing DML. In the Flow, use a Decision element to call the Invocable method and skip logic when the flag is true. This prevents the Flow from re-processing records that the trigger already handled.
**Why not the alternative:** Static variables in Apex are invisible to Flows by default. Without an Invocable bridge, the Flow has no way to know it was triggered by an Apex DML and will always execute, causing infinite recursion.
### Pattern 3: Consolidation Into Single Trigger Handler
**When to use:** Long-term refactoring of a mixed-automation object toward a single entry point.
**How it works:**
1. Inventory all before-save Flows on the object and document their logic.
2. Rewrite each Flow's logic as a method in the trigger handler class.
3. Deactivate the before-save Flows one at a time, testing after each deactivation.
4. Repeat for after-save Flows if the team prefers trigger-only automation.
5. Document the migration in the automation inventory so future developers do not recreate Flows on the object.
**Why not the alternative:** Consolidation into Flows is equally valid. The key is choosing one entry point per timing slot, not necessarily choosing triggers over Flows. The decision depends on the team's skill set and change management process.
---
## Decision Guidance
| Situation | Recommended Approach | Reason |
|---|---|---|
| Before trigger and before-save Flow both write the same field | Give the field a single owner, or make the trigger's write conditional | Step 4 (trigger) always runs after step 3 (Flow), so the trigger silently wins every time |
| After trigger DML re-fires Flows that re-fire triggers | Implement cross-automation recursion guard with InvocableMethod bridge | Static variables alone do not cross the Apex-to-Flow boundary |
| New Flow being added to an object with existing triggers | Build automation inventory first; confirm no field-write collisions | Prevents introducing a silent overwrite bug in production |
| Org has process builder, workflow rules, triggers, and Flows on the same object | Prioritize consolidation; use Flow Trigger Explorer to sequence Flows | Four automation types on one object is unmaintainable at scale |
| Team is split between Flow-first and code-first developers | Establish a per-object ownership agreement and document it in the automation inventory | Mixed patterns are acceptable if governed; ungoverned mixing causes outages |
---
## Recommended Workflow
Step-by-step instructions for an AI agent or practitioner working on this task:
1. **Build the automation inventory.** For the target object, list every trigger (before/after, insert/update/delete), every record-triggered Flow (before-save, after-save), every workflow rule with field updates, and every active Process Builder. Record the fields each automation reads and writes.
2. **Identify field-write collisions.** Using the inventory, flag any field that is written by more than one automation at the same timing slot. These are active or latent coexistence bugs.
3. **Check for cross-automation recursion paths.** Trace DML operations in after triggers and after-save Flows. If a trigger performs DML that re-enters the save, check whether Flows on the target object will fire and vice versa.
4. **Implement guards or resolve conflicts.** For field-write collisions, choose one owner per field per timing. For recursion paths, implement the cross-automation recursion guard pattern with an InvocableMethod bridge. For legacy automations (workflow rules, Process Builder), plan migration to either triggers or Flows.
5. **Document the ownership model.** Update the automation inventory with the resolved ownership. Store this document in the repo or wiki so future changes go through the same review.
6. **Test with the Flow Trigger Explorer.** In a sandbox, use Setup > Flow Trigger Explorer to visualize the execution sequence. Verify that field values match expectations after save.
7. **Validate in a full sandbox with data volume.** Run bulk DML (200+ records) to confirm that recursion guards hold under bulk and that governor limits are not hit by the combined automation stack.
---
## Review Checklist
Run through these before marking work in this area complete:
- [ ] Automation inventory exists and lists every trigger, Flow, workflow rule, and Process Builder on the object
- [ ] No field is written by more than one automation at the same timing slot (or conflicts are explicitly guarded)
- [ ] Cross-automation recursion paths are identified and guarded with InvocableMethod bridge or field-value checks
- [ ] Flow Trigger Explorer confirms expected execution sequence in sandbox
- [ ] Bulk DML test (200+ records) passes without governor limit errors
- [ ] Automation inventory document is committed or stored in a shared location
- [ ] Legacy automations (workflow rules, Process Builder) have a migration plan documented
---
## Salesforce-Specific Gotchas
Non-obvious platform behaviors that cause real production problems:
1. **The before trigger always overwrites the before-save Flow, silently** -- The Apex Developer Guide lists before-save Flows at step 3 and before triggers at step 4. The order is documented, not indeterminate. If a Flow and a trigger both set `Status__c`, the trigger's value is what saves, every time. The gotcha is that nothing surfaces the conflict: no error, no warning, no debug-log flag. Beware older guidance (including AI-generated guidance) that describes this as an unpredictable race — acting on that belief leads people to add guards instead of fixing field ownership.
2. **Workflow field updates re-fire before and after triggers but not record-triggered Flows** -- When a workflow rule performs a field update at step 11, the platform updates the record again, re-runs system validations, and executes before update and after update triggers "one more time (and only one more time)." Record-triggered Flows, custom validation rules, duplicate rules, and escalation rules are not re-run. This asymmetry means a trigger can see a value set by a workflow field update, but a before-save Flow cannot.
3. **After-save Flow DML is invisible to trigger recursion guards** -- A typical trigger recursion guard uses a static Boolean like `hasRun`. This prevents the trigger from running twice in the same transaction. However, DML performed by an after-save Flow enters a fresh save cycle that resets the trigger context. The static variable is still true, so the trigger skips -- but the Flow may not skip, causing a one-sided infinite loop.
---
## Output Artifacts
| Artifact | Description |
|---|---|
| Automation Inventory Matrix | Object-level document listing every automation, its type, timing, fields read, fields written, and ownership |
| Conflict Analysis Report | Identification of field-write collisions and recursion paths with severity ratings |
| Refactoring Plan | Step-by-step plan to consolidate or guard coexisting automations |
---
## Related Skills
- order-of-execution-deep-dive -- Use when you need the full 20-step order of execution reference rather than coexistence governance
- trigger-framework -- Use when designing or refactoring the trigger handler pattern itself
- record-triggered-flow-patterns -- Use when designing Flows in isolation without trigger coexistence concerns
- recursive-trigger-prevention -- Use when the recursion problem is trigger-to-trigger only, without Flow involvement
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!