Complex business logic in Salesforce Screen Flows
Screen Flows are capable automation tools, but they hit a wall against complicated, conditional business rules. 'Assignment' and 'Decision' cover the basics. Past that, enterprise work wants logic the Flow UI cannot express without leaving you a canvas nobody can read.
1. Invocable methods for the heavy lifting
The cleanest way to inject complex logic into a Flow is @InvocableMethod. Complex calculations, heavy data transformation, calls out to an external service: don't try to build any of that from a dozen Flow elements. Write Apex.
Offloading the computation keeps the Flow canvas clean. Let the Flow manage the UI and let Apex handle the data state.
Implementation example
public class FlowBusinessLogicHandler {
@InvocableMethod(label='Process Complex Calculation' description='Executes proprietary logic')
public static List<Result> executeLogic(List<Request> inputs) {
List<Result> results = new List<Result>();
for (Request input : inputs) {
// Add your complex business rules here
Decimal score = (input.amount * 0.05) + (input.tenure * 10);
Result res = new Result();
res.calculatedScore = score;
results.add(res);
}
return results;
}
public class Request {
@InvocableVariable(required=true) public Decimal amount;
@InvocableVariable(required=true) public Integer tenure;
}
public class Result {
@InvocableVariable public Decimal calculatedScore;
}
}
2. Custom LWC components for dynamic UI logic
Sometimes the 'logic' you need is UI logic: disabling fields on the fly, running client-side validation, reacting to what the user types as they type it. Standard screen components in Flow are too coarse for that. Embed a Lightning Web Component (LWC) in the Flow screen and you control the whole experience.
Key steps to LWC integration
- Create an LWC that exposes properties via the
js-meta.xmlfile using the<targetConfigs>tag. - Use
flow-supportwithin your JavaScript to handle navigation. - Expose outputs to the Flow using
@apidecorators.
// lwcComponent.js
import { LightningElement, api } from 'lwc';
import { FlowAttributeChangeEvent } from 'lightning/flowSupport';
export default class CustomFlowInput extends LightningElement {
@api inputValue;
handleChange(event) {
this.inputValue = event.target.value;
// Dispatch event so Flow knows the value changed
const attributeChangeEvent = new FlowAttributeChangeEvent('inputValue', this.inputValue);
this.dispatchEvent(attributeChangeEvent);
}
}
3. The 'logic-only' Flow pattern
I have seen teams cram everything into one Flow, and what comes out the other end is the "spaghetti flow" nobody can debug. Use the 'Logic-Only' subflow pattern instead.
Build a dedicated 'Logic' Flow that takes parameters, runs the rules, and returns a result. Now you can unit test it independently of the UI Flow. It is the same idea as a 'service' layer in traditional software architecture.
- Maintainability: update the logic in one place and it propagates to every calling flow.
- Reusability: call the same subflow from Screen Flows, Record-Triggered Flows, or even Apex.
- Debugging: isolate the fault to the subflow or the screen component.
4. Working around limits with Platform Events
When logic should run asynchronously, or in a different context, without blocking the user, fire a Platform Event from the Screen Flow and let a separate 'Autolaunched Flow' or 'Apex Trigger' do the work. The user carries on while the external integration or the heavy update finishes on its own.
- Use a 'Create Records' element to publish the Platform Event.
- Configure an 'Event-Triggered Flow' to act as your backend engine.
Leave a Comment