Three primitives, one shared icon family, and dramatically different runtime behavior. Most Flow Designer messes I inherit started with someone reaching for a Subflow when an Action would have shipped in a third of the time.
The actual differences that matter
| Concern | Action | Subflow | Script Step |
|---|---|---|---|
| Reusability | Across flows and scopes | Across flows, same scope | None |
| Inputs/outputs | Strongly typed | Strongly typed | Untyped |
| Error handling | Per-step | Stage and step | Try/catch only |
| Test harness | Yes, in builder | Yes, with mocks | No |
| Visible to citizen devs | Yes | Yes | No |
Pick Action when the work is composable
If the unit of work has a clear input contract, a clear output contract, and is something more than one flow will ever call, build an Action. Actions are the only artifact you can publish across scopes and the only one IntegrationHub treats as first-class.
Pick Subflow when state matters across calls
Subflows preserve flow context — trigger.current, stage data, the operating user. If the work needs to record stages on the parent, sit inside the parent’s transaction, or wait for an event mid-execution, you need a Subflow.
Pick Script Step only when the API is awkward
A Script Step is the right call exactly when the platform Action you would write is just a thin wrapper around a gs.eventQueue or a GlideAggregate. Anywhere else, the lack of input typing and the lack of a test harness will burn you on the next upgrade.
// Good: Script Step that only does what no Action can
(function execute(inputs, outputs) {
outputs.count = new GlideAggregate('incident')
.addQuery('assignment_group', inputs.group)
.getRowCount();
})(inputs, outputs);
The reusability test
Before you build, ask: “Will three flows call this in 12 months?” If yes, Action. If no, ask: “Does this need parent-flow context?” If yes, Subflow. Otherwise, Script Step and move on.
What to do this week
Pull every flow modified in the last 90 days. Find the ones with more than three Script Steps. Those are your refactor candidates — extract Actions, ship the test cases, move on.