Flow Design and Orchestration Patterns

Based on Real Implementation Experience: This document captures Flow patterns and practices derived from actual implementation experience across multiple enterprise-scale Salesforce projects, including public sector portals serving 40,000+ concurrent users and higher education CRM implementations with complex integrations.

Overview

Flow is the primary automation engine across projects, with Apex reserved for complex logic, integrations, and performance-critical scenarios. This declarative-first approach enables faster development, easier maintenance, and better collaboration between admins and developers.

Core Philosophy: Prefer Flows over Apex when logic can be expressed declaratively. Use Apex for complex logic that Flow cannot handle efficiently, tight control over governor limits, heavy reuse across multiple contexts, or integrations requiring complex authentication and error handling.

Prerequisites

Required Knowledge:

Recommended Reading:

When to Use Flow vs Apex

Use Flow When:

Use Apex When:

Flow Types and Detailed Use Cases

Record-Triggered Flows

Primary Workhorse: Record-Triggered Flows are the primary automation tool for creating/updating related records, status transitions, and notifications.

Before-Save Flows

Execution Context: Run before the record is saved to the database, during the before-save phase of the order of execution.

Capabilities:

Use Cases:

Best Practices:

Real Example: Case_BeforeSave_Defaulting - Sets default values on Case creation based on record type and other criteria.

Example Pattern:

Entry Criteria: Record Type = 'Support Case' AND Status = 'New'
Logic:
  - Set Priority = 'Medium' if Priority is null
  - Set Owner = Queue if Owner is null
  - Calculate Due Date based on SLA rules

After-Save Flows

Execution Context: Run after the record is saved to the database, during the after-save phase of the order of execution.

Capabilities:

Use Cases:

Best Practices:

Real Example: App_AfterSave_ApplicationStatusOrchestration - Orchestrates application status changes, creates related records, publishes Platform Events, and sends notifications.

Example Pattern:

Entry Criteria: Record Type = 'Application' AND Status changed
First Decision Node:
  - Route by IsNew (New vs Update)
  - Route by Channel (Portal vs Internal vs Integration)
  - Route by Person Type (Student vs Vendor vs Staff)
Subflows:
  - "Create Advisor Tasks"
  - "Sync Application Status to Child Objects"
  - "Build Notification Payload"
Actions:
  - Create related records
  - Publish Platform Event
  - Send email notification

Record-Triggered Flow Structure Pattern

Consistent Structure: All Record-Triggered Flows follow a consistent structure pattern.

Before-Save Flow Structure:

  1. Entry Criteria: Strict criteria matching specific conditions
  2. Fast Field Updates: Update triggering record fields only
  3. Simple Calculations: Basic field calculations and defaulting
  4. No DML: No DML operations on other objects
  5. No Callouts: No callouts or Platform Events

After-Save Flow Structure:

  1. Entry Criteria: Strict criteria matching specific conditions
  2. First Decision Node: Route by context (New vs Update, Channel, Person Type)
  3. Subflows: Extract complex tasks into Subflows
  4. Related Record Operations: Create/update/delete related records
  5. Integration Calls: Call Apex actions for integrations
  6. Platform Event Publishing: Publish events for event-driven architecture
  7. Error Handling: Fault paths for all operations

Screen Flows

Guided Data Capture: Screen Flows provide step-by-step user interactions for complex processes.

Use Cases:

Best Practices:

Real Example: Mid_Point_Evaluation_Screen_Flow - Guided evaluation process sending 29,004 emails (83.9% of automated emails in one org).

Screen Flow Structure Pattern:

  1. Introduction Screen: Welcome message and instructions
  2. Data Collection Screens: Step-by-step data input with validation
  3. Decision Nodes: Route based on user input
  4. Review Screen: Summary of collected data
  5. Confirmation Screen: Success message and next steps
  6. Error Handling: User-friendly error messages

Scheduled Flows

Periodic Operations: Scheduled Flows run on a schedule for batch operations.

Use Cases:

Best Practices:

Scheduled Flow Structure Pattern:

  1. Entry Criteria: Filter records to process
  2. Decision Node: Route by record state or criteria
  3. Batch Processing: Process records in collections
  4. Error Handling: Log errors and continue processing
  5. Completion Logic: Update status and send notifications

Auto-Launched Flows

Reusable Logic: Auto-Launched Flows are called from other Flows or Apex for reusable logic.

Use Cases:

Best Practices:

Auto-Launched Flow Structure Pattern:

  1. Input Variables: Define required and optional inputs
  2. Logic: Reusable business logic
  3. Output Variables: Return results to caller
  4. Error Handling: Return error information to caller

Subflows

Reusable Logic Chunks: Subflows extract logical chunks into reusable components.

Use Cases:

Benefits:

Best Practices:

Subflow Structure Pattern:

  1. Input Variables: Define inputs needed by Subflow
  2. Reusable Logic: Common logic used by multiple flows
  3. Output Variables: Return results to caller
  4. Error Handling: Handle errors and return status

Flow Naming Conventions

Real Naming Pattern: Based on actual implementation experience across enterprise projects.

Format: {Type}_{Object}_{Trigger}_{Description}

Components:

Real Examples:

Flow Structure Patterns

Entry Criteria

Strict Entry Criteria: Avoid “run on every change, then decide inside” - use entry criteria to filter at the trigger point.

Best Practice: Set entry criteria to match the specific conditions where the flow should run, reducing unnecessary executions.

Benefits:

Example: Instead of running on all Case updates and checking status inside, set entry criteria to Status = 'New' if the flow only needs to run when status is New.

Entry Criteria Patterns:

Decision Logic

Separation of Concerns: Use decision nodes to route by record state, channel, person type, or other criteria.

Pattern: Route early, handle specific cases in separate branches.

Decision Node Routing Pattern:

  1. First Decision: Route by IsNew (New vs Update)
  2. Second Decision: Route by Record Type or Channel
  3. Third Decision: Route by Status or Person Type
  4. Specific Branches: Handle each case in separate branches

Example: Route by IsNew (New vs Update), then by record type, then by status.

Decision Node Best Practices:

Subflows for Complex Tasks

Extract Logical Chunks: Extract complex logic into Subflows for reuse and easier testing.

Pattern: Identify repeated logic patterns and extract them into Subflows.

Common Subflow Patterns:

When to Extract to Subflow:

DML Operations

Minimal DML: Use fast field updates when possible, aggregate logic to reduce DML operations.

Best Practices:

DML Optimization Patterns:

Order of Execution Context

Understanding Execution Order: Flows execute at specific points in the Salesforce order of execution.

Before-Save Flows Execution

Execution Point: Step 4 in order of execution (after system validation, before custom validation rules)

Execution Order:

  1. System validation rules
  2. Before-save triggers
  3. Before-save flows
  4. Custom validation rules
  5. Record save
  6. After-save triggers
  7. After-save flows

Key Points:

After-Save Flows Execution

Execution Point: Step 7 in order of execution (after record save, after after-save triggers)

Execution Order:

  1. System validation rules
  2. Before-save triggers
  3. Before-save flows
  4. Custom validation rules
  5. Record save
  6. After-save triggers
  7. After-save flows

Key Points:

See Also: Order of Execution for complete execution order details.

Flow Elements Reference

This section provides comprehensive coverage of all Flow elements, including what each element does, when to use it, how to use it, naming conventions, examples, and best practices.

Get Records Element

What It Does: Retrieves records from the database using SOQL queries. Can retrieve single records or collections of records based on criteria.

When to Use:

When NOT to Use:

How to Use:

  1. Add Get Records element to flow
  2. Select object to query
  3. Set filter conditions (WHERE clause)
  4. Select fields to retrieve
  5. Choose how many records to retrieve (First, All, or specific number)
  6. Store results in a variable (single record or collection)

