Sigma Logic AI Lead with AI. Thrive with Innovation.
Automation

When to write a custom n8n node

The threshold where five chained HTTP nodes should become one custom node, what writing one actually involves, and the three cheaper options to exhaust first.

On this page 12 sections
  1. Key takeaways
  2. Who this applies to
  3. Exhaust these three first
  4. The threshold
  5. What writing one actually involves
  6. What the code actually looks like
  7. A rough decision order
  8. The version that is neither
  9. What we do, and the bias we correct for
  10. When not to write one
  11. Frequently asked questions
  12. Next step

Write a custom node when the same integration logic - auth, pagination, error shaping - is duplicated across three or more workflows, or when a non-technical person needs to use the integration without seeing an HTTP request. Below that threshold, an HTTP Request node with a sub-workflow is cheaper to build and much cheaper to maintain.

Most teams reach for a custom node too early, because the HTTP node feels like a workaround. It usually is not.

Key takeaways

  • Duplication across workflows is the trigger, not complexity within one.
  • A custom node is code you now own, version and upgrade against n8n releases.
  • A sub-workflow gives you most of the reuse for a fraction of the commitment.
  • Auth handled once, in a credential type, is the strongest single argument for a node.
  • If one workflow uses it, you do not need a node.

Who this applies to

You are integrating a system n8n has no built-in node for - an internal API, a niche vendor, a partner endpoint - and you are deciding how much to build.

Exhaust these three first

1. The HTTP Request node

It handles most integrations completely: methods, headers, query parameters, body shaping, and n8n’s generic credential types cover basic auth, header auth and OAuth2 without any code.

For a single workflow calling three endpoints, this is the correct answer and there is nothing crude about it. A custom node here is strictly more work for the same behaviour.

2. A sub-workflow

The step most people skip, and usually the right answer at medium scale.

Put the integration logic in its own workflow - auth, the call, pagination, error shaping - and invoke it from the others with the Execute Workflow node. You get one place to change the API version, one place to fix a bug, and reuse across as many callers as you like.

What you give up against a real node: no typed parameter UI, no dropdowns, a slightly clumsier calling convention. What you keep: no build tooling, no npm package, no compatibility surface against n8n upgrades.

If you are considering a custom node, build the sub-workflow first. It takes an hour, it solves the duplication, and if it turns out to be enough you have saved yourself a maintained package.

3. The Code node

For transformation rather than integration. If the awkwardness is reshaping a response rather than fetching it, eight lines of JavaScript solves it and needs no packaging.

The four steps before a custom node, in order A rising staircase of four options. HTTP Request node for one workflow with few endpoints. Code node for reshaping a response. Sub-workflow for two or three workflows against the same API. Custom node, highlighted, for three or more workflows, fiddly authentication, or when non-technical users must configure it. HTTP Request One workflow, few endpoints Code node Reshaping a response Sub-workflow 2 or 3 workflows, same API Custom node 3+ workflows, fiddly auth, or non-technical use Exhaust each step before taking the next. Most needs stop at the first two.
Each step up costs more to build and more to maintain. A custom node is the right answer for a small minority of cases, and the staircase is how you find out whether yours is one.

The threshold

Write a node when two or more of these hold:

The same integration appears in three or more workflows. Duplication is the actual trigger. Two workflows is a sub-workflow; five is a maintenance problem.

Auth is non-trivial and repeated. Signed requests, token refresh, tenant-scoped credentials. A custom node lets you define a credential type once, and users pick it from a dropdown rather than pasting a token into a header field in every workflow. This is the strongest single argument.

Non-technical people need to use it. A node gives them labelled fields and dropdowns. An HTTP node gives them a URL and a JSON body, which is where operations teams break things.

Pagination or rate limiting is fiddly. Cursor pagination with backoff is genuinely awkward to express in a workflow and clean in code.

You will distribute it. Across teams, or to clients. A package installs; a sub-workflow gets copy-pasted and diverges.

What writing one actually involves

Not difficult, and not free either.

A node is a TypeScript package with a class describing the node’s properties - fields, dropdowns, display conditions - and an execute method that does the work. Credentials are a separate class. n8n’s node-creation tooling scaffolds the structure.

A straightforward REST integration with a handful of operations is one to three days including tests. Complex auth or many operations, more.

The part people underestimate is the ongoing side:

  • It is code you own. Someone maintains it when the vendor’s API changes.
  • It has a compatibility surface with n8n. Node API changes across major versions, and a node nobody updates eventually stops loading.
  • Self-hosted installation adds a step. Community nodes install through the UI or into the container; either way it is a deployment concern, and n8n Cloud restricts which community nodes can run.
  • It needs its own tests. A bug in a node used by eight workflows breaks eight workflows.

