Flow Versioning Strategy
The Model
Each flow has many versions; only one is active. Paused interviews
(long-running) pin to the version that started them. Versioning is not
just housekeeping — it is correctness.
Activation Policy
- New feature → create a new version, activate after test.
- Non-breaking fix → new version, same name, activate, retire the
previous after paused-interview drain window.
- Breaking change → NEW flow, not a new version. Paused interviews
cannot migrate between versions that break the contract.
Paused Interview Compatibility
A paused interview resumes on the version it started on. Breaking
changes that cannot survive a resume:
- Added required input variable.
- Removed or renamed variable still referenced downstream.
- Changed element output shape (collection → single, etc.).
- Changed decision paths in a way that strands the paused node.
If any of these is needed, route NEW traffic to a new flow and let the
old one drain.
Cleanup Cadence
- Retain the last 3 inactive versions (rollback depth).
- Delete a version only when zero interviews reference it. Age is a cheap
pre-filter for that condition, never a substitute — a paused interview resumes
on the version it started on, and since Spring '24 the org has no cap on how
many paused interviews accumulate.
- Size the retention window per flow from the observed interview lifetime. A
screen flow with an overnight pause and a scheduled flow with a 90-day wait
need different windows; one org-wide number is wrong for both.
- Cap total versions per flow at 10 by policy, so pruning happens on a calm
cadence rather than in response to a failed save.
The platform ceiling is 50 versions per flow — stated in the Visual
Workflow Implementation Guide's limits table, and the number Salesforce returns
in the save error ("Maximum number of Versions per flow is 50").
Breaking-Change Detection
The test is mechanical: if anything outside the flow has to change at the same
moment the flow changes, it is a new flow, not a new version. The contract
surface binds by name at run time — Apex Flow.Interview.createInterview,
lightning-flow with inputVariables, another flow's <subflows> input
assignments, quick actions, Experience Cloud pages — and nothing compiles over
it.
Before activating, diff against the current active version:
- Added required variables? → breaking.
- Renamed or removed variables still referenced by callers? → breaking.
- Changed element outputs on a path before a Pause? → breaking.
- Removed an element a paused interview could currently occupy? → breaking.
- Added a Pause at the top of a flow that previously completed inline? →
behaviour-changing; test callers.
- API version moved? → behaviour-changing. Flow behaviour is versioned, and
Flow Builder can bump the version on save. Crossing API 52.0 changes the
run-mode default; crossing 57.0 removes the executed-elements cap.
Querying the Right Object
Four objects answer four different questions, and picking the wrong one produces
"sObject type 'Flow' is not supported."
| Question |
Object |
API |
| Versions, their status, their definition |
Flow |
Tooling API |
| Which version is active per definition |
FlowDefinitionView |
Standard |
| Version metadata, read-only |
FlowVersionView |
Standard (46.0+) |
| Live and paused interviews |
FlowInterview |
Standard |
Flow version Status has five values: Active, Draft, Obsolete,
InvalidDraft, and UnderReview. None of them means "safe to delete," and the
API values do not match the UI labels — Draft and Obsolete both display as
Inactive, InvalidDraft displays as Draft, UnderReview as Under Review.
Filter cleanup queries on Status != 'Active' rather than enumerating the
inactive values, so a value you did not think of cannot fall out of the inventory.
Change Log
Keep a FLOWS_CHANGELOG.md or equivalent block in the flow's PR body:
Flow: CustomerOnboarding
From v12 → v13
- Added input variable `partnerAccountId` (optional, default null).
- Non-breaking. Paused interviews on v12 continue.
- Activate: after UAT sign-off.
- Retire v11: 2026-05-15.
Metrics To Watch
- Count of paused interviews per version.
- Age of oldest paused interview.
- Activations per week (high churn = unstable flow).
- Version count per flow.
Recommended Workflow
- Inventory the callers first, not last. Search the repository for the
flow's API name and for every input/output variable name it exposes. This is
the input to the decision, not a check afterwards.
- Apply the breaking-change test. Anything outside the flow that must change
at the same moment makes it a new flow. Otherwise, a new version.
- Capture the currently active version number, per environment, before
activating. It is the entire rollback plan.
- Activate, and write the changelog entry — breaking or not with the reason,
the callers checked, the live paused-interview count, and the rollback version
number.
- Roll back by activating the prior version, never by redeploying its
source. Redeploying creates a new version whose content matches the old one;
it does not restore the old one. Keep the bad version as evidence.
- Prune on the interview-reference condition, retaining at least three
inactive versions.
- Treat every subflow activation as a multi-caller production change. Search
the metadata for
<flowName> references before activating; resolution is late,
so the parent runs whatever version of the child is active at run time.
Official Sources Used
The full annotated list is in references/well-architected.md.
1---2name: flow-versioning-strategy3description: Manage Flow versions: activation policy, paused interview compatibility, cleanup cadence, and breaking-change detection. Trigger keywords: flow version management, activate flow version, paused interview, flow cleanup, flow breaking change, flow rollback. NOT for the deploy-time activation order of FlowDefinition metadata — use devops/flow-deployment-activation-ordering. NOT for moving a flow from sandbox to production — use flow/flow-deployment-and-packaging.4---56# Flow Versioning Strategy78## The Model910Each flow has many versions; only one is active. Paused interviews11(long-running) pin to the version that started them. Versioning is not12just housekeeping — it is correctness.1314## Activation Policy1516- **New feature** → create a new version, activate after test.17- **Non-breaking fix** → new version, same name, activate, retire the18 previous after paused-interview drain window.19- **Breaking change** → NEW flow, not a new version. Paused interviews20 cannot migrate between versions that break the contract.2122## Paused Interview Compatibility2324A paused interview resumes on the version it started on. Breaking25changes that cannot survive a resume:2627- Added required input variable.28- Removed or renamed variable still referenced downstream.29- Changed element output shape (collection → single, etc.).30- Changed decision paths in a way that strands the paused node.3132If any of these is needed, route NEW traffic to a new flow and let the33old one drain.3435## Cleanup Cadence3637- Retain the last 3 inactive versions (rollback depth).38- Delete a version only when **zero interviews reference it**. Age is a cheap39 pre-filter for that condition, never a substitute — a paused interview resumes40 on the version it started on, and since Spring '24 the org has no cap on how41 many paused interviews accumulate.42- Size the retention window per flow from the observed interview lifetime. A43 screen flow with an overnight pause and a scheduled flow with a 90-day wait44 need different windows; one org-wide number is wrong for both.45- Cap total versions per flow at 10 by policy, so pruning happens on a calm46 cadence rather than in response to a failed save.47 The platform ceiling is **50 versions per flow** — stated in the Visual48 Workflow Implementation Guide's limits table, and the number Salesforce returns49 in the save error ("Maximum number of Versions per flow is 50").50 <!-- PARTIALLY VERIFIED: 50 is corroborated by the Implementation Guide's table51 and by the runtime error text. What was not confirmed during authoring is52 whether the current General Flow Limits page restates it, because that page is53 a Lightning SPA that fetchers cannot read. Two other figures on the same legacy54 page (2,000 executed elements, 500 active flows) are known stale, so cite 5055 from the error message rather than from that page. -->5657## Breaking-Change Detection5859The test is mechanical: **if anything outside the flow has to change at the same60moment the flow changes, it is a new flow, not a new version.** The contract61surface binds by *name* at run time — Apex `Flow.Interview.createInterview`,62`lightning-flow` with `inputVariables`, another flow's `<subflows>` input63assignments, quick actions, Experience Cloud pages — and nothing compiles over64it.6566Before activating, diff against the current active version:6768- Added required variables? → breaking.69- Renamed or removed variables still referenced by callers? → breaking.70- Changed element outputs on a path before a Pause? → breaking.71- Removed an element a paused interview could currently occupy? → breaking.72- Added a Pause at the top of a flow that previously completed inline? →73 behaviour-changing; test callers.74- API version moved? → behaviour-changing. Flow behaviour is versioned, and75 Flow Builder can bump the version on save. Crossing API 52.0 changes the76 run-mode default; crossing 57.0 removes the executed-elements cap.7778## Querying the Right Object7980Four objects answer four different questions, and picking the wrong one produces81"sObject type 'Flow' is not supported."8283| Question | Object | API |84|---|---|---|85| Versions, their status, their definition | `Flow` | **Tooling API** |86| Which version is active per definition | `FlowDefinitionView` | Standard |87| Version metadata, read-only | `FlowVersionView` | Standard (46.0+) |88| Live and paused interviews | `FlowInterview` | Standard |8990Flow version `Status` has five values: `Active`, `Draft`, `Obsolete`,91`InvalidDraft`, and `UnderReview`. None of them means "safe to delete," and the92API values do not match the UI labels — `Draft` and `Obsolete` both display as93*Inactive*, `InvalidDraft` displays as *Draft*, `UnderReview` as *Under Review*.94Filter cleanup queries on `Status != 'Active'` rather than enumerating the95inactive values, so a value you did not think of cannot fall out of the inventory.9697## Change Log9899Keep a `FLOWS_CHANGELOG.md` or equivalent block in the flow's PR body:100101```text102Flow: CustomerOnboarding103From v12 → v13104- Added input variable `partnerAccountId` (optional, default null).105- Non-breaking. Paused interviews on v12 continue.106- Activate: after UAT sign-off.107- Retire v11: 2026-05-15.108```109110## Metrics To Watch111112- Count of paused interviews per version.113- Age of oldest paused interview.114- Activations per week (high churn = unstable flow).115- Version count per flow.116117## Recommended Workflow1181191. **Inventory the callers first**, not last. Search the repository for the120 flow's API name and for every input/output variable name it exposes. This is121 the input to the decision, not a check afterwards.1222. **Apply the breaking-change test.** Anything outside the flow that must change123 at the same moment makes it a new flow. Otherwise, a new version.1243. **Capture the currently active version number, per environment,** before125 activating. It is the entire rollback plan.1264. **Activate, and write the changelog entry** — breaking or not with the reason,127 the callers checked, the live paused-interview count, and the rollback version128 number.1295. **Roll back by activating the prior version**, never by redeploying its130 source. Redeploying creates a new version whose content matches the old one;131 it does not restore the old one. Keep the bad version as evidence.1326. **Prune on the interview-reference condition,** retaining at least three133 inactive versions.1347. **Treat every subflow activation as a multi-caller production change.** Search135 the metadata for `<flowName>` references before activating; resolution is late,136 so the parent runs whatever version of the child is active at run time.137138## Official Sources Used139140- FlowDefinition (Metadata API) — https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_flowdefinition.htm141- Flow (Metadata API) — https://developer.salesforce.com/docs/atlas.en-us.api_meta.meta/api_meta/meta_visual_workflow.htm142- Flow (Tooling API) — https://developer.salesforce.com/docs/atlas.en-us.api_tooling.meta/api_tooling/tooling_api_objects_flow.htm143- FlowVersionView (Object Reference) — https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_flowversionview.htm144- Have Unlimited Paused and Waiting Flows (Spring '24) — https://help.salesforce.com/s/articleView?id=release-notes.rn_automate_flow_mgmt_remove_paused_interview_limit.htm&release=248&type=5145- General Flow Limits — https://help.salesforce.com/s/articleView?id=platform.flow_considerations_limit.htm&type=5146147The full annotated list is in `references/well-architected.md`.