Naming Conventions:

Examples:

Example 1: Get Single Parent Record

Example 2: Get Collection of Related Records

Example 3: Check if Record Exists

Best Practices:

Anti-Patterns:

Governor Limit Impact:

Assignment Element

What It Does: Assigns values to variables, including field values, formulas, and expressions. Can assign multiple values in a single element.

When to Use:

When NOT to Use:

How to Use:

  1. Add Assignment element to flow
  2. Select variable or field to assign
  3. Set value using formula, expression, or reference
  4. Add multiple assignments in single element
  5. Use formulas for calculations and transformations

Naming Conventions:

Examples:

Example 1: Calculate Full Name

Example 2: Calculate Total Amount

Example 3: Build Email Body

Example 4: Set Multiple Values

Best Practices:

Anti-Patterns:

Decision Element

What It Does: Routes flow execution based on conditions. Evaluates conditions and directs flow to different paths based on outcomes.

When to Use:

When NOT to Use:

How to Use:

  1. Add Decision element to flow
  2. Add outcomes (conditions to evaluate)
  3. Set condition for each outcome
  4. Set default outcome (when no conditions match)
  5. Connect outcomes to next elements

Naming Conventions:

Examples:

Example 1: Route by Record State

Example 2: Route by Status

Example 3: Route by Priority

Example 4: Route by Multiple Conditions

Best Practices:

Anti-Patterns:

Loop Element

What It Does: Iterates through a collection of records or items, executing elements inside the loop for each item.

When to Use:

When NOT to Use:

How to Use:

  1. Add Loop element to flow
  2. Select collection variable to iterate
  3. Set loop variable name (single item from collection)
  4. Add elements inside loop to process each item
  5. Use loop variable to access current item

Naming Conventions:

Examples:

Example 1: Process Related Records

Example 2: Aggregate Values

Example 3: Create Related Records

Example 4: NPSP Opportunity Payment Calculation

Example 5: NPSP Campaign Total Calculation

Best Practices:

Anti-Patterns:

Governor Limit Impact:

Create Records Element

What It Does: Creates new records in the database. Can create single records or multiple records in bulk.

When to Use:

When NOT to Use:

How to Use:

  1. Add Create Records element to flow
  2. Select object to create
  3. Set field values (use Assignment element to prepare values)
  4. Choose how many records to create (single or multiple)
  5. Store created record IDs in variables
  6. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Create Single Related Record

Example 2: Create Multiple Records from Collection

Example 3: Create Child Records

Best Practices:

Anti-Patterns:

Governor Limit Impact:

Update Records Element

What It Does: Updates existing records in the database. Can update single records or multiple records in bulk.

When to Use:

When NOT to Use:

How to Use:

  1. Add Update Records element to flow
  2. Select records to update (from variable or collection)
  3. Set field values to update
  4. Choose how many records to update (single or multiple)
  5. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Update Single Related Record

Example 2: Update Multiple Records from Collection

Example 3: Update Triggering Record

Best Practices:

Anti-Patterns:

Governor Limit Impact:

Delete Records Element

What It Does: Deletes records from the database. Can delete single records or multiple records in bulk.

When to Use:

When NOT to Use:

How to Use:

  1. Add Delete Records element to flow
  2. Select records to delete (from variable or collection)
  3. Choose how many records to delete (single or multiple)
  4. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Delete Single Related Record

Example 2: Delete Multiple Records from Collection

Example 3: Delete Child Records

Best Practices:

Anti-Patterns:

Governor Limit Impact:

Fast Field Updates (Before-Save Only)

What It Does: Updates field values on the triggering record before it is saved. More efficient than Update Records for simple field updates.

When to Use:

When NOT to Use:

How to Use:

  1. Add Fast Field Update element to flow (before-save only)
  2. Select field to update
  3. Set field value using formula or reference
  4. Add multiple fast field updates as needed

Naming Conventions:

Examples:

Example 1: Set Default Values

