DEV Community

Robert Breen
Robert Breen

Posted on Originally published at learn.ynteractive.com

n8n: IF vs Switch for Conditional Logic, With the Real Expressions and Node JSON

Most first n8n workflows do one thing to every item: every form goes to the same sheet, every email gets the same reply. Then the owner asks for a rule. "Send me the big jobs. Log the rest. And if it's an emergency, I want to know right away, whatever the budget."

That's conditional logic: if this, then that. It's the same idea as a form that shows a field only when someone picks a certain service, applied to where the work goes instead of what the form shows.

The cost of not having it is easy to see in a small business. Either the owner reads every request to find the three that matter, or an emergency sits in a log until somebody happens to look.

In n8n, two nodes do this job. Here's how I decide between them, with the expressions and the node JSON.

The example

My free lesson uses Harbor Point Handyman, a made-up business that takes service requests through an n8n form. The form asks for a name, a Service (Repair, Installation or Emergency) and a Budget. Two actions already exist: a Gmail step called Send a message that emails the owner, and a Google Sheets step called Append row in sheet that logs the request.

What's missing is the part that decides.

Use If for one yes-or-no question

The If node asks one question and has two exits, true and false. Every item takes one or the other, never both.

"Is the budget over 1,000?" is an If question.

  1. Click Execute workflow and submit a test request: Installation, budget 2500.
  2. Click the + after On form submission, search for if, choose If.
  3. Drag Budget into value1. Open the comparison, point to Number, choose is greater than. Type 1000 in value2.
  4. Click Execute step. The request goes to True Branch (1 item).

Then drag true to Send a message and false to Append row in sheet.

Pick Number, not text, for an amount. As text, "900" and "1000" compare letter by letter, which is not what you want.

Behind the drag-and-drop, the condition is an expression. In the workflow JSON the If node looks like this:

{
  "parameters": {
    "conditions": {
      "options": {
        "caseSensitive": true,
        "leftValue": "",
        "typeValidation": "strict"
      },
      "conditions": [
        {
          "id": "budget-over-1000",
          "leftValue": "={{ $json.Budget }}",
          "rightValue": 1000,
          "operator": { "type": "number", "operation": "gt" }
        }
      ],
      "combinator": "and"
    },
    "options": {}
  },
  "name": "If",
  "type": "n8n-nodes-base.if",
  "typeVersion": 2,
  "position": [440, 0]
}
Enter fullscreen mode Exit fullscreen mode

If your form sends the budget as text, convert it in the expression instead of switching the comparison to String: {{ Number($json.Budget) }}.

You can stack conditions with Add condition and choose AND or OR. Two conditions joined with AND is still one yes-or-no question:

{{ $json.Budget > 1000 && $json.Service === "Installation" }}
Enter fullscreen mode Exit fullscreen mode

Use Switch when one field has several answers

The moment you catch yourself chaining If after If on the same field ("is it Repair? if not, is it Emergency? if not..."), you want a Switch. It compares one value against several rules and gives each match its own exit.

In the lesson, the owner wants emergencies straight to them, so a Switch goes in front of the If:

  1. Point to the line between the form and If, click its +, choose Switch. n8n places it on that line.
  2. Mode stays Rules, one rule per output.
  3. First rule: drag Service into value1, type Repair in value2. Turn on Rename Output and name it Repair.
  4. Click Add Routing Rule, drag Service in again, type Emergency, rename the output Emergency.

Outputs are numbered 0, 1, 2 until you name them. Name them. You'll thank yourself in a month.

The Fallback Output: the setting that prevents lost work

Here's the part I'd put in bold for every new n8n builder. An item that matches none of your Switch rules is ignored by default. No error, no warning. It just stops.

The Installation request in the lesson matches neither Repair nor Emergency. Without a fallback, installation requests would silently disappear.

Under Options, click Add option, choose Fallback Output. It starts at None (default). Change it to Extra Output. Click Execute step, and the Installation request lands in Fallback (1 item).

Here's the Switch node as JSON, with both rules and the fallback:

{
  "parameters": {
    "rules": {
      "values": [
        {
          "conditions": {
            "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
            "conditions": [
              {
                "leftValue": "={{ $json.Service }}",
                "rightValue": "Repair",
                "operator": { "type": "string", "operation": "equals" }
              }
            ],
            "combinator": "and"
          },
          "renameOutput": true,
          "outputKey": "Repair"
        },
        {
          "conditions": {
            "options": { "caseSensitive": true, "leftValue": "", "typeValidation": "strict" },
            "conditions": [
              {
                "leftValue": "={{ $json.Service }}",
                "rightValue": "Emergency",
                "operator": { "type": "string", "operation": "equals" }
              }
            ],
            "combinator": "and"
          },
          "renameOutput": true,
          "outputKey": "Emergency"
        }
      ]
    },
    "options": { "fallbackOutput": "extra" }
  },
  "name": "Switch",
  "type": "n8n-nodes-base.switch",
  "typeVersion": 3.2,
  "position": [220, 0]
}
Enter fullscreen mode Exit fullscreen mode

Note caseSensitive: true. If your form lets people type the service instead of picking it, "repair" won't match "Repair". Either keep it a dropdown, or normalize in the expression: {{ $json.Service.trim().toLowerCase() }} and compare against lowercase values.

Wire it all together

The finished routing reads like the owner's rules:

On form submission
  -> Switch
       Repair    -> If (Budget > 1000)
                      true  -> Send a message
                      false -> Append row in sheet
       Emergency -> Send a message
       Fallback  -> Append row in sheet
Enter fullscreen mode Exit fullscreen mode

Repairs keep the budget check. Emergencies skip it. Everything else gets logged. Every route has somewhere to go.

When an expression is enough

Sometimes you don't need a branch at all, just a value that depends on a condition. A ternary in an Edit Fields node does that without changing the shape of the workflow:

{{ $json.Budget > 1000 ? "Owner review" : "Standard" }}
Enter fullscreen mode Exit fullscreen mode

I use this for labels and priority columns in a sheet. If the two cases need different actions, a different email or a different app, use If or Switch so the canvas shows the decision.

Test, then publish

Run Execute step on each node with a test request to see which branch an item took before you connect anything. Then submit one request per path: a big repair, a small repair, an emergency, an installation.

When every path works, click Publish, keep the suggested Version name, and click Publish again. Testing in the editor doesn't make the workflow run on real submissions; publishing does.

You need an n8n account for the real thing. n8n Cloud has paid plans after a trial, and it can also be self-hosted. You can try n8n here (affiliate link: I may earn a commission, at no cost to you).

Try it free

The lesson, IF and Switch in n8n: Route Work by Rules, builds this exact workflow in 40 steps on a practice copy of n8n, with no account needed. If you want the plain-words idea first, the glossary page on conditional logic covers it with a form example.

Practice it step by step, free: https://learn.ynteractive.com/content/n8n-if-and-switch-node-tutorial

Top comments (0)