Record-Triggered Flow Code Examples

Overview

Record-Triggered Flows are the primary automation tool in Salesforce for declarative automation. These examples demonstrate common patterns for:

When to Use

Use Record-Triggered Flows When

Avoid Record-Triggered Flows When

Example 1: Before-Save Flow - Field Defaulting

Use Case: Set default values on Case creation based on record type and other criteria.

Flow Name: Case_BeforeSave_Defaulting

Entry Criteria:

Record Type = 'Support Case' AND Status = 'New'

Flow Structure:

  1. Start Element: Record-Triggered Flow (Before Save)
    • Object: Case
    • Entry Criteria: RecordType.DeveloperName = 'Support_Case' AND Status = 'New'
    • Trigger: Create and Update
  2. Decision Node: Check Priority
    • Outcome 1: Priority = null → Set Priority to ‘Medium’
    • Outcome 2: Priority != null → Continue
  3. Assignment Element: Set Default Values
    • Priority = 'Medium' (if null)
    • OwnerId = {!$Record.OwnerId} (if null, assign to Queue)
    • Due_Date__c = TODAY() + 3 (calculate based on SLA)
  4. End Element: Save the record

Key Points:

Use Case: Create a Task when a Case is created with Priority = ‘High’.

Flow Name: Case_AfterSave_CreateHighPriorityTask

Entry Criteria:

Priority = 'High' AND ISNEW() = true

Flow Structure:

  1. Start Element: Record-Triggered Flow (After Save)
    • Object: Case
    • Entry Criteria: Priority = 'High' AND ISNEW() = true
    • Trigger: Create
  2. Create Records Element: Create Follow-up Task
    • Object: Task
    • How Many: One
    • Fields:
      • Subject = 'Follow up on High Priority Case ' & {!$Record.CaseNumber}
      • WhatId = {!$Record.Id}
      • Status = 'Not Started'
      • Priority = 'High'
      • ActivityDate = TODAY() + 1
    • Store In: NewTask (single record variable)
    • Fault Path: Log error and continue
  3. End Element: End the flow

Key Points:

Example 3: After-Save Flow - Route by Record State

Use Case: Orchestrate application status changes with different logic for new vs updated records.

Flow Name: App_AfterSave_ApplicationStatusOrchestration

Entry Criteria:

Record Type = 'Application' AND ISCHANGED(Status)

Flow Structure:

  1. Start Element: Record-Triggered Flow (After Save)
    • Object: Application__c (custom object)
    • Entry Criteria: RecordType.DeveloperName = 'Application' AND ISCHANGED(Status__c)
    • Trigger: Create and Update
  2. Decision Node: Route by Record State
    • Outcome 1: ISNEW() = true → New Application Path
    • Outcome 2: ISNEW() = false → Updated Application Path
  3. New Application Path:
    • Subflow: Subflow_Create_Advisor_Tasks
      • Input: ApplicationId = {!$Record.Id}
    • Create Records: Create Application History record
    • Publish Platform Event: ApplicationCreated__e
      • Fields: ApplicationId__c = {!$Record.Id}, Status__c = {!$Record.Status__c}
  4. Updated Application Path:
    • Decision Node: Route by Status
      • Outcome 1: Status__c = 'Approved' → Approved Path
      • Outcome 2: Status__c = 'Rejected' → Rejected Path
      • Outcome 3: Status__c = 'Pending' → Pending Path
    • Subflow: Subflow_Sync_Application_Status_to_Child_Objects
    • Send Email: Notify applicant of status change
  5. End Element: End the flow

Key Points:

Use Case: Create tasks for multiple Contacts when Account is updated.

Flow Name: Account_AfterSave_CreateContactTasks

Entry Criteria:

ISCHANGED(Status__c) AND Status__c = 'Active'