Example 2: Calculate Field Value

Example 3: Normalize Field Value

Best Practices:

Anti-Patterns:

Apex Action Element

What It Does: Calls Apex methods marked with @InvocableMethod from Flows. Enables integration between declarative and programmatic automation.

When to Use:

When NOT to Use:

How to Use:

  1. Create Apex class with @InvocableMethod
  2. Add Apex Action element to flow
  3. Select Apex class and method
  4. Set input parameters
  5. Store output in variables
  6. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Retry Logic

Example 2: External API Call

Example 3: Complex Calculation

Best Practices:

Anti-Patterns:

Subflow Element

What It Does: Calls another Flow (Subflow) from the current Flow. Enables reusable logic and modular flow design.

When to Use:

When NOT to Use:

How to Use:

  1. Create Subflow with input/output variables
  2. Add Subflow element to flow
  3. Select Subflow to call
  4. Set input variable values
  5. Store output variable values
  6. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Reusable Task Creation

Example 2: Reusable Assignment Logic

Example 3: Reusable Validation

Best Practices:

Anti-Patterns:

Platform Event Element

What It Does: Publishes Platform Events from Flows. Enables event-driven architecture and decoupling.

When to Use:

When NOT to Use:

How to Use:

  1. Add Platform Event element to flow
  2. Select Platform Event type
  3. Set event field values
  4. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Application Submission Event

Example 2: Status Change Event

Best Practices:

Anti-Patterns:

See Also: Event-Driven Architecture for complete event-driven patterns.

Email Action Element

What It Does: Sends email from Flows. Can send email alerts, email templates, or compose emails.

When to Use:

When NOT to Use:

How to Use:

  1. Add Email Action element to flow
  2. Choose email type (Alert, Template, or Compose)
  3. Set recipients
  4. Set email content
  5. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Email Alert

Example 2: Email Template

Example 3: Composed Email

Best Practices:

Anti-Patterns:

Post to Chatter Element

What It Does: Posts messages to Chatter from Flows. Can post to records, users, or groups.

When to Use:

When NOT to Use:

How to Use:

  1. Add Post to Chatter element to flow
  2. Set message content
  3. Set target (record, user, or group)
  4. Configure fault path for error handling

Naming Conventions:

Examples:

Example 1: Post to Record

Example 2: Post to User

Best Practices:

Wait Element

What It Does: Pauses flow execution for a specified duration or until a condition is met. Used in scheduled flows and screen flows.

When to Use:

When NOT to Use:

How to Use:

  1. Add Wait element to flow
  2. Choose wait type (duration or condition)
  3. Set wait duration or condition
  4. Continue flow after wait

Naming Conventions:

Examples:

Example 1: Wait Duration

Example 2: Wait for Condition

Best Practices:

Anti-Patterns:

Screen Elements (Screen Flows Only)

Screen Flows include specialized elements for user interaction. These elements are only available in Screen Flows.

Screen Element

What It Does: Displays a screen to the user with input fields, text, and navigation buttons.

When to Use:

How to Use:

  1. Add Screen element to flow
  2. Add components (input fields, text, buttons)
  3. Set field labels and help text
  4. Configure navigation (Next, Back, Finish)
  5. Set screen visibility conditions

Naming Conventions:

Screen Components:

Best Practices:

Choice (Radio Buttons / Dropdown)

What It Does: Displays choices to users as radio buttons or dropdown menus.

When to Use:

How to Use:

  1. Add Choice component to screen
  2. Define choice options
  3. Set default selection
  4. Store selected value in variable
  5. Use choice value in decision logic

Naming Conventions:

Examples:

Example 1: Priority Selection

Example 2: Status Selection

Best Practices:

Multi-Select Choice

What It Does: Allows users to select multiple options from a list.

When to Use:

How to Use:

  1. Add Multi-Select Choice component to screen
  2. Define choice options
  3. Store selected values in collection variable
  4. Use collection in decision logic or loops

