# How to convert Pipedream if/else and switch blocks to n8n

> Source: https://workflowexit.com/pipedream-if-else-switch-to-n8n · Updated 2026-10-13

A Pipedream if/else block becomes an n8n **If** node when it has one condition branch, and a **Switch** node in Rules mode when it has several. Both send each item down the first branch whose rules match, as Pipedream did, and the If node's false output or the Switch node's fallback output takes the place of Else. Switch blocks become Switch nodes, filters become If or Filter nodes, parallel blocks end in a Merge node, and loops use Loop Over Items. Two details change results if you miss them: Pipedream's text rules ignore case by default and n8n's don't, and steps after a block need a node to read the block's result from.

## The mapping at a glance

| Pipedream | n8n | Notes |
|---|---|---|
| If/else with one condition branch | If | True output runs the branch. False output runs Else, or the step after the block. |
| If/else with several condition branches | Switch, Rules mode | One output per branch in Pipedream's order, plus a fallback output for Else. |
| Switch | Switch, Rules mode | Pipedream's expression becomes the left side of every rule. |
| Filter | If, or Filter | Only the path that continues is connected. |
| End Workflow action | No next node | A branch with nothing after it stops. |
| `$.flow.exit()` in code | `return []` in a Code node | No items come out, so later nodes don't run. |
| Delay | Wait | Same duration. |
| Parallel | Branches from one node, then Merge | n8n runs the branches one after another. |
| Loop | Loop Over Items | The steps run once per item. |

Pipedream's plan-limit data lists control-flow blocks as an Advanced feature, so on Free or Basic, look at Filter steps and `$.flow.exit()` calls instead. Both are covered below.

## How Pipedream runs if/else and switch

Pipedream's [if/else](https://pipedream.com/docs/workflows/building-workflows/control-flow/ifelse) and [switch](https://pipedream.com/docs/workflows/building-workflows/control-flow/switch) blocks follow four rules that the n8n version has to keep:

1. **The first match wins.** Branches are checked top to bottom, and only the first one whose rules pass runs.
2. **Else and Default are optional.** If the fallback branch is off and nothing matches, the workflow skips the block and continues after it.
3. **Blocks have an end phase.** Steps after a block read `steps.<block>.$return_value`, which holds the result of the last step in the branch that ran.
4. **Branches are isolated.** A step inside a branch can read the steps that ran before the block, but not the steps in a sibling branch.

Nested blocks convert the same way, level by level.

## If/else becomes an If or a Switch node

**One condition branch.** Workflow Exit creates an If node named `<block> (if)`. Its true output leads into the branch. Its false output leads into the Else branch, or straight to the next step when Else was off.

**Several condition branches.** Workflow Exit creates a Switch node named `<block> (switch)` in Rules mode, with one rule per branch in Pipedream's order. Each output is renamed after its branch, and the fallback output carries Else. When Else was off, the fallback output connects to the step after the block, so unmatched items carry on as they did in Pipedream. If you build the Switch yourself, leave its option to send data to all matching outputs turned off. Otherwise an item that matches two rules runs both branches.

**After the block.** Where the branches meet, Workflow Exit adds a pass-through node with the block's own name. An expression like `{{steps.route_order.$return_value}}` then points at that node and returns the result of whichever branch ran. If that branch had no steps, a small Code node returns an empty result, as Pipedream did.

## How the rules are converted

Workflow Exit doesn't translate rule-builder conditions into n8n's operators. It writes each rule group as a single n8n condition: a JavaScript expression that applies Pipedream's comparison exactly, tested with "is true". For a rule that checks whether the country equals `us`, ignoring case, the condition looks like this (wrapped here to fit):

```text
{{ ((a, b) => typeof a === "string" && typeof b === "string"
     && a.localeCompare(b, undefined, { sensitivity: "base" }) === 0)
   ($('trigger').first().json.body.country, "us") }}
```

It's harder to edit than n8n's condition builder, but every item routes as it did in Pipedream. A rule the converter can't read is set to always true or always false, and the migration checklist names it.

To rebuild a branch in n8n's condition builder instead, start from its rules. This branch has two:

| Value | Pipedream operator | Compared with |
|---|---|---|
| `{{steps.trigger.event.body.total}}` | Number: is greater than | `500` |
| `{{steps.trigger.event.body.country}}` | String: equals | `us` |

1. Add an If node after the Webhook node, which is named `trigger` here.
2. First condition: `{{ $('trigger').first().json.body.total }}`, type Number, greater than, `500`.
3. Second condition: `{{ $('trigger').first().json.body.country }}`, type String, equals, `us`.
4. Combine them with AND, the same combinator the Pipedream branch used.
5. Turn on Ignore Case, and turn on loose type validation if `total` can arrive as text.

## Rule semantics that differ

| Pipedream rule | How Pipedream evaluates it | What to do in n8n |
|---|---|---|
| Text equals | Ignores case and accents unless match case is on | n8n is case-sensitive by default, so turn on Ignore Case |
| Contains, starts with, ends with | Ignores case unless match case is on | Turn on Ignore Case |
| Any text rule | False when either side isn't text, so "doesn't equal" is false for a missing field | Decide where missing fields should go, and add an exists rule |
| Number rules | Converts both sides, so `"42"` equals `42` | Strict type validation stops with a "Wrong type" error on text, so turn on loose type validation |
| Is true, is false | Needs a real boolean, so the text `"true"` fails | Check the type the field really has |
| Exists | Only a missing value fails, and `null` counts as existing | n8n's exists also fails on `null` and `NaN` |
| Is blank | Only empty or whitespace text, so a missing field isn't blank | Check missing fields separately |
| Rule groups | AND or OR, nested freely, and an empty AND group is true | The condition builder has one AND or OR per node, so nested groups need an expression |

## Switch blocks

A Pipedream switch block evaluates one expression, then compares it with each case. An n8n Switch in Rules mode has no shared expression, so the expression goes on the left side of every rule. Workflow Exit fills it in. By hand, a block that routes on `{{steps.trigger.event.body.type}}` becomes:

| Output | Left value | Operator | Right value |
|---|---|---|---|
| `paid` | `{{ $('trigger').first().json.body.type }}` | String equals | `invoice.paid` |
| `failed` | `{{ $('trigger').first().json.body.type }}` | String equals | `invoice.payment_failed` |
| Fallback | | | Pipedream's Default branch |

Set the Switch's fallback output to an extra output. Without a fallback, n8n drops items that match no rule, so the workflow stops for them. Pipedream continued after the block instead, so connect the fallback output to the next step when Default was off.

A switch that routed on `steps.trigger.event.path` needs another approach, because n8n's Webhook output has no path field. The [webhook guide](/pipedream-http-trigger-to-n8n-webhook) covers the options.

## Filter and End Workflow

Pipedream's built-in Filter step has a set of rules and one choice: continue when they match, or end when they match. Workflow Exit turns it into an If node named after the step, with one output connected:

- **Continue when the rules match:** the true output continues.
- **End when the rules match:** the false output continues, and nothing follows the true output.

The rules keep Pipedream's semantics, as with if/else. Older workflows may use the Filter app's actions, `filter-continue-based-on-condition` and `filter-end-based-on-condition`, which are evaluated the way those actions did, including their own case-sensitive option.

By hand, n8n's Filter node is the simplest replacement. It passes the items that match and drops the rest, and when none pass, the branch stops.

End Workflow has no node of its own in n8n, because a branch with nothing after it simply ends. Workflow Exit still adds a No Operation node with the step's name, so you can see where Pipedream stopped. Inside code, `$.flow.exit()` works through the compatibility layer: the Code node returns no items, so the nodes after it don't run. Written by hand, it looks like this:

```javascript
// n8n Code node, Run Once for All Items
const order = $('trigger').first().json.body;
if (!order.items?.length) {
  return []; // ends this path, like return $.flow.exit("empty order")
}
return [{ json: { orderId: order.id, lineCount: order.items.length } }];
```

There's more on code steps in [what breaks on n8n Cloud](/pipedream-code-steps-n8n-cloud).

## Delay

A Delay step becomes a Wait node set to the same duration. In n8n, waits longer than about a minute are saved to the database, and the execution shows as waiting until it resumes. A `$.flow.delay()` call inside code can't be converted in place: split the step in two and put a Wait node between the halves.

## Parallel and loop blocks

Pipedream's docs still listed parallel and looping as coming soon, but the builder supports them, so your export may contain them.

**Parallel.** Each branch has a mode: always run, run when its rules match, run when they don't, or never run. Workflow Exit connects every branch that can run to the same node, puts an If node in front of each conditional branch, and joins the branches with a Merge node. A Code node named after the block then returns `{ branch_name: result }`, the shape Pipedream returned. Two things differ: n8n runs the branches one after another, not at the same time, and a Merge node takes at most 10 inputs. Branches set to never run stay on the canvas, unconnected.

**Loop.** Pipedream ran the branch once per element of a list and returned the results in order. Workflow Exit builds three parts:

1. A Code node named `<block> items` that turns the list into one item per element, with `item` and `idx` fields.
2. A Loop Over Items node named `<block> loop`, with a batch size of 1, that runs the loop's steps for each item.
3. A Code node named after the block that returns all the results once the loop is done.

Inside the loop, the current element is `$('<block> loop').first().json.item`. The checklist lists the steps that need that change.

**AI routing.** Pipedream's AI block, where an OpenAI model picked the branch, becomes a Text Classifier node with an OpenAI chat model and your own OpenAI credential.

## Test every branch before you switch

1. Import the workflow and open each If and Switch node. Look in the checklist for rules that couldn't be read.
2. Replay a saved event for every branch, plus one event that matches nothing.
3. Check the output of each end-of-block node, which later steps read.
4. Compare the results with Pipedream's, then disable the Pipedream workflow.

The [free migration report](/report) lists every if/else, switch, filter, delay, parallel and loop block in your export with its n8n target, and flags rules it can't read. It runs in your browser. When you're ready, the [paid conversion](/pricing) builds these nodes for you, and the [Pipedream to n8n guide](/pipedream-to-n8n) covers the rest of the move.

## Frequently asked questions

### Does the n8n If node have an else branch?

Yes. The If node has a true output and a false output, and the false output plays the part of Pipedream's Else branch. A Switch node does the same with its fallback output.

### Does the n8n Switch node run more than one branch?

Not by default. In Rules mode it sends each item to the first matching rule, as Pipedream's blocks did. Leave the option that sends items to all matching outputs turned off.

### Why does my condition behave differently after moving to n8n?

Usually because of case or types. Pipedream's text rules ignore case unless match case is on, while n8n compares case-sensitively by default. n8n's strict type validation also stops on a number that arrives as text.

### How do I end an n8n workflow early, like Pipedream's End Workflow?

Leave the branch without a next node, or return an empty array from a Code node. Nodes that receive no items don't run.

### What replaces Pipedream's parallel block in n8n?

Connect several branches to the same node, then join them with a Merge node. n8n runs those branches one after another rather than at the same time.
