Coopen Free audit →

Coopen / Automation / n8n workflows

n8n workflows: how they actually work.

An n8n workflow is a chain of nodes that passes data from one step to the next: something triggers it, each node transforms or sends the data it receives, and the result lands wherever you told it to go. That much is easy. What trips people up is the data model underneath — so this page explains that properly, with examples you can copy, before it explains what we do.

Platforms we build on

Developer building an automation across a multi-monitor workstation

What an n8n workflow is

n8n is a workflow automation tool you can run on your own server. You build automations visually on a canvas: each box is a node, the lines between them are the path the data takes, and the whole thing is triggered by a schedule, a webhook, an event in another app, or a button you press.

Where it differs from the hosted connectors most people meet first is ownership. You can self-host it, which means execution volume stops being a billing event and your data never leaves infrastructure you control. It is fair-code licensed rather than fully open source: the source is available and self-hosting for your own business is free, with restrictions on reselling it as a service.

The other difference is depth. A workflow can branch, loop, call sub-workflows and drop into JavaScript or Python whenever the visual nodes run out of expressive power. That makes it viable for real business logic rather than only for glue between two SaaS apps — and it is why we default to it when a client needs serious automation without a licence per task.

Anatomy

The six parts of every workflow

Learn these and the rest of the tool is detail.

  • Trigger nodeWhat starts the run: a schedule, an incoming webhook, an app event, or manual execution while you build.
  • Regular nodesEverything after the trigger — call an API, query a database, transform data, send a message.
  • ConnectionsThe lines between nodes. They define order and branching; a node only runs when data reaches it.
  • ItemsThe data itself. Every node receives an array of items and outputs an array of items. This is the concept everything else depends on.
  • ExpressionsSmall snippets like {{ $json.email }} that pull values out of the data flowing through, evaluated per item.
  • CredentialsStored separately from the workflow and encrypted, so an API key is configured once and reused everywhere.

The core concept

How data moves between nodes

This is the part worth reading twice, because almost every confusing n8n behaviour traces back to it. Data travels as an array of items. Each item is an object with a `json` property holding your actual data, and optionally a `binary` property for files.

Most nodes run once per item automatically. If a node outputs fifty items, the next node executes fifty times — you do not write a loop for that, it is the default behaviour. That is why fetching fifty rows and then calling an API "once" quietly makes fifty API calls.

The corollary catches everyone at least once: if a node outputs zero items, every node after it simply does not run. Nothing errors, nothing is logged as a failure, the execution just ends early and looks successful. When a workflow "does nothing" with no error, an empty item array is almost always why.

Expressions — reading data as it flows
{{ $json.email }}
// A field on the item currently being processed.

{{ $('Fetch Orders').item.json.total }}
// The matching item from an earlier node, by node name.

{{ $now.minus({ days: 7 }).toISO() }}
// Dates use Luxon. Handy for "everything since last week" filters.

{{ $json.lines.map(l => l.sku).join(', ') }}
// Plain JavaScript works inside expressions.

When a branch needs data from two different paths, the Merge node joins them — by position, by a matching field, or by simply appending one set to the other. Reaching for the Merge node is usually the fix when a workflow "loses" fields halfway through: the data did not disappear, it went down a different branch.

Examples

Three workflows worth copying

These are shapes we build repeatedly for clients. None of them needs a Code node, and all three are a few hours of work once the credentials exist.

  • Inbound lead to CRM to SlackWebhook trigger → validate the payload → look up whether the company already exists → create or update the CRM record → post to the sales channel with the enrichment attached.
  • Nightly report from two systemsSchedule trigger → query the database → fetch yesterday's figures from an API → Merge by date → format → email the summary and write the row to a sheet.
  • Document inbox to structured dataEmail trigger with attachment → extract the file → send it to an AI extraction step → validate the fields against rules → post to your accounting system, or route to a human if confidence is low.
  • Sub-workflow for the shared partThe "notify a human and wait" logic lives once in its own workflow and is called by the other three via Execute Workflow. Change it once, every caller gets it.

When nodes are not enough

The Code node, and when to reach for it

The Code node runs JavaScript (or Python) over the items passing through. It has two modes and picking the wrong one is a common source of confusion: "Run Once for All Items" gives you the whole array to work with, while "Run Once for Each Item" gives you a single item and runs repeatedly.

Use it for reshaping data, non-trivial filtering and calculations that would take six visual nodes to express. Do not use it as a place to call APIs and hide half the workflow — the value of a visual workflow is that someone else can read it, and a hundred-line Code node throws that away.

Code node — Run Once for All Items
// Keep only the big orders, and reshape them for the next node.
const items = $input.all();

return items
  .filter((item) => item.json.total > 100)
  .map((item) => ({
    json: {
      id: item.json.id,
      customer: item.json.customer.name,
      total: item.json.total,
    },
  }));

Every Code node must return an array of items shaped like { json: {...} } — returning a bare object is the most common error here.

Production

Error handling: the part that decides if it survives

A workflow that works on the happy path is a demo. What makes it a system is what happens when an API rate-limits you, a token expires, a field arrives null, or a third party has a bad afternoon. n8n gives you four mechanisms and a production workflow generally uses all four.

  • Retry on failPer node: number of attempts and the wait between them. Fixes the majority of transient API failures on its own.
  • Continue on failLets the workflow carry on past a node that errored, so one bad record does not kill a batch of five hundred.
  • Error workflowA workflow-level setting pointing at a second workflow that runs when this one fails — where you put the alerting.
  • Error Trigger nodeThe entry point of that error workflow. It receives what failed, in which node, with which data.

The other half is idempotency. If a workflow can run twice on the same input — and eventually it will, through a retry or a duplicate webhook — it must not create the invoice twice. Keying on an external ID and checking before creating is boring and it is what separates automation people trust from automation people quietly turn off.

Running it

Self-hosted or n8n Cloud

Both are legitimate. The decision is usually about data and volume rather than about features, since the editor and the nodes are the same either way.

Self-hostedn8n Cloud
Where data livesYour infrastructureThe vendor's
Cost shapeFlat — your server, any volumePer workflow execution
Who patches itYou (or us)The vendor
ScalingQueue mode with Redis and worker processesHandled for you
Best whenSensitive data, high volume, internal systemsSmall volume, no ops appetite

If you self-host, three settings matter more than the rest: set a persistent encryption key before creating any credentials — regenerate it later and every stored credential becomes unreadable; turn on execution data pruning, because execution history grows without limit and will eventually fill the disk; and put it behind a proper reverse proxy with the webhook URL configured, or your webhook nodes will hand out addresses nobody can reach.

Comparison

n8n vs Zapier vs Make

They overlap more than their marketing suggests. The honest split is that hosted connectors are faster to start and priced per unit of work, while n8n costs more setup and then stops charging you for volume.

n8nZapierMake
HostingSelf-host or cloudVendor cloud onlyVendor cloud only
Billing unitWorkflow execution (flat if self-hosted)Per taskPer operation
Complex logicBranching, loops, sub-workflowsLimitedGood visual routing
Custom codeJavaScript and Python nodesCode stepsLimited
Data residencyYours, if self-hostedVendorVendor
LicenceFair-code, source availableProprietaryProprietary

Our rule of thumb: three simple connections between popular SaaS apps and nobody to run a server, use a hosted connector. Steady volume, sensitive data or logic with real branching, use n8n. A legacy system with no API at all is neither — that is an RPA problem.

From experience

The mistakes we see most

Every one of these has cost somebody a weekend, including us.

  • Building in productionTest executions hitting live systems. Use test credentials and a staging path, or you will email real customers.
  • Ignoring the item modelA node that "runs once" actually running per item, quietly making hundreds of API calls.
  • No error workflowFailures nobody notices for a week, because the workflow is silent when it dies.
  • Everything in one workflowA canvas with eighty nodes that nobody dares change. Split it and call sub-workflows.
  • No version controlWorkflows only exist inside the instance. Export the JSON into a repository so changes are reviewable and revertible.
  • Losing the encryption keyRebuild the container without persisting it and every credential has to be entered again.

How it works

What we do when a client hands us this

You do not have to become an n8n team to get the benefit of one.

  1. Map the process first

    On paper, including the exceptions. Half the time the process gets simplified before anything is built.

  2. Build with the failure path

    Retries, error workflow and idempotency from the start, not bolted on after the first incident.

  3. Host it properly

    Your infrastructure or ours: encryption key persisted, pruning on, backups, and monitoring that alerts a person.

  4. Hand it over documented

    Named nodes, exported JSON in your repo and a walkthrough — so small changes never require calling us.

Results

What you get out of it

Flat

Cost at any volume

Self-hosted execution means growth is not a per-task billing event.

Yours

Data and workflows

Running on your infrastructure, exported to your repository, documented.

Watched

Not set-and-forget

Alerting on failures, so a broken workflow is noticed by us and not by a customer.

FAQ

n8n workflow FAQ

What is an n8n workflow?

It is an automation built from connected nodes. A trigger node starts it — a schedule, a webhook or an app event — and each following node receives data, does something with it and passes the result on. Data travels as an array of items, and most nodes run once per item.

Is n8n free?

Self-hosting is free for your own business use. It is fair-code licensed under the Sustainable Use License rather than a standard open-source licence: the source is available, but there are restrictions on offering it to third parties as a service. The vendor also sells a hosted cloud plan and an enterprise edition.

Why did my workflow stop halfway with no error?

Almost certainly a node returned zero items. Downstream nodes only run when data reaches them, so an empty result ends the execution early and it still looks successful. Check the output of each node in the execution log to find where the items ran out.

How do I reference data from an earlier node?

Use an expression like {{ $('Node Name').item.json.field }}. For the item currently being processed, {{ $json.field }} is enough. If the branches have diverged, use a Merge node to bring the data back together rather than reaching across.

Do I need to know JavaScript?

Not for most workflows — the visual nodes and simple expressions cover a lot. JavaScript helps when you need to reshape data or express logic that would otherwise take many nodes, and that is where the Code node comes in.

How does n8n compare to Zapier?

Zapier is faster to start and bills per task on the vendor cloud. n8n takes more setup, can be self-hosted so volume stops costing per unit, keeps data on your own infrastructure, and handles branching, loops and custom code far better. Small and simple favours Zapier; volume, sensitive data or real logic favours n8n.

Can n8n do AI steps?

Yes — there are nodes for language models and agents, which is useful for classifying incoming messages, extracting fields from documents and drafting replies. We build these with a validation step after the model, so its output is checked before it triggers anything that matters.

Can you build and run this for us?

Yes. We design the workflows, host the instance, wire up monitoring and hand everything over documented — including the exported JSON, so you can take it fully in-house whenever you want.

Is Coopen affiliated with n8n?

No. We are an independent software studio that builds on it because it fits a category of problem well. n8n is a trademark of its respective owner. We recommend it when it is the right tool and something else when it is not.

Carlos Ezequiel Centurión

Written by

Carlos Ezequiel Centurión · Founder, Coopen

Two decades building software, automation and hardware for businesses across three continents. Every automation on this site is scoped, built and handed over by the same engineer you talk to.

Ready to cut this cost?

Tell us the repetitive work slowing your team down. We'll show you what it costs — and what to automate first.