Naming Conventions:

Best Practices:

Formula Element

What It Does: Calculates values using formulas. Can be used in Assignment elements, Decision elements, and field updates.

When to Use:

How to Use:

  1. Use formula in Assignment, Decision, or field update
  2. Reference variables and field values
  3. Use formula functions
  4. Store calculated value in variable or field

Naming Conventions:

Common Formula Patterns:

Pattern 1: String Concatenation

{!$Record.FirstName} & ' ' & {!$Record.LastName}

Pattern 2: Conditional Logic

IF({!$Record.Priority} = 'High', TODAY() + 1, TODAY() + 7)

Pattern 3: Date Calculation

TODAY() + 30
NOW() + 1

Pattern 4: Null Handling

IF(ISBLANK({!$Record.CustomField}), 'Default', {!$Record.CustomField})

Pattern 5: Case Logic

CASE({!$Record.Status}, 
  'New', 'New Case',
  'In Progress', 'Active Case',
  'Closed', 'Completed Case',
  'Other'
)

Best Practices:

Anti-Patterns:

Collection Operations

What It Does: Operations on collections (lists) of records or values.

When to Use:

Collection Functions:

Examples:

Example 1: Count Related Records

Example 2: Sum Line Items

Example 3: Find Maximum Value

Best Practices:

Advanced Flow Patterns

Bulk Processing Pattern

Pattern: Process records in bulk to minimize governor limit usage.

Structure:

  1. Get Records: Retrieve all records to process
  2. Loop: Iterate through collection
  3. Assignment: Prepare records for bulk operation
  4. Create/Update Records: Bulk operation outside loop

Example:

Get Records: Get all Contacts to update
Loop: For each Contact
  Assignment: Set Department = Account.Department
  Add to collection: ContactsToUpdate
End Loop
Update Records: Update ContactsToUpdate (bulk)

Best Practices:

Relationship Query Pattern

Pattern: Use relationship queries to avoid multiple Get Records elements.

Structure:

  1. Get Records: Query parent record with related records
  2. Access related records via relationship
  3. Process related records in loop

Example:

Get Records: Account with Contacts (relationship query)
  Fields: Account fields + Contacts (relationship)
Loop: For each Contact in Account.Contacts
  Process Contact
End Loop

Best Practices:

Error Handling Pattern

Pattern: Comprehensive error handling with logging and fallback.

Structure:

  1. Configure fault paths for all operations
  2. Log errors to LOG_LogMessage__c
  3. Use Platform Event fallback if DML fails
  4. Provide user-friendly error messages

Example:

Create Records: Create Task
  Fault Path:
    Assignment: Set ErrorMessage
    Apex Action: LOG_LogMessageUtility.logError
      Fault Path:
        Platform Event: Publish ErrorLog__e
    Screen: Show Error Message

Best Practices:

Recursion Prevention Pattern

Pattern: Prevent Flow from triggering itself recursively.

Structure:

  1. Entry Criteria: Use ISCHANGED() to detect specific changes
  2. Decision: Check if value actually changed
  3. Assignment: Only update if value changed

Example:

Entry Criteria: ISCHANGED(Status) AND Status = 'Closed'
Decision: Check if Status was already 'Closed'
  If No: Update related records
  If Yes: Skip (prevent recursion)

Best Practices:

Comprehensive Naming Conventions

Flow Naming Conventions

Format: {Type}_{Object}_{Trigger}_{Description}

Type Prefixes:

Object Abbreviations:

Trigger Type (Record-Triggered only):

Examples:

Variable Naming Conventions

Single Record Variables:

Collection Variables:

Calculated Values:

Choice Variables:

Input/Output Variables:

Element Naming Conventions

Get Records:

Assignment:

Decision:

Loop:

Create Records:

Update Records:

Delete Records:

Apex Action:

Subflow:

Platform Event:

Email:

Screen:

Wait:

Integration Patterns

Platform Events from Flows

