trigger-and-flow-coexistence
Governance patterns for orgs where Apex triggers and record-triggered Flows both run on the same object. Covers field-write conflict prevention, single-entry-point consolidation, recursion guards across automation types, and automation inventory documentation. 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 order-of-execution mechanics (use order-of-execution-deep-dive). NOT for trigger handler framework design (use trigger-framework). NOT for Flow-only design patterns (use record-triggered-flow-patterns).
Best use case
trigger-and-flow-coexistence is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Governance patterns for orgs where Apex triggers and record-triggered Flows both run on the same object. Covers field-write conflict prevention, single-entry-point consolidation, recursion guards across automation types, and automation inventory documentation. 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 order-of-execution mechanics (use order-of-execution-deep-dive). NOT for trigger handler framework design (use trigger-framework). NOT for Flow-only design patterns (use record-triggered-flow-patterns).
Teams using trigger-and-flow-coexistence should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/trigger-and-flow-coexistence/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How trigger-and-flow-coexistence Compares
| Feature / Agent | trigger-and-flow-coexistence | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Governance patterns for orgs where Apex triggers and record-triggered Flows both run on the same object. Covers field-write conflict prevention, single-entry-point consolidation, recursion guards across automation types, and automation inventory documentation. 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 order-of-execution mechanics (use order-of-execution-deep-dive). NOT for trigger handler framework design (use trigger-framework). NOT for Flow-only design patterns (use record-triggered-flow-patterns).
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# 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 Ambiguity
Before-save Flows and before Apex triggers both execute at step 3 of the order of execution (after initial record load and before system validation). Salesforce does not guarantee a fixed relative order between a before-save Flow and a before trigger on the same object. If both write to the same field, the result is indeterminate -- whichever runs second silently wins. This is the single most common source of coexistence bugs.
### After-Save Flow Placement
After-save Flows run at step 15 in the order of execution, after workflow rules, workflow field updates, and any re-invocation of before/after triggers caused by those field updates. 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. The bug only surfaces intermittently because the relative execution order is not guaranteed.
### 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 | Move one to a different timing or consolidate into a single automation | No guaranteed relative order at step 3; last writer wins silently |
| 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. **Before-save Flow and before trigger order is indeterminate** -- Salesforce documentation states both run at step 3 but does not specify which executes first. This means a before-save Flow and a before trigger that both set `Status__c` will produce unpredictable results. The field value after step 3 depends on internal platform scheduling, not deployment order.
2. **Workflow field updates re-fire before and after triggers but not before-save Flows** -- When a workflow rule performs a field update at step 9, the system re-evaluates before and after triggers (steps 3-4 again). However, before-save Flows do not re-run during this re-evaluation. 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 18-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 involvementRelated Skills
ip-range-and-login-flow-strategy
Design and implement Salesforce Login Flows (Screen Flows assigned to profiles or Experience Cloud sites) that run post-authentication to enforce conditional MFA, IP-based branching, terms-of-service acceptance, or user data collection. Covers Login Flow creation in Flow Builder, profile/site assignment, IP-aware decision logic, and ConnectedAppPlugin extension points. NOT for static IP allowlisting or profile Login IP Ranges (see network-security-and-trusted-ips), org-wide session policies, or SSO/SAML IdP configuration.
customer-data-request-workflow
Implement GDPR/CCPA data subject rights (access, deletion, rectification) using Salesforce Privacy Center and/or custom workflow. NOT for general backup or org-level data retention policy.
omnistudio-vs-flow-decision
Use when choosing between OmniStudio (OmniScript / Integration Procedure / FlexCard / DataRaptor) and Flow / Screen Flow / Apex for a given capability. Triggers: 'omnistudio or flow', 'omniscript vs screen flow', 'integration procedure vs subflow', 'flexcard vs lightning page'. NOT for general automation selection across Workflow/Process Builder/Apex (see automation-selection tree).
lwc-in-flow-screens
Use when building, reviewing, or troubleshooting a custom Lightning Web Component that runs inside a Flow screen element, covering @api props exposed to Flow, FlowAttributeChangeEvent for output, validate() for user input validation, and flow navigation events. Triggers: 'lwc in flow screen', 'FlowAttributeChangeEvent', 'flow screen component not updating', 'flow validate method', 'flow navigation from lwc'. NOT for custom property editors (use custom-property-editor-for-flow), NOT for embedding a flow inside an LWC (use flow/screen-flows), NOT for auto-launched flows.
custom-property-editor-for-flow
Use when building or reviewing an LWC Custom Property Editor for Flow screen or action configuration, including the `configurationEditor` metadata hook, builder-side APIs, validation, and value-change events. Triggers: 'custom property editor', 'Flow configuration editor', 'builderContext', 'inputVariables', 'configurationEditor'. NOT for ordinary runtime screen-component behavior when no Flow Builder design-time customization is involved.
slack-workflow-builder
Use this skill when designing or troubleshooting Slack Workflow Builder workflows that call Salesforce — especially the Salesforce connector step Run a Flow, mapping inputs/outputs, handling failures, and understanding limits. Triggers on: Slack Workflow Builder Salesforce, Run a Flow from Slack, autolaunched flow from Slack, Slack automation calling Salesforce. NOT for Salesforce Flow Builder tutorials unrelated to Slack (use flow skills), not for Flow Core Actions that send Slack messages from Salesforce (use flow-for-slack), not for initial org-to-workspace connection (use slack-salesforce-integration-setup), and not for building custom Slack apps outside Workflow Builder.
oauth-flows-and-connected-apps
Use when choosing or reviewing Salesforce OAuth flows and connected-app policy for integrations, including client credentials, JWT bearer, authorization code, device flow, scopes, and token lifecycle controls. Triggers: 'OAuth flow', 'connected app', 'client credentials', 'JWT bearer', 'refresh token', 'integration user'. NOT for record-level sharing design or for simple Named Credential usage when the auth-flow decision is already settled.
workflow-rule-to-flow-migration
Migrate Workflow Rules to record-triggered Flows: field update mapping, email alert migration, outbound message alternatives using Flow Core Actions, time-based workflow replacement with Scheduled Paths. NOT for Process Builder migration (use process-builder-to-flow-migration), NOT for building new flows from scratch.
subflows-and-reusability
Use when extracting reusable Flow logic into subflows, defining input and output variables, keeping parent flows maintainable, and sharing common automation contracts across multiple flows. Triggers: 'reuse this flow logic', 'how should subflow variables work', 'too much duplicated flow logic', 'subflow contract design'. NOT for Apex-called Flow execution direction or Flow Orchestration process design.
screen-flows
Use when designing or reviewing interactive Flow screen experiences, including navigation, validation, screen component choice, custom LWC screen components, and user-safe commit timing. Triggers: 'screen flow validation', 'back button behavior in flow', 'custom flow screen component', 'screen flow UX'. NOT for Experience Cloud guest exposure or custom property editor design-time tooling.
screen-flow-accessibility
Use when building Screen Flows that must meet accessibility standards (WCAG 2.1 AA, Salesforce accessibility guidelines). Covers keyboard navigation, focus order, labels, error messaging, color contrast, and screen reader compatibility. Does NOT cover LWC a11y (see lwc-accessibility) or general record-page a11y.
scheduled-flows
Use when designing or reviewing schedule-triggered flows for recurring automation, replacement of time-based workflow patterns, bounded record selection, idempotent processing, and escalation to Apex when volume is too high. Triggers: 'scheduled flow design', 'nightly flow job', 'time based workflow replacement', 'schedule triggered flow limits'. NOT for record-triggered scheduled paths or large-scale batch processing that should be built directly in Batch Apex.