Flow Structure:

  1. Start Element: Record-Triggered Flow (After Save)
    • Object: Account
    • Entry Criteria: ISCHANGED(Status__c) AND Status__c = 'Active'
    • Trigger: Update
  2. Get Records Element: Get Related Contacts
    • Object: Contact
    • Filter: AccountId = {!$Record.Id} AND Active__c = true
    • Store In: RelatedContacts (collection variable)
    • Sort: None
  3. Loop Element: Prepare Tasks
    • Loop Through: RelatedContacts
    • Current Item: CurrentContact
    • Assignment Element: Add Task to Collection
      • Variable: TasksToCreate (collection variable, initialized empty)
      • Add Items:
        • Subject = 'Follow up with ' & {!CurrentContact.Name}
        • WhoId = {!CurrentContact.Id}
        • WhatId = {!$Record.Id}
        • Status = 'Not Started'
        • Priority = 'Medium'
        • ActivityDate = TODAY() + 7
  4. Create Records Element: Create Tasks in Bulk
    • Object: Task
    • How Many: Multiple
    • Records: TasksToCreate
    • Store In: CreatedTasks (collection variable)
    • Fault Path: Log errors and continue
  5. End Element: End the flow

Key Points:

Use Case: Update all related Cases when Account status changes to ‘Closed’.

Flow Name: Account_AfterSave_CloseRelatedCases

Entry Criteria:

ISCHANGED(Status__c) AND Status__c = 'Closed'

Flow Structure:

  1. Start Element: Record-Triggered Flow (After Save)
    • Object: Account
    • Entry Criteria: ISCHANGED(Status__c) AND Status__c = 'Closed'
    • Trigger: Update
  2. Get Records Element: Get Open Cases
    • Object: Case
    • Filter: AccountId = {!$Record.Id} AND Status != 'Closed'
    • Store In: OpenCases (collection variable)
  3. Decision Node: Check if Cases Exist
    • Outcome 1: OpenCases is not empty → Update Cases
    • Outcome 2: OpenCases is empty → End flow
  4. Update Records Element: Close All Cases
    • Records: OpenCases
    • How Many: Multiple
    • Fields:
      • Status = 'Closed'
      • ClosedDate = TODAY()
      • Reason = 'Account Closed'
    • Fault Path: Log errors and continue
  5. End Element: End the flow

Key Points:

Example 6: After-Save Flow - Platform Event Publishing

Use Case: Publish Platform Event when Application status changes for integration.

Flow Name: App_AfterSave_PublishStatusChangeEvent

Entry Criteria:

ISCHANGED(Status__c)

Flow Structure:

  1. Start Element: Record-Triggered Flow (After Save)
    • Object: Application__c
    • Entry Criteria: ISCHANGED(Status__c)
    • Trigger: Create and Update
  2. Publish Platform Events Element: Publish Status Change Event
    • Platform Event: ApplicationStatusChange__e
    • How Many: One
    • Fields:
      • ApplicationId__c = {!$Record.Id}
      • OldStatus__c = {!$Record.PRIORVALUE(Status__c)}
      • NewStatus__c = {!$Record.Status__c}
      • ChangedBy__c = {!$User.Id}
      • ChangedDate__c = NOW()
    • Store In: PublishedEvent (single record variable)
    • Fault Path: Log error and continue
  3. End Element: End the flow

Key Points:

Testing Considerations

Test Scenarios

  1. Before-Save Flows:
    • Test with null values (defaulting logic)
    • Test with existing values (no overwrite)
    • Test with bulk records (200+ records)
    • Verify save time impact (should be fast)
  2. After-Save Flows:
    • Test with single record creation
    • Test with bulk record creation (200+ records)
    • Test with related record queries (empty results, multiple results)
    • Test error scenarios (fault paths)
    • Test decision node routing (all paths)
  3. Common Edge Cases:
    • Empty collections (no related records)
    • Null field values
    • Record type changes
    • Status transitions (all valid transitions)
    • Concurrent updates (UNABLE_TO_LOCK_ROW)

Best Practices