Preferred Pattern: Platform Events published from Flows (preferred over Apex) for declarative event publication.

Use Cases:

Pattern: Use Flow’s “Publish Platform Event” action to publish events declaratively.

Best Practices:

Real Example: Platform Events published from Flows for SIS integration events, routed to external event bus (EventBridge reference architecture).

Event Payload Design:

See Also: Event-Driven Architecture for complete event-driven patterns.

Invocable Methods

Apex Integration: Use @InvocableMethod to make Apex methods callable from Flows.

Use Cases:

Real Examples:

Pattern: Create Apex classes with @InvocableMethod for Flow integration, keeping business logic in Apex while enabling declarative orchestration.

Invocable Method Requirements:

Example:

public class ContactRetryUpdateService {
    @InvocableMethod(label='Retry Contact Update' description='Retries Contact update with exponential backoff')
    public static List<Result> retryUpdate(List<Request> requests) {
        List<Result> results = new List<Result>();
        for (Request req : requests) {
            // Retry logic with exponential backoff
            Result res = new Result();
            // ... implementation
            results.add(res);
        }
        return results;
    }
    
    public class Request {
        @InvocableVariable(label='Contact IDs' required=true)
        public List<Id> contactIds;
    }
    
    public class Result {
        @InvocableVariable(label='Success')
        public Boolean success;
        @InvocableVariable(label='Error Message')
        public String errorMessage;
    }
}

Callable Interface

Flexible Integration: Use Callable interface for classes that need to be callable from both Flows and Apex.

Use Cases:

Real Examples:

Pattern: Implement Callable interface when class needs to be callable from both Flows and Apex, providing flexibility in how the class is invoked.

Callable Interface Implementation:

public class LOG_LogMessageUtility implements Callable {
    public Object call(String action, Map<String, Object> args) {
        switch on action {
            when 'logError' {
                return logError(args);
            }
            when 'logInfo' {
                return logInfo(args);
            }
            when else {
                throw new IllegalArgumentException('Unknown action: ' + action);
            }
        }
    }
    
    private Object logError(Map<String, Object> args) {
        // Error logging implementation
        return true;
    }
}

Service Layer Pattern

Separation of Concerns: Separate business logic into service classes that can be called from Flows and LWCs.

Pattern: Create service classes with @InvocableMethod or Callable interface for Flow integration.

Real Examples:

Benefits:

Error Handling Patterns

Error Handling in Flows

Comprehensive Error Handling: All errors must be handled gracefully in Flows.

Patterns:

Real Example: LOG_LogMessageUtility class implementing Callable interface for error logging from Flows, with Platform Event fallback if DML fails.

Error Handling Best Practices:

Fault Path Configuration:

Platform Event Fallback

DML Failure Handling: If DML fails (governor limits, validation rules), publish Platform Event as fallback to ensure error is still captured.

Pattern: Use Platform Events as fallback mechanism when DML operations fail.

Real Example: LOG_LogMessageUtility publishes ErrorLog__e Platform Event on DML exceptions, ensuring errors are captured even when DML fails.

Fallback Pattern:

  1. Attempt to log error to LOG_LogMessage__c object
  2. If DML fails, publish ErrorLog__e Platform Event
  3. Platform Event subscriber processes error asynchronously
  4. Error is captured even when DML fails

See Also: Error Handling and Logging for complete error handling patterns.

Performance and Governor Limits

Governor Limits in Flows

Understanding Limits: Flows share the same governor limits as Apex within a transaction.

Key Limits:

Best Practices:

Performance Optimization

Optimization Strategies:

Performance Monitoring:

See Also: Governor Limits and Optimization for complete performance patterns.

Testing Patterns

Flow Testing Best Practices

Testing Requirements:

Testing Patterns:

Testing Checklist:

See Also: Automated Testing Patterns for complete testing strategies.

Troubleshooting

Common Flow Issues

Issue: Flow Not Running

Issue: Flow Running Too Often