Call it a day to write and a few hours a year to keep, indefinitely.

What the code actually looks like

Worth seeing the shape, because the gap between “we should write a node” and “we have written a node” is smaller than people imagine and the maintenance is larger.

A node is two things. A description object declaring the node’s display name, its inputs and outputs, and the properties users configure - each with a type, a default, and optional displayOptions that show or hide it based on other selections. And an execute method that reads those properties, does the work, and returns items in n8n’s shape.

Credentials are a separate class declaring the fields to collect and how they attach to a request - a header, a query parameter, an OAuth2 flow. Declaring it once is what gives users a dropdown instead of a header they paste a token into.

The part that surprises people is the property definitions rather than the logic. A node with three operations and a dozen conditional fields has a description object several times longer than its execute method, and that object is where the usability lives. A node with a good execute method and a careless description is a node your operations team will misconfigure.

Two practical notes. n8n’s node-creation tooling scaffolds the structure, so you are editing rather than starting blank. And test the execute method as ordinary code - it is a function taking inputs and returning outputs, and treating it as untestable because it lives in a node package is a choice rather than a constraint.

A rough decision order

SituationBuild
One workflow, few endpointsHTTP Request node
Reshaping a responseCode node
Two or three workflows, same APISub-workflow
Three-plus workflows, fiddly authCustom node
Non-technical users must configure itCustom node
Distributing across teams or clientsCustom node, packaged
Vendor already has a community nodeEvaluate it before writing your own

That last row is worth checking properly. The community registry covers a lot, and an existing node - even an imperfect one you fork - beats starting from nothing.

The version that is neither

Sometimes the honest answer is that the integration should not be in n8n at all.

If the “integration” is really a body of business logic - reconciling two systems with rules, deciding what to do with conflicts, maintaining state between runs - that is a service. Writing it as a custom node buries logic in a package that is harder to test than a normal codebase, and harder to reason about than a small API.

The signal: the node’s execute method is growing branches that have nothing to do with talking to the vendor. At that point you are using the node system as an application framework, and it is not one.

What we do, and the bias we correct for

Our default is HTTP node, then sub-workflow, then custom node, and we hold that order harder than clients usually want to.

The bias we are correcting is that a custom node feels like the professional answer and an HTTP node feels like a shortcut. In practice the HTTP node is a supported, first-class part of the tool and the custom node is a package somebody has to own after we leave. On a handover-first engagement that asymmetry matters: we would rather leave a client with a sub-workflow they can read than a TypeScript package they cannot modify.

Where we do write nodes without hesitation: when auth is repeated and non-trivial, and when the people configuring workflows afterwards are not engineers. Both are cases where the node removes a real recurring cost rather than adding polish.

The opinion that occasionally costs us scope: if you have one workflow, you do not need a node, and we will say so on the call rather than quoting for one.

When not to write one

One workflow. Repeated, because it is the most common case.

A vendor API that is about to change. Wait for the stable version rather than maintaining a node through their migration.

Nobody to maintain it. A node without an owner becomes the reason an n8n upgrade gets deferred.

To avoid learning the HTTP node. Genuinely a reason people do this. The HTTP node is worth an afternoon.

Frequently asked questions

How long does a custom node take to write?

One to three days for a straightforward REST integration with a few operations, including tests. Complex auth pushes it further.

Can we use custom nodes on n8n Cloud?

Cloud restricts which community nodes may run, and privately-built ones are generally a self-hosted concern. Check the current policy before planning around it - see self-hosted n8n.

Should we publish it publicly?

Only if it is genuinely reusable and you intend to maintain it. A published node with an open issue list and no maintainer is worse for your reputation than no node.

What breaks a custom node most often?

The vendor’s API changing, then n8n major-version upgrades. Both are manageable with a cadence and neither is manageable with nobody assigned.

Is a sub-workflow really enough?

For most reuse, yes. You lose the parameter UI and gain zero build tooling. Try it before committing to a package - that is the whole recommendation.

Next step

If you are unsure whether your integration warrants a node, the deciding question is how many workflows will call it and who configures them. The n8n and Make engagement builds workflows under version control, with custom nodes only where they earn their keep.

Related: n8n vs Make · n8n error handling · Self-hosted n8n · Custom AI development

Let's talk

Got a workflow this applies to?

Describe it in a couple of sentences. We will tell you whether it is worth automating, what we would build, and roughly what it takes.