Ten n8n tips

2023-02-05 · Ben Williamson

n8n is a new-ish ETL tool I've been using for the better part of a year. It's built with Typescript and Vue, and is Open Source, self hosted and free. Their cloud offering is a good price compared to the alternatives- with no api call limits, just workflow limits. Check them out at n8n.io

With n8n the modern web projects I work with are a breeze. I use it as an API micro-service communication layer between products for complex and simple opperations alike. Why build custom stuff burried in your code base when you could use existing APIs and a little typescript to get it done instead? No deployments, no downtime, no devop cycle (not really). It's the definition of agile.

So for those that I know and work with, I've created some helpful docs and videos to get you going.

These are the first 10 things that come to mind when I think "N8N Tips"

1: Turn on save manual execution data while developing

Ref: n8n course one chapter five

In each workflow you can configure what data is saved - manual executions by default are NOT saved. Toggle this to ON for a better dev experience.

If something goes wrong in your manual execution, or the browser de-syncs, you can flip over to the execution tab and see everything that happened.


2: Pin or Mock Data while developing

These features do not work in production workflows- only while testing

By pinning and/or mocking data of previous nodes we can save a lot of time. This reduces api calls, and requirements/blockers to dev efforts.


3: Use expression fields to get node syntax

When working in a code node, the intellisense is nice- but doesn't give a good UX for finding output or parameters of previous nodes.

With a partial execution, mocked data, or pinned data- use any node with an expression field (Like the Set node) at the end of the flow. With this you can use the standard expression click-adventure to quickly find the right syntax for specifics in the flow.


4: If a flow is out of sync

Switch to executions tab of the current flow and back, sometimes the UI just needs a bump.

and/or

Click stop - Most flows only take a matter of seconds- you can click stop on the running flow to many times force the UI to sync up


5: JmesPath and Luxon

First of all, Use them. While they are intimidating at first- they do save a lot of time and code effort. 90% of what you'll use can be found on the two pages linked here for copy+paste

Also, go to their docs.

If you have a specific use case that's not covered in the above, the docs for these libraries have more examples.

JmesPath examples
Attached file: JmesPath examples

In n8n the Jmespath search syntax is reversed compared to the official docs

The examples in the JMESPath Specification

Attached file: JMESPath Specification
follow the pattern search(searchString, object). The JMESPath JavaScript library, which n8n uses, supports search(object, searchString) instead.

The short version: in n8n you'll do: $jmespath($input.all(), "[?json.whatever=='foo'].[field1, field2]")

Luxon Formatting examples

The short version: You'll normally want $now or $today with .toLocaleString() including a format type found on the above link.

eg $now.toLocaleString(DateTime.DATETIME_FULL); //=> 'April 20, 2017 at 11:32 AM EDT'


6: Node settings

Use them!

Especially Always Output Data and Continue On Fail


7: Use the browser dev tools

console.log() can be used in any expression or code node, anywhere!

N8N frontend is built with Vue - if you are familiar with vue dev, you may be able to leverage vue dev tools in your browser.

Use the Network tab, especially with the HTTP Request node - when sending requests manually the payload will be logged in the network tab for review


8: Start at the docs - then community - then github/google

Trouble? Questions? Bugs? (Or so you think?)

  1. First search the docs: https://docs.n8n.io/
  2. If no luck, search the forum: https://community.n8n.io/
  3. Still no luck? Quickly check their github issues page with no filters before turning to google.

9: Incoming data can be modified

While it may not be intuitive, the $input in each node is mutable (not read only).

This is demonstrated in the example code whenever you place a new code node, but that's not where it stops. You can use the $input objects for storage of your transformed data, and then return $input.all() when you're done, instead of trying to build your own object.


10: Use backticks and plain text

Another not-so-intuitive thing- you may get the impression from the docs that all expressions and code need to be wrapped in some special way.

Eg {% raw %}

{{ "I want " + "to concatenate this" }}

{% endraw %}

Not so- you CAN do {% raw %}

I want {{ "" }} to concatenate this

{% endraw %} in an expression field.

You can also do this in code blocks to make life easier, and it's perfectly valid:

let myBigString = `
<html>
    <div> All the things in the html</div>
    <p>Some ${$input.first().json.fieldName} dynamic stuff too.</p>
    <em>This also captures newlines!</em>
</html>
`

Ok, now go automate some stuff!