Issue: Flow Performance Issues

Issue: Flow Errors

Debugging Flows

Debug Tools:

Debug Best Practices:

Change Management

Version Control

Version Control All Flows: All Flows must be version controlled and tracked in source control.

Best Practice:

Testing

Test Thoroughly: Test Flows thoroughly before deployment, including edge cases and error scenarios.

Best Practice:

Documentation

Document Purpose and Business Logic: Document Flow purpose, business logic, and entry criteria.

Best Practice:

Coordination

Coordinate Changes: Coordinate Flow changes with related automation (other Flows, Apex, Process Builder, Workflow Rules).

Best Practice:

Real-World Examples

Example 1: Application Status Orchestration

Flow: App_AfterSave_ApplicationStatusOrchestration

Type: Record-Triggered Flow (After Save)

Purpose: Orchestrates application status changes and related record updates

Entry Criteria: Record Type = 'Application' AND ISCHANGED(Status)

Pattern:

Structure:

  1. Entry Criteria: Status changed on Application
  2. First Decision: Route by Status value
  3. Subflow: “Create Advisor Tasks” for specific statuses
  4. Subflow: “Sync Application Status to Child Objects”
  5. Action: Publish Platform Event with application data
  6. Action: Send email notification

Example 2: Case Defaulting

Flow: Case_BeforeSave_Defaulting

Type: Record-Triggered Flow (Before Save)

Purpose: Sets default values on Case creation

Entry Criteria: Record Type = 'Support Case' AND ISNEW()

Pattern:

Structure:

  1. Entry Criteria: New Case with specific Record Type
  2. Fast Field Update: Set Priority = ‘Medium’ if null
  3. Fast Field Update: Set Owner = Queue if null
  4. Fast Field Update: Calculate Due Date based on SLA

Example 3: Account Value Updates

Flow: RT_C_BS_Update_Account_Values_from_Parent_Account_Academic_Programs

Type: Record-Triggered Flow (Before Save)

Purpose: Updates Account values from parent Account Academic Programs

Entry Criteria: Record Type = 'Academic Program' AND Parent Account != null AND ISNEW()

Pattern:

Structure:

  1. Entry Criteria: New Academic Program with Parent Account
  2. Get Records: Get Parent Account with related fields
  3. Fast Field Update: Update Account fields from Parent Account
  4. Fast Field Update: Set derived fields based on Parent Account

Example 4: Screen Flow - Mid-Point Evaluation

Flow: Screen_Mid_Point_Evaluation

Type: Screen Flow

Purpose: Guided evaluation process for student mid-point evaluations

Real Impact: Sending 29,004 emails (83.9% of automated emails in one org)

Structure:

  1. Introduction Screen: Welcome and instructions
  2. Data Collection Screens: Step-by-step evaluation input
  3. Decision Nodes: Route based on evaluation responses
  4. Review Screen: Summary of evaluation data
  5. Confirmation Screen: Success message and next steps
  6. Email Action: Send evaluation confirmation email

Edge Cases and Limitations

Before-Save Flow Limitations

Limitations:

Workarounds:

After-Save Flow Limitations

Limitations:

Workarounds:

Flow Recursion Prevention

Prevention Patterns:

Example Pattern:

Entry Criteria: ISCHANGED(Status) AND Status = 'Closed'
Logic:
  - Check if Status was already 'Closed' (prevent recursion)
  - Only update if Status actually changed
  - Use decision node to prevent unnecessary updates

Governor Limit Considerations

Common Limit Issues:

Solutions:

Best Practices Summary

Flow Design

Error Handling

Performance

Integration

Testing

Maintenance

Q&A

Q: When should I use Flow instead of Apex?

A: Use Flow when logic can be expressed declaratively, you need to create/update related records based on record changes, need guided user interactions, or need to publish Platform Events. Flow is preferred for declarative automation; Apex is for complex logic that Flow cannot handle efficiently.

Q: What is the difference between Before-Save and After-Save Flows?

