Quick Answer
Plan it as a rebuild. Inventory every published workflow and how often it runs, retire the ones nobody uses, then rebuild the rest as flows and subflows one at a time. Run old and new side by side on a slice of records, cut over by switching the trigger, and keep the old workflow ready as your rollback.
Key takeaways
- ServiceNow's own documentation recommends Flow Designer over the legacy workflow for new process flows, so every rebuilt workflow moves onto the tool new automation is built in.
- Build your migration list from the wf_workflow_version and wf_context tables, which show which workflows are published and which ones actually run.
- Map each workflow activity to a flow action or flow logic block before you build, and move shared steps into subflows.
- A legacy workflow can start a subflow through the FlowAPI, and a flow can call a published workflow, so you can migrate one piece at a time.
- Cut over by changing what starts new work, let in-flight workflows finish, and keep the old workflow intact until the flow has run cleanly through a full business cycle.
Planning a workflow migration?
If you would rather hand the inventory or the rebuild to someone else, NowSpectrum offers ServiceNow development, administration and one-off project work.
See NowSpectrum ServicesDo I have to migrate legacy workflows to Flow Designer now?
You can migrate on your own schedule, but the direction is clear. ServiceNow's Flow Designer documentation recommends Flow Designer over the legacy workflow for new process flows, and a ServiceNow support article says out-of-box (platform-supplied) legacy workflows stop shipping starting with the Zurich release.
Quick definitions. The Workflow Editor is the older drag-and-drop canvas where you build a workflow from activities such as approvals, timers and scripts. Flow Designer is the low-code builder for flows, subflows (reusable sequences you call from flows or scripts) and actions. In current releases you build flows in Workflow Studio, ServiceNow's single design environment for flows, actions and related tools.
The practical case for moving is maintenance. A flow shows its data as data pills (labeled values passed between steps), while a legacy workflow often hides state in scratchpad variables. Treat the support article as direction rather than a shutdown notice, and check the release notes for your version before you promise anyone a date.
If a workflow has one script and no waiting, read when a flow beats a business rule first. The right target might not be a flow at all.
How do I find every legacy workflow on my instance?
Query two tables. The Workflow Version table [wf_workflow_version] holds each version of a workflow, including the published ones, and the Workflow Context table [wf_context] holds each instance of a workflow being used. Published versions tell you what could run. Contexts created recently tell you what actually runs. Together they are your migration backlog.
The tables that hold your legacy workflows
ServiceNow documents these in its workflow tables reference. These are the ones you will use during a migration:
| Table | What it holds | Why it matters for migration |
|---|---|---|
| wf_workflow | The primary record of each workflow | One row per workflow, regardless of version |
| wf_workflow_version | Published and checked-out versions | Filter on Published to see what can run today |
| wf_context | Individual instances of a workflow in use | Count by version to see real usage, and watch it during cutover |
| wf_executing | Activities being performed in active contexts | Shows where open work is waiting, such as an approval |
| wf_activity | Activities as they are used in workflows | Gives you the activity list to map, step by step |
A script to build the inventory
Run this as a background script in a sub-production instance (a non-production copy such as dev or test, ideally a recent clone). It lists every published version, then counts contexts per version for the last 90 days with GlideAggregate. If you have not used GlideAggregate before, our GlideAggregate guide explains the grouping pattern. ServiceNow's documentation describes these tables but does not list their fields, so confirm the field names (published, table, name and workflow_version) in your instance's dictionary before you run it.
// Background script, sub-production instance only.
// 1. Published workflow versions: what can run today.
var ver = new GlideRecord('wf_workflow_version');
ver.addQuery('published', true);
ver.orderBy('table');
ver.query();
while (ver.next()) {
gs.info('PUBLISHED | ' + ver.getValue('table') + ' | ' + ver.getValue('name'));
}
// 2. Contexts created in the last 90 days: what actually runs.
var ga = new GlideAggregate('wf_context');
ga.addQuery('sys_created_on', '>=', gs.daysAgoStart(90));
ga.addAggregate('COUNT');
ga.groupBy('workflow_version');
ga.query();
while (ga.next()) {
gs.info('RUNS | ' + ga.workflow_version.getDisplayValue() + ' | ' + ga.getAggregate('COUNT'));
}
Paste both outputs into a spreadsheet and add four columns per workflow: the process owner, the number of activities, the number of Run Script activities, and whether it waits on approvals or timers. Those four columns drive the triage in the next section.
Which workflows should I migrate first?
Start with workflows that run often and get edited often, because every change request is a chance to rebuild instead of patch. Retire workflows with no contexts in the last 90 days once the owner agrees. Leave stable, rarely touched workflows for later, and do not pick the most complex catalog workflow on the instance as your first migration.
| Bucket | Signal in your inventory | What to do |
|---|---|---|
| Retire | No contexts in 90 days, no clear owner | Confirm with the owner, then deactivate it. Do not delete it. |
| Rebuild now | Runs every week and has open change requests | Rebuild as a flow as part of the next change |
| Rebuild next | Runs often, rarely changes, few scripts | Schedule after your first two or three migrations |
| Leave for now | Runs rarely, many scripts, nothing pending | Document it and call it from a flow if a flow needs it |
Pick a first migration with a handful of activities, one approval and an owner who will test it. You learn the mapping on something small and end up with a pattern others can copy.
How do legacy workflow activities map to Flow Designer?
Most workflow patterns have a direct counterpart. Approvals become the Ask for Approval action, timers become Wait for a duration, branch and join become Do the following in parallel, and if or switch logic becomes If or Make a decision. Scripts usually move into a custom action. Map every activity on paper before you build anything.
The flow logic names below come from ServiceNow's Workflow Studio flow logic reference.
| Workflow Editor pattern | Flow Designer equivalent | Watch for |
|---|---|---|
| User or group approval | Ask for Approval action | Rebuild the approval rules, and test both approve and reject paths |
| Timer | Wait for a duration | Test with a short duration first |
| Wait for a condition | Wait for Condition action | Check the condition can actually become true |
| If or switch branching | If, or Make a decision | Make a decision replaces long Else If chains |
| Branch and join | Do the following in parallel | Test every path, including the slowest one |
| Rollback to an earlier step | Go back to flow logic | Guard against endless loops with a counter |
| Run Script | A custom action that runs your script | Check for a built-in action first |
| Scratchpad values | Set Flow Variables | Name variables for what they hold |
| Sub-workflow | Subflow | Define inputs and outputs explicitly |
| Error branches in scripts | Try | Decide what a failure should do to the record |
Two habits help. First, describe each Run Script activity in one sentence. Often the answer is "sets three fields on the record", which a built-in action handles without a script. Second, give every new flow an error path from day one: see our guide to Flow Designer error handling and the Flow Designer best practices post.
When an activity has no clean counterpart yet, leave that part in the old workflow. The next section shows how a flow can call it.
How do I run the old workflow and the new flow side by side?
Use the two bridges ServiceNow provides. From a legacy workflow, a Run Script activity can start a subflow through the FlowAPI in the sn_fd namespace. From a flow, the Call a workflow flow logic runs a published, active workflow and can pass flow data in as inputs. Either lets you move one piece at a time.
From the workflow: start a subflow
This is the pattern for replacing one step inside a workflow you are not ready to retire. It uses the ScriptableFlowRunner API, which you start with sn_fd.FlowAPI.getRunner().
// Run Script activity inside the legacy workflow.
// Hands one step to a new subflow; the rest of the workflow is unchanged.
(function () {
try {
var inputs = {};
inputs['requested_item'] = current; // the record this workflow runs on
var result = sn_fd.FlowAPI.getRunner()
.subflow('global.provision_standard_laptop') // scope.internal_name
.inForeground() // waits for the subflow to finish
.withInputs(inputs)
.run();
var outputs = result.getOutputs();
workflow.scratchpad.provision_status = outputs['status'];
} catch (ex) {
gs.error('Subflow call failed: ' + ex.getMessage());
}
})();
One limit matters: the documentation says foreground runs do not support steps that pause for wait conditions, such as Ask for Approval or Wait for Condition. If the subflow needs an approval, use inBackground(). The script then continues right away, so read results from the execution record later. Swap in your own subflow and input names.
From the flow: call the old workflow
When you have rebuilt the front of a process but not the back, add Call a workflow where the old logic should take over. The workflow must be published and active.
Split the traffic before you switch it
Give the new flow a trigger condition that matches only a slice of records, such as one catalog item, and exclude that slice from the workflow's start condition. Compare outcomes for a few weeks (approvals requested, tasks created, fields set) and widen the slice when they match.
How do I cut over and roll back without breaking open requests?
Switch what starts new work, not what is already running. Activate the flow and stop the workflow from starting on new records in the same update set (a container of configuration changes you move between instances), let existing contexts finish, and keep the old workflow version intact. Rolling back is the reverse switch in its own update set.
Cutover steps
- Freeze changes to the old workflow once the flow is in final testing.
- Test the flow in sub-production with the same cases the workflow handles: approve, reject, timer expires, and the error path.
- Capture the switch in one update set: the flow activation and the workflow's start condition change. Our update sets guide covers preview and commit.
- Build the reverse update set at the same time, and test it in sub-production too.
- Promote the cutover update set during a quiet period.
- Watch wf_context for contexts still executing on the old version, and let them finish on their own.
- Review flow executions daily for errors until the flow has covered a full business cycle, such as a month end, so every approval and wait has fired at least once.
- Only then deactivate the old workflow. Keep it, do not delete it.
When to roll back
Roll back when the flow produces a wrong outcome on a real record. Promote the reverse update set, fix the flow in sub-production, and repeat the cutover. Because the old workflow was never deleted, rolling back is a configuration change.
Want help with the cutover?
A ServiceNow consultant can review your inventory, check your activity mapping and sit in on the cutover so open requests keep moving.
Hire a ServiceNow ConsultantFrequently asked questions
Is the ServiceNow Workflow Editor being deprecated?
ServiceNow's Flow Designer documentation recommends Flow Designer over the legacy workflow for new process flows, and a ServiceNow support article says out-of-box legacy workflows stop shipping starting with the Zurich release. Read that as direction for new work, then check the release notes for your instance's version before you plan around any removal date.
Can ServiceNow automatically convert a workflow into a flow?
Plan for a manual rebuild. ServiceNow's documentation on flows describes building flows and calling a published workflow from a flow, not converting one into the other. If your release offers conversion help, treat its output as a first draft and test it with the same cases you use for any rebuilt flow.
Can a flow call a legacy workflow in ServiceNow?
Yes. Workflow Studio includes a Call a workflow flow logic block that runs a published and active workflow from your flow, and you can pass flow data in as workflow inputs. It is a practical bridge during migration: rebuild the parts you understand as flow steps and keep the tricky part in the old workflow for now.
How do I call a subflow from a legacy workflow Run Script activity?
Use the ScriptableFlowRunner API in the sn_fd namespace: sn_fd.FlowAPI.getRunner(), then .subflow() with the scoped subflow name, .withInputs() with an inputs object, a foreground or background choice, and .run(). Foreground runs return outputs to the script, but they do not support steps that pause, such as Ask for Approval.
What happens to running workflows when I switch to a flow?
Contexts (running instances of a workflow) that already started keep running on the old workflow until they finish, because switching the trigger only changes what starts new work. Before you retire anything, check the wf_context table for contexts still executing on the old version, and leave the workflow intact until that list is empty.
Which ServiceNow workflows should I migrate to Flow Designer first?
Start with workflows that run often and get edited often, since each change request is a chance to rebuild instead of patch. Retire anything with no contexts in the last 90 days. Leave stable, rarely edited workflows for later, and avoid making the most complex catalog workflow your first migration.
What replaces the Timer activity in Flow Designer?
Use the Wait for a duration flow logic, which pauses the flow to give users time to act or to wait for a specific date and time. Test long waits in sub-production with a short duration first, then set the real value before you promote the flow.
Why does my subflow fail when I run it in the foreground from a script?
ServiceNow's ScriptableFlowRunner documentation says foreground runs do not support steps that pause for wait conditions, such as Ask for Approval or Wait for Condition. If the subflow needs an approval or a wait, run it with inBackground() instead, and read its results later from the flow's execution record rather than in the same script.
How do I roll back a Flow Designer migration if something breaks?
Keep the old workflow version published but no longer triggered, and prepare a reverse update set (a record of configuration changes you move between instances) before go-live that deactivates the flow and restores the workflow's start condition. If the flow misbehaves, promote that update set, then fix the flow in sub-production before trying again.
Sources
- ServiceNow Docs: Flow Designer (Australia release)
- ServiceNow Support KB2077859: ServiceNow Will Not Ship OOB Legacy Workflows Starting in Zurich
- ServiceNow Docs: Workflow Studio
- ServiceNow Docs: Workflow tables
- ServiceNow Docs: Workflow Studio flow logic
- ServiceNow Docs: ScriptableFlowRunner (scoped API reference)