Salesforce has come a long way from its days of relying on Workflow Rules and Process Builders for handling regular field updates. With the advent of Flows as the primary automation tool, many businesses have benefited from their power and flexibility. However, this shift has brought new challenges. Flows can become massive and complex, making it difficult to manage multiple record updates—both on the triggering record and related records identified during the process—in a scalable and clear way. Additionally, large Flows can easily hit Salesforce governor limits.

To address these challenges, adopting a decoupled architecture for record updates after-save can help. By leveraging a Platform Event framework for dynamic updates, you can create a scalable and reliable solution to handle field updates efficiently.

The benefit of a decoupled record update model is that a single record's transaction can publish many platform events, and each platform event will be handled asynchronously in its own separate transaction. This means the many updates to happen in the trigger record's transaction is far less likely to hit limits, by extricating each update into its own asynchronous transaction.

Who Is This For?

This framework is designed for:

  • Salesforce Architects and Developers: Working in environments with complex, multi-object field update requirements.
  • Organizations with Decoupled Systems: Needing to synchronize data between Salesforce and external systems in real time.
  • Admins Looking for Scalability: Seeking a centralized, reusable solution for managing dynamic updates.

Who Is This Not For?

  • Small Organizations with Simple Workflows: If field updates are static and predictable, simpler solutions like standard after-save Flows or Triggers are sufficient.
  • Teams Requiring Immediate Updates: If synchronous processing is critical, such as in high-stakes transactional systems, Apex Triggers or before-save Flows are more suitable.

Why Use a Dynamic Update Framework?

  1. Flexibility: Handle updates for any object and field dynamically using the same framework.
  2. Decoupled Logic: Reduce system strain by separating the update logic from the transaction.
  3. Error Resilience: Take advantage of Platform Event replay functionality to ensure updates aren’t lost.
  4. Centralized Maintenance: Simplify troubleshooting and enhancements by managing updates through a single framework.

How to Implement the Dynamic Update Framework

Step 1: Define the Platform Event Structure

Create a Platform Event called DynamicFieldUpdate__e. This event will carry the necessary data to identify the record, field, and new value for the update.

Fields for DynamicFieldUpdate__e:

Field Name Data Type Description
RecordId__c Text(18) The ID of the record to update.
FieldApiName__c Text(255) The API name of the field to update (e.g., Account.Name).
NewValue__c Text(255) The new value to set for the specified field.
ObjectName__c Text(50) (Optional) Name of the object for additional validation.

Step 2: Publish Platform Events

Platform Events can be published via Apex or declaratively using Flows.

Example Apex Code for Publishing Events:

public static void publishFieldUpdate(String recordId, String fieldApiName, String newValue) {
    DynamicFieldUpdate__e event = new DynamicFieldUpdate__e(
        RecordId__c = recordId,
        FieldApiName__c = fieldApiName,
        NewValue__c = newValue
    );
    EventBus.publish(event);
}

Using Flows to Publish Events:

  1. Use the Create Records action.
  2. Select the Platform Event object (DynamicFieldUpdate__e).
  3. Map the values for RecordId__c, FieldApiName__c, and NewValue__c.

Step 3: Create an Event Listener

The listener processes the event and performs the required updates. You can use either a Flow triggered by Platform Events or an Apex Trigger for more complex scenarios.

Example Apex Trigger:

trigger DynamicFieldUpdateTrigger on DynamicFieldUpdate__e (after insert) {
    for (DynamicFieldUpdate__e event : Trigger.new) {
        try {
            // Get the record to update
            String recordId = event.RecordId__c;
            String fieldApiName = event.FieldApiName__c;
            String newValue = event.NewValue__c;

            // Retrieve the record dynamically
            SObject recordToUpdate = [SELECT Id FROM sObject WHERE Id = :recordId LIMIT 1];
            
            // Update the field value dynamically
            recordToUpdate.put(fieldApiName, newValue);

            // Save the record
            update recordToUpdate;
        } catch (Exception e) {
            System.debug('Error processing event: ' + e.getMessage());
        }
    }
}

Declarative Listener Using Flow:

  1. Trigger the Flow: Start with the DynamicFieldUpdate__e Platform Event.
  2. Retrieve the Record: Fetch the record using RecordId__c.
  3. Invocable Apex: Flow does not support dynamic fields to be updated in a single element. This would require a Decision element splitting off to every possible outcome, and each branch having its own unique Update element to update the right field. This is not scalable at all. Instead, you will need to use invocable Apex within the flow to process the record update. The Flow will simply serve as the trigger to listen for the platform event, then will pass the platform event's attributes into the invocable Apex to handle the update DML.

    Here is an example of what this invocable Apex could look like:
@InvocableMethod
public static void handleDynamicUpdates(List<DynamicFieldUpdateWrapper> updates) {
    for (DynamicFieldUpdateWrapper update : updates) {
        try {
            // Retrieve the record
            SObject recordToUpdate = Database.query(
                'SELECT Id FROM ' + update.objectName + ' WHERE Id = :update.recordId LIMIT 1'
            );
            
            // Dynamically set the field value
            recordToUpdate.put(update.fieldApiName, update.newValue);
            
            // Update the record
            update recordToUpdate;

        } catch (Exception e) {
            System.debug('Error updating record: ' + e.getMessage());
        }
    }
}

public class DynamicFieldUpdateWrapper {
    @InvocableVariable(required=true)
    public String recordId;
    
    @InvocableVariable(required=true)
    public String fieldApiName;

    @InvocableVariable(required=true)
    public String newValue;

    @InvocableVariable(required=true)
    public String objectName;
}


Step 4: Test and Validate

  1. Publish sample Platform Events with test data.
  2. Monitor debug logs and event replays for validation.
  3. Ensure the framework handles edge cases, such as:
    • Invalid field names.
    • Data type mismatches.
    • Missing records.

Advantages of This Approach

  • Flexibility: A single Platform Event can handle updates for multiple objects and fields.
  • Scalability: Decoupled processing reduces strain on Salesforce’s synchronous limits.
  • Error Handling: Use Platform Event replay capabilities for enhanced reliability.
  • Centralized Maintenance: Simplify debugging and system evolution.

Potential Drawbacks

  • Performance: Handling large event volumes can introduce latency.
  • Governor Limits: Listeners (Flow or Apex) are still bound by Salesforce governor limits.
  • Complexity: Implementing a dynamic framework requires advanced Apex knowledge.
  • Error Risk: Dynamic updates may fail if field names are incorrect or data types mismatch.

When to Use This Framework

Ideal Use Cases:

  • Dynamic Business Processes: When field updates vary across objects based on real-time conditions.
  • Decoupled Systems: Synchronizing data between Salesforce and external applications.
  • Complex Update Logic: When updates depend on advanced or conditional logic.

Avoid This Approach If:

  • Immediate Processing is Critical: Synchronous triggers are better for real-time needs.
  • Static Update Logic: Standard after-save Flows are simpler for predictable updates.

Conclusion

The Dynamic Update Framework using Platform Events offers a robust, scalable solution for managing complex field updates in Salesforce. By decoupling update logic and leveraging Salesforce’s asynchronous processing capabilities, this approach is ideal for dynamic, high-volume environments.

While it introduces some complexity, the flexibility and centralized management it provides make it a compelling choice for advanced use cases. For simpler workflows, however, static Flows or Apex Triggers may remain the better option.

Evaluate your business requirements carefully to determine whether this framework aligns with your goals, and enjoy the benefits of a more streamlined, resilient architecture.

Tagged in: