DEV Community

Cover image for Salesforce Flow deactivation using Metadata API
Oleksandra Todorenko
Oleksandra Todorenko

Posted on

Salesforce Flow deactivation using Metadata API

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

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>
Enter fullscreen mode Exit fullscreen mode

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

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Once deployed, the flow is successfully deactivated.

Salesforce flow deactivated

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!

Top comments (0)