Salesforce Flow deactivation using Metadata API
Tags: salesforce, flow, metadataapi, tutorial
Published: 2024-01-31 20:10:45

Salesforce Flow is a powerful tool, offering declarative solutions for various business processes within the Salesforce ecosystem. While creating and updating flows is straightforward, deactivating an active flow presents its own set of challenges.

Typically, one might assume that updating the `<status>` tag in the flow XML file to a value indicating "Inactive" would deactivate the flow.
According to the documentation, there are four possible status values:
- Active
- Draft—In the UI, this status appears as Inactive.
- Obsolete—In the UI, this status appears as Inactive.
- InvalidDraft—In the UI, this status appears as Draft.

However, using any of these values in the `flow-meta.xml` file and deploying it to the org will not deactivate the flow.

Let’s see the resolution of this tricky task of Salesforce Flow deactivation in the following example:

I created a pretty simple flow that just makes a Chatter post on the Account record page when Billing Country is updated. 


![Active Salesforce flow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/73jcig1f23090av2a944.png)

As you can see, this flow is active.

Retrieving this active flow from the org to the codebase reveals its XML structure. Here's a snippet:

```
<?xml version="1.0" encoding="UTF-8"?>
<Flow xmlns="http://soap.sforce.com/2006/04/metadata">
   <actionCalls>
       <name>Post_Update_To_Chatter</name>
       <label>Post Update To Chatter</label>
       <locationX>50</locationX>
       <locationY>431</locationY>
       <actionName>chatterPost</actionName>
       <actionType>chatterPost</actionType>
       <flowTransactionModel>CurrentTransaction</flowTransactionModel>
       <inputParameters>
           <name>text</name>
           <value>
               <elementReference>ChatterMessageCountryChanged</elementReference>
           </value>
       </inputParameters>
       <inputParameters>
           <name>subjectNameOrId</name>
           <value>
               <elementReference>$Record.Id</elementReference>
           </value>
       </inputParameters>
       <storeOutputAutomatically>true</storeOutputAutomatically>
   </actionCalls>
   <apiVersion>59.0</apiVersion>
   <decisions>
       <name>CountryWasChanged</name>
       <label>Country Was Changed</label>
       <locationX>182</locationX>
       <locationY>323</locationY>
       <defaultConnectorLabel>Default Outcome</defaultConnectorLabel>
       <rules>
           <name>PostToChatter</name>
           <conditionLogic>and</conditionLogic>
           <conditions>
               <leftValueReference>$Record.BillingCountry</leftValueReference>
               <operator>NotEqualTo</operator>
               <rightValue>
                   <elementReference>$Record__Prior.BillingCountry</elementReference>
               </rightValue>
           </conditions>
           <conditions>
               <leftValueReference>$Record.BillingCountry</leftValueReference>
               <operator>IsNull</operator>
               <rightValue>
                   <booleanValue>false</booleanValue>
               </rightValue>
           </conditions>
           <connector>
               <targetReference>Post_Update_To_Chatter</targetReference>
           </connector>
           <label>Post To Chatter</label>
       </rules>
   </decisions>
   <environments>Default</environments>
   <interviewLabel>Account Country Update Post To Chatter {!$Flow.CurrentDateTime}</interviewLabel>
   <label>Account Country Update Post To Chatter</label>
   <processMetadataValues>
       <name>BuilderType</name>
       <value>
           <stringValue>LightningFlowBuilder</stringValue>
       </value>
   </processMetadataValues>
   <processMetadataValues>
       <name>CanvasMode</name>
       <value>
           <stringValue>AUTO_LAYOUT_CANVAS</stringValue>
       </value>
   </processMetadataValues>
   <processMetadataValues>
       <name>OriginBuilderType</name>
       <value>
           <stringValue>LightningFlowBuilder</stringValue>
       </value>
   </processMetadataValues>
   <processType>AutoLaunchedFlow</processType>
   <start>
       <locationX>56</locationX>
       <locationY>0</locationY>
       <connector>
           <targetReference>CountryWasChanged</targetReference>
       </connector>
       <object>Account</object>
       <recordTriggerType>Update</recordTriggerType>
       <triggerType>RecordAfterSave</triggerType>
   </start>
   <status>Active</status>
   <textTemplates>
       <name>ChatterMessageCountryChanged</name>
       <isViewedAsPlainText>true</isViewedAsPlainText>
       <text>Attention! The Billing Country on this Account was changed from {!$Record__Prior.BillingCountry} to {!$Record.BillingCountry}</text>
   </textTemplates>
</Flow>
```

Regardless of the status specified in the `<status>` tag during deployment, the flow remains active.

To resolve this, you need to retrieve the `.flowDefinition-meta.xml` file associated with the flow. Within this file, set the `<activeVersionNumber>` to 0.


An example of how these files are structured in my project:


![Structure in codebase](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hguwroihqvt1f9hh6hem.png)

Here's how the file structure appears after retrieval:

```
<?xml version="1.0" encoding="UTF-8"?>
<FlowDefinition xmlns="http://soap.sforce.com/2006/04/metadata">
   <activeVersionNumber>2</activeVersionNumber>
</FlowDefinition>
```

And here's the adjustment to deactivate the flow before deployment:

```
<?xml version="1.0" encoding="UTF-8"?>
<FlowDefinition xmlns="http://soap.sforce.com/2006/04/metadata">
   <activeVersionNumber>0</activeVersionNumber>
</FlowDefinition>
```

Once deployed, the flow is successfully deactivated.


![Salesforce flow deactivated](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzrvc9s5d1a5nzohv7s1.png)

This simple yet effective approach offers a solution to the challenge of deactivating Salesforce Flows programmatically. Share your insights and alternative methods for flow deactivation in the comments below, and let's enrich our knowledge together!