A: Before-Save Flows update triggering record fields only and run before the record is saved. After-Save Flows handle related records, integrations, and events and run after the record is saved. Use Before-Save for field defaulting and validation; use After-Save for related records and integrations.

Q: Can I modify field values in After-Save Flows?

A: No, records are read-only in After-Save Flows. You cannot modify field values in After-Save Flows. To modify field values, use Before-Save Flows or create an After-Save Flow that updates the record (which will trigger another flow execution).

Q: Can I perform DML operations in Before-Save Flows?

A: No, Before-Save Flows cannot perform DML operations on other records. You can only modify field values on the triggering record. To perform DML on other records, use After-Save Flows or async processing (Platform Events, Queueable).

Q: How do I make Apex methods callable from Flows?

A: Use @InvocableMethod annotation on static methods in public classes. Methods must accept and return lists (even for single values). Use @InvocableVariable for complex input parameters. Alternatively, implement Callable interface for classes that need to be callable from both Flows and Apex.

Q: How do I handle errors in Flows?

A: Use fault paths for error handling, log errors to LOG_LogMessage__c object using LOG_LogMessageUtility class (implements Callable interface), use Platform Event fallback if DML fails, and provide user-friendly error messages.

Q: What is the best naming convention for Flows?

A: Use format {Type}_{Object}_{Trigger}_{Description} where Type is RT_ (Record-Triggered), Screen_, Scheduled_, or Auto_; Object is abbreviation like C_ (Case), App_ (Application); Trigger is BS_ (Before Save) or AS_ (After Save); and Description is what the flow does.

Q: When should I use Subflows?

A: Use Subflows for reusable logic chunks like assignment rules, task creation, status updates, common validation logic, or reusable decision logic. Subflows enable easier testing, easier maintenance, and clearer flow structure.

Q: How do I publish Platform Events from Flows?

A: Use Flow’s “Publish Platform Event” action to publish events declaratively. This is preferred over Apex for declarative event publication. Include all necessary context in event payloads, minimize PII, and design payloads to be idempotent where possible.

Q: What is the Platform Event fallback pattern?

A: If DML fails (governor limits, validation rules), publish Platform Event as fallback to ensure error is still captured. This pattern ensures errors are captured even when DML operations fail, using ErrorLog__e Platform Event as fallback mechanism.

Q: How do I prevent Flow recursion?

A: Prevent Flow recursion by checking if field values have actually changed before performing updates, using entry criteria with ISCHANGED() to detect specific changes, avoiding update operations that would re-trigger the same flow, and using decision nodes to prevent unnecessary updates.

Q: What are the governor limits for Flows?

A: Flows share the same governor limits as Apex: 100 SOQL queries, 150 DML operations, 10,000ms CPU time, 6MB heap (synchronous), 12MB heap (asynchronous), and 100 callouts (async only) per transaction.

Q: How do I optimize Flow performance?

A: Optimize Flow performance by using strict entry criteria, minimizing SOQL queries (use relationship queries), aggregating DML operations (use collections), using fast field updates when possible, moving heavy operations to async processing, and monitoring governor limit usage.

Q: How do I test Flows?

A: Test Flows with various data scenarios, test error handling paths, test with bulk data (200+ records), test edge cases and boundary conditions, test integration points, and coordinate testing with related automation.

Q: What is the execution order of Flows?

A: Before-Save Flows execute at step 4 (after system validation, before custom validation rules). After-Save Flows execute at step 7 (after record save, after after-save triggers). See Order of Execution for complete details.

Q: Can I make callouts from Before-Save Flows?

A: No, Before-Save Flows cannot make callouts. Use After-Save Flows or async processing (Platform Events, Queueable) for callouts.

Q: How do I handle bulk operations in Flows?

A: Handle bulk operations by processing records in collections, aggregating DML operations, using relationship queries to avoid multiple queries, testing with 200+ records, and moving heavy operations to async processing when needed.