Windmill vs n8n for Self-Hosted Automation: Scripts First or Nodes First

Leila Voss

Leila Voss

October 14, 2026

Windmill vs n8n for Self-Hosted Automation: Scripts First or Nodes First

Self-hosted automation used to mean one name: n8n. Drag nodes onto a canvas, connect them, and you have a private Zapier running on your own server. It is still the default choice, and for good reason. But a different kind of tool has been gaining ground with people who are comfortable writing code: Windmill, which starts from scripts rather than boxes, and turns them into workflows, scheduled jobs and small internal apps.

I run self-hosted automation for a one-person business, and I have had n8n, Activepieces and Windmill on the same Docker host at different times. The quickest way to understand the difference between Windmill and n8n is not a feature list. It is building the same job in both and noticing where each one makes you work.

The job: a weekly invoice reminder

Here is a real automation I run. Every Monday morning:

  1. Read the list of unpaid invoices from a Google Sheet.
  2. Skip anything not yet overdue, and anything already reminded in the last seven days.
  3. For each overdue invoice, send a polite reminder email with the invoice details.
  4. Write the reminder date back to the sheet.
  5. Post a short summary to a chat channel so I know it ran.

Nothing exotic: a schedule, a data source, some filtering logic, an email, a write-back and a notification. That mix, part integration and part logic, is typical of personal and small-business automation.

Building it in n8n: wiring boxes together

In n8n, the job is a chain of nodes on a canvas. A Schedule Trigger node fires on Monday at 9:00. A Google Sheets node reads the rows. An IF or Filter node drops invoices that are not overdue, and another checks the last-reminded date. A Gmail or SMTP node sends each email, a second Google Sheets node updates the row, and a Slack or Telegram node posts the summary.

The integrations are where n8n shines. The Google Sheets and Gmail nodes handle authentication, field mapping and pagination for you. You connect your accounts once, pick the spreadsheet from a dropdown, and map columns by clicking. For the date comparisons, you either use n8n’s expression syntax inside the filter nodes or drop in a Code node with a few lines of JavaScript or Python.

The result is easy to read at a glance: anyone can open the canvas and follow the flow from left to right. When it runs, n8n records every execution, and you can click into each node to see exactly what data passed through it, which makes debugging pleasant.

The friction appears as logic grows. Date arithmetic, nested conditions and “only remind if not reminded in seven days” become a tangle of expression strings and IF nodes, or a Code node that slowly absorbs the whole workflow. Many n8n users reach the point where the canvas is mostly a wrapper around one big Code node.

A node-based visual automation canvas with connected boxes on a wide monitor

Building it in Windmill: scripts first

In Windmill, you start by writing scripts. One Python or TypeScript script reads the sheet and returns the overdue invoices, with the filtering logic written as ordinary code: a few lines of date comparisons that any developer can read and test. A second script sends one reminder email. A third writes back to the sheet and posts the summary.

Windmill turns each script’s function parameters into a form automatically, so you can run and test each step on its own from the web interface, with real inputs. Credentials are stored as “resources” of typed kinds, such as a Google account, an SMTP server or a Slack token, and passed into scripts as parameters, so secrets never live in your code.

Then you combine the scripts into a flow: run the first, loop over its results calling the second for each invoice, then run the third. Windmill’s flow editor handles the loop, retries and error handling, and a schedule triggers the flow every Monday. Each run is logged with the inputs, outputs and logs of every step.

The friction here is the opposite of n8n’s. The logic is clean, but the integrations are your job. There is no drag-and-drop Google Sheets node that knows your columns. You use a library, or one of the many community scripts on Windmill’s hub, and handle the API details yourself. For someone who writes code daily, that is quick. For someone who does not, it is a wall.

Where each one wins

Building the same job twice makes the trade-off concrete:

  • Integrations: n8n, clearly. Hundreds of ready-made nodes, with authentication handled for you. Windmill relies on code and community scripts.
  • Logic: Windmill. Branching, loops, data transformation and dates are just code, in a real language, with real tests if you want them. In n8n, complex logic fights the canvas.
  • Readability for non-developers: n8n. A business owner can follow the canvas. A Windmill flow is readable, but the substance is in the scripts.
  • Reuse: Windmill. Each script is a reusable, testable unit with a generated form, so the “send reminder email” script can serve five different flows.
  • Internal tools: Windmill. Its app builder turns scripts into simple internal interfaces, such as a form to trigger a job or a table of results, which n8n does not attempt.
  • Performance at volume: Windmill is built around workers that run jobs quickly and scale out. n8n can scale too, with its queue mode, but needs more setup to get there.

If you are weighing n8n against other visual tools rather than a code-first one, Activepieces vs n8n covers that side of the decision.

A laptop showing container status for a small self-hosted server

The Monday it breaks

Automations fail in boring ways: an expired Google token, a renamed column, an invoice with a blank date. The difference between the tools shows most clearly on the morning one of these happens.

In n8n, the failed execution appears in the executions list, highlighted at the node that failed. Click it and you see the exact input that node received, often enough to spot the blank date immediately. You can fix the workflow and re-run the execution with the same data. You can also add an error workflow that runs whenever any workflow fails, which is the easiest way to get a notification.

In Windmill, the failed step shows its logs, its input and the full error from your script, including the line number. Because each script can be run on its own from its generated form, you can paste the failing invoice in as input and reproduce the bug in seconds. Flows can retry steps automatically and route errors to a dedicated handler script that alerts you.

Both are good at this. n8n is friendlier when the problem is in an integration; Windmill is better when the problem is in your logic, which is where most of mine turn out to be.

Running them yourself

Both run in Docker on a modest server. n8n can start as a single container with SQLite, and grows into PostgreSQL plus Redis-backed queue mode with separate workers when you need more throughput. Windmill’s standard setup is a few containers from the start, with a server, one or more workers and PostgreSQL, but it is well documented and the Compose file does the work.

Licensing differs in a way worth knowing. n8n uses its own “fair-code” licence, the Sustainable Use License, which lets you self-host for your own business but restricts offering n8n itself as a service to others; it is source-available rather than open source in the strict sense. Windmill’s core is open source under the AGPL, with an enterprise edition adding features such as advanced permissions and audit logs. For personal and small-business use, both are free to self-host. If you plan to build a product on top of either, read the licences carefully.

Whichever you choose, automation that runs your business needs the same care as any other critical service: back up its database, keep it updated, and make sure failures reach you. A workflow that silently stops on a Monday is worse than no automation at all, because you stop checking by hand.

Is either one overkill?

Before installing anything, it is worth asking whether you need a platform at all. A few scheduled jobs can live happily as scripts run by cron, with a monitoring ping at the end. A platform earns its place when you have many workflows, want a history of every run, need other people to see or trigger them, or connect enough services that credentials and retries become a chore. That threshold is explored in when n8n is overkill, and the same reasoning applies to Windmill.

Which way of working fits you

The honest answer depends less on features than on how you think. If you picture automation as boxes and arrows, and most of your work is moving data between well-known services, n8n will feel natural from the first hour, and its integrations will save you days. If you picture automation as code that happens to run on a schedule, and your workflows are mostly logic with a few API calls, Windmill will feel like a relief: real code, real tests, and a platform that handles scheduling, retries, secrets and logs around it.

Plenty of people end up using both: n8n for the integration-heavy glue, Windmill for the jobs that are really programs. If you write code every day and have felt your n8n canvases turning into one giant Code node, Windmill is the experiment worth running next.

More articles for you