This rule raises an issue when the nesting depth of control actions in an Azure Logic Apps workflow exceeds a given threshold.

Why is this an issue?

Control actions such as If, Switch, Foreach, Until, and Scope are building blocks of Logic Apps workflows. When they are nested deeply inside one another the workflow becomes a tangled structure that is:

The recommended remediation is to extract deeply nested logic into a child Logic App (called via the built-in HTTP or Logic Apps connector), or to flatten the structure by rethinking the control flow.

How to fix it in JSON templates

Reduce the nesting depth by extracting inner logic into child workflows or by flattening the control flow.

Code examples

Noncompliant code example

With the default threshold of 3:

{
  "type": "Microsoft.Logic/workflows",
  "apiVersion": "2019-05-01",
  "name": "deeply-nested-workflow",
  "location": "[resourceGroup().location]",
  "properties": {
    "definition": {
      "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
      "actions": {
        "Check_condition": {
          "type": "If",
          "expression": "@equals(triggerBody()?['status'], 'active')",
          "actions": {
            "Loop_items": {
              "type": "Foreach",
              "foreach": "@triggerBody()?['items']",
              "actions": {
                "Check_item": {
                  "type": "If",
                  "expression": "@greater(items('Loop_items')?['value'], 0)",
                  "actions": {
                    "Retry_until_done": {
                      "type": "Until",
                      "expression": "@equals(body('Process')?['done'], true)",
                      "limit": { "count": 10 },
                      "actions": {
                        "Process": {
                          "type": "Http",
                          "inputs": {
                            "method": "POST",
                            "uri": "https://api.example.com/process"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Nesting path: If (1) → Foreach (2) → If (3) → Until (4) — depth 4 exceeds the default max of 3.

Compliant solution

{
  "type": "Microsoft.Logic/workflows",
  "apiVersion": "2019-05-01",
  "name": "flat-with-child",
  "location": "[resourceGroup().location]",
  "properties": {
    "definition": {
      "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
      "actions": {
        "Check_condition": {
          "type": "If",
          "expression": "@equals(triggerBody()?['status'], 'active')",
          "actions": {
            "Loop_items": {
              "type": "Foreach",
              "foreach": "@triggerBody()?['items']",
              "actions": {
                "Call_Child_Workflow": {
                  "type": "Workflow",
                  "inputs": {
                    "host": {
                      "workflow": { "id": "/subscriptions/.../workflows/child-processor" }
                    },
                    "body": "@items('Loop_items')"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

The complex inner logic is extracted into a child workflow, reducing nesting depth to 2.

How to fix it in Bicep

Reduce the nesting depth by extracting inner logic into child workflows or by flattening the control flow.

Code examples

Noncompliant code example

With the default threshold of 3:

resource workflow 'Microsoft.Logic/workflows@2019-05-01' = {
  name: 'deeply-nested-workflow'
  location: resourceGroup().location
  properties: {
    definition: {
      '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#'
      actions: {
        Check_condition: {                          // depth 1
          type: 'If'
          expression: '@equals(triggerBody()?[\'status\'], \'active\')'
          actions: {
            Loop_items: {                           // depth 2
              type: 'Foreach'
              foreach: '@triggerBody()?[\'items\']'
              actions: {
                Check_item: {                       // depth 3
                  type: 'If'
                  expression: '@greater(items(\'Loop_items\')?[\'value\'], 0)'
                  actions: {
                    Retry_until_done: {             // Noncompliant: depth 4
                      type: 'Until'
                      expression: '@equals(body(\'Process\')?[\'done\'], true)'
                      limit: { count: 10 }
                      actions: {
                        Process: {
                          type: 'Http'
                          inputs: {
                            method: 'POST'
                            uri: 'https://api.example.com/process'
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Nesting path: If (1) → Foreach (2) → If (3) → Until (4) — depth 4 exceeds the default max of 3.

Compliant solution

resource workflow 'Microsoft.Logic/workflows@2019-05-01' = {
  name: 'flat-with-child'
  location: resourceGroup().location
  properties: {
    definition: {
      '$schema': 'https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#'
      actions: {
        Check_condition: {                          // depth 1
          type: 'If'
          expression: '@equals(triggerBody()?[\'status\'], \'active\')'
          actions: {
            Loop_items: {                           // depth 2
              type: 'Foreach'
              foreach: '@triggerBody()?[\'items\']'
              actions: {
                Call_Child_Workflow: {
                  type: 'Workflow'
                  inputs: {
                    host: {
                      workflow: { id: childWorkflow.id }
                    }
                    body: '@items(\'Loop_items\')'
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

Resources

Documentation