A flow deployment never overwrites the running version. It adds a new one, and whether that becomes active depends on the status element in your file and on a setting in Process Automation Settings. The two failure modes are opposite: a fix that changes nothing because the new version landed as a draft, or a half-finished flow that goes live because the setting was on.
What actually happens on deploy
Flows are versioned by the org, not by your repository. Your source holds one file, Invoice_Router.flow-meta.xml, with no version number in it. On deploy, the org creates the next version and leaves every previous one in place. Deploy the same flow eleven times and the org holds eleven versions.
The deciding element sits near the top of the file:
<status>Active</status>
The values are Active, Draft, Obsolete and InvalidDraft. When the deployed version becomes active, the previous one is marked obsolete and stops running. There is no moment where both are live.
The setting is Setup, Process Automation Settings, “Deploy processes and flows as active”. With it off, a flow whose file says Active arrives inactive and the old version keeps running. That is behind most “I deployed the fix and it did nothing” tickets.
Pick one behaviour and make it explicit
Both are defensible. The wrong move is not knowing which one you are in.
Deploy inactive, activate manually. Nothing changes until a person clicks. The cost is real: production runs a version that is not the one in your branch until someone remembers. That drift is how an org ends up with an active version nobody can find in git.
Deploy active. The repository is the truth and the deployment is the change, with no second step to forget. What I would pick, on one condition: the pipeline validates first, because there is no manual gate left.
Turning the setting on also brings a coverage requirement for autolaunched flows and processes in production, measured across the org rather than per flow. Screen flows are exempt. If you have never written an Apex test that runs a flow, expect that gate to bite on the first release after you flip it.
Changing a flow that is running right now
Record-triggered flows fire on DML, so activating a new version happens mid-traffic. Anything in flight finishes on the version it started with, which is fine. What is not fine is a new version expecting a field deploying in the same request, because ordering within one deployment is not yours to control. Deploy the field first.
For anything that moves data, put a decision at the top gated on a custom permission, so you can switch it off in Setup without a deployment. Disabling a misbehaving flow in thirty seconds is worth two extra elements.
Version hygiene
Versions accumulate and there is a cap per flow, so clear obsolete versions from the version list in Flow Builder occasionally. The active one cannot be deleted. Removing a flow entirely means deactivating it, deleting every version, and only then running a destructive change against the definition.
Testing it first
Flow Builder has built-in tests for record-triggered flows: define the triggering record, assert on what the flow does, run it in the org. Less expressive than Apex, and a minute to write, so worth having for the path a flow takes most often.
Anywhere an Apex test already does DML on the object, the flow runs inside that test. That is the coverage the org counts, and why a flow change can break a test nobody edited.
A deployment checklist
- Confirm the
statuselement says what you intend. - Confirm the org setting in the target, not the sandbox. They differ more often than you expect.
- Deploy new fields and Apex in an earlier request.
- Validate with
--dry-run, so a missing reference fails before the window. - Afterwards, open the flow in the target and read the version number and active flag rather than inferring them from the deployment result.
- Watch the flow error emails for an hour. They go to the last modified user, which is now whoever ran the deployment.
Frequently asked
Can I roll back? Yes. In Flow Builder, open the older version and activate it. That is the fastest rollback on the platform, and a good argument against deleting versions too eagerly.
Why did my flow deploy as InvalidDraft? It references something the target lacks, usually a field, a subflow, or an Apex action. The version exists but cannot activate until the reference resolves.
Does editing a flow in Setup break my repository? It creates a version your branch does not have. Retrieve it the same day, or the next deployment from source quietly replaces that work with an older definition.
