You've Outgrown n8n: When to Move to a Custom AI Agent (2026)

Seven signals a workflow has become a distributed system — and the hybrid most teams actually want

Jai Garg

HoD, Software Development

12 min read  ·  Tue Jun 02 2026

An equipment frame of glowing custom circuit boards built around a small, dark, plain plastic box

The signal that you've outgrown n8n is never that n8n got slow, or broke, or let you down. It's subtler: you notice you've started building things around it.

A repo of helper scripts the Code nodes call out to. A Postgres table you maintain by hand because the workflow needs to remember what it already did. A spreadsheet tracking token spend, because nothing else does.

None of these is a complaint about n8n. Each is a small, sensible patch. Collectively they're a message: the thing you're operating is no longer a workflow. It's a stateful service that happens to be drawn on a canvas.

What n8n is genuinely excellent at

Be clear about this, because the answer for a large share of teams asking this question is *stay where you are*.

n8n is one of the best tools available for connecting SaaS systems. The credential and OAuth handling alone represents work you do not want to reimplement — token refresh, scope management, and the authentication weirdness of a few hundred vendor APIs. It's equally good at unglamorous plumbing: scheduled jobs, webhook fan-out, retries on flaky endpoints, reshaping one vendor's JSON into another's. Self-hosting is real and well supported.

And the property most technical evaluations undervalue: a non-engineer can own an n8n workflow. An ops lead can change a Slack message, add a filter, or swap a recipient without a pull request or a deploy window. That's often the entire reason the automation exists, and it's what you lose the day the logic moves into a repo.

n8n 2.x has closed many gaps that older "not production-ready" posts complained about: native evals with datasets in Data Tables and built-in metrics; OpenTelemetry trace export; git-backed source control with a visual diff on the Enterprise tier; human approval gates on agent tool calls; MCP support in both directions. If you last evaluated n8n eighteen months ago, evaluate it again.

The inflection point, stated precisely

A workflow is a function of its input. A service is a function of its input and its history. The moment correctness depends on *previous* runs — what you already emailed, what the user said three turns ago, which half-finished job needs resuming after a crash — you're operating a stateful service. n8n can hold state; it just doesn't make state a first-class thing you can version, test, and reason about independently of the graph that mutates it.

Second: when control flow is chosen at runtime by a model rather than at design time by you. A directed graph represents a plan you decided in advance, not one a model decides per request. Once the model picks the path, the canvas documents your plumbing, not your behaviour.

Cross both lines and the tool is no longer the right *shape* for the problem. That's an architecture observation, not a criticism.

Seven signals you've outgrown it

1. The Code nodes stopped being glue

Symptom: Code nodes past a hundred lines, holding business rules rather than field mapping. When something breaks, you read the code, not the canvas.

Why: The visual graph is a source of truth only if the nodes are semantically meaningful. Once real logic lives inside opaque function bodies, the diagram shows sequencing while hiding behaviour.

Cost: That code has no IDE, no type checking, no linter, no dependency management, no unit tests — it's a string inside a JSON document. n8n 2.0's task-runner sandbox tightens this further: environment variables are blocked from Code nodes, and external modules on self-hosted instances need allowlisting. Correct security decisions, and a signal you're using an escape hatch as your authoring surface.

2. Error handling is most of the graph, and retries aren't idempotent

Symptom: Count your nodes. If more than half exist to catch, classify, route, or compensate for failures, the happy path has become a minority stakeholder.

Why: n8n gives you real primitives — per-node retry, an error output branch, dedicated error workflows. What no automation platform gives you is *transactional* semantics. A retry re-executes a node; it does not roll back the side effects of the attempt that failed. If the node charged a card before erroring, the retry charges it again.

Cost: Idempotency becomes your problem, and solving it means dedup keys, an operation ledger, and consistent at-least-once decisions — straightforward in code, awkward as nodes.

3. You need state that outlives a run

Symptom: Conversation memory across sessions. A job that runs for hours and must survive a restart. Work that pauses for a human and resumes days later with context intact.

Why: n8n has genuine pieces here — Data Tables, Postgres and Redis chat memory, a Wait node that resumes on a timer or webhook. But chat memory is a conversation buffer keyed by session, not an application state machine, and the default Simple Memory node is instance-local: fine for a demo, wrong for a multi-worker deployment.

Cost: You assemble a state machine out of Data Tables, Wait nodes and sub-workflows — one you can't unit test, can't migrate with a schema tool, and can't reason about without reading the whole canvas.

4. You can't tell whether a change broke something

Symptom: Changes ship by clicking Publish and watching. Confidence comes from someone remembering the edge case.

Why: n8n's evaluation tooling is real and worth using — an Evaluation Trigger gives you a test path isolated from production. But evals are not tests. Evals measure output quality on a sample. Tests assert that a unit, given specific inputs and mocked dependencies, produces a specific result — deterministically, in seconds, with an exit code that blocks a merge.

Cost: No unit tests on individual steps, no dependency injection to mock a third-party API, no red-green loop while editing. You need both kinds of check. n8n gives you one.

5. A generated JSON blob is not a reviewable diff

Symptom: Your review process is "open it in n8n and look at it," or there isn't one.

Why: Source control and a visual diff exist and work — but they're Enterprise-tier, and the artifact that lands in git is machine-generated JSON. Node IDs, coordinates and connection arrays churn alongside the change you care about. A pull request cannot usefully show that someone edited a system prompt or swapped a model.

Cost: Review moves out of the tooling your engineers already use, so it happens less — and your automation sits outside every code-quality control you've built.

6. The model picks the branch

Symptom: You're building multi-agent handoffs, a supervisor that decomposes tasks, or a loop whose iteration count depends on what the model found.

Why: n8n's AI Agent node handles a tool-calling loop well, and the human approval gate on tool execution is a genuinely good production feature. But the loop is internal to the node. The moment you need control *of* that loop — a planner spawning subtasks, agents handing off partial context, a retry that reformulates rather than repeats — you're either constrained by one node's opaque behaviour or rebuilding an agent runtime out of Switch and Execute Workflow nodes.

Cost: Non-determinism is the defining property of these systems, and a fixed graph is the wrong abstraction for it. This is usually what pushes teams toward custom agentic AI development — not performance, but expressiveness.

7. You can't answer "what does one run cost?"

Symptom: The model bill arrives and nobody can attribute it to a workflow, a step, or a customer.

Why: n8n exports OpenTelemetry traces and surfaces execution metrics in Insights, so latency and failure rates are covered. Token-level cost attribution is not first-class — the community solution is a workflow that writes token counts to a spreadsheet. That works, and it's also evidence: when a dozen community templates solve the same problem, the platform hasn't.

Cost: You can't tell which step regressed after a prompt change, compute unit economics per tenant, or set a budget guardrail mid-run. Fixing this — traces, per-step cost, evals sharing the same run IDs — is ordinary LLMOps instrumentation work, and much easier when the agent is code you control.

n8n vs custom agent vs hybrid

n8nHybrid (n8n + service)Fully custom
Time to first versionHours to daysDays to weeksWeeks
Who can maintain itOps and technical non-engineersOps owns edges, engineers the coreEngineers only
TestabilityEvals only, no unit testsReal tests on the core, evals end-to-endFull unit, integration and eval coverage in CI
State handlingData Tables, chat memory, Wait/resumeDurable state in your serviceWhatever the problem needs
Error recoveryRetries and error branches, no transactionsIdempotency in the service, alerting in n8nIdempotency keys, compensation, dead-letter queues
ObservabilityOTel export plus Insights, node-levelOTel both sides, correlated by run IDWhatever you instrument
Cost visibilityBuild it yourselfPer-call cost in the servicePer-step, per-tenant, budget-enforced
Integration breadthExcellent, hundreds of connectorsExcellent, inherited from n8nYou build every one
Cost of a small changeMinutes, no deployMinutes at the edges, deploy for the coreA deploy
Best whenDeterministic, integration-heavy, non-engineers own itRich integrations *and* real reasoningReasoning is the product, or compliance demands control

Read that honestly. n8n wins four rows outright. If those are the rows that matter to you, you have your answer.

The hybrid most teams actually want

You rarely rip n8n out. The durable architecture keeps it as the trigger and integration layer and moves the reasoning core into code behind a defined interface. One rule draws the boundary: *n8n owns talking to other systems and letting humans intervene. Your service owns anything whose correctness you need to prove.*

Stays in n8n: triggers and schedules; SaaS credentials and OAuth; fan-out to Slack, email and ticketing; human approval steps; any branch a non-engineer should be able to change without a deploy.

Moves to code: the agent loop; prompts and tool definitions; durable state and checkpointing; idempotency and compensation; evals and the golden dataset.

The interface should be coarse-grained, idempotent and versioned — not a chatty RPC surface, but a few meaningful operations (triage_ticket, draft_response) that accept an idempotency key, return a structured result plus a run ID tying back to your traces, and are safe to call twice.

An HTTP API is the obvious mechanism. The more interesting one is exposing your core as an MCP server: n8n's AI Agent connects to MCP servers as tools, and recent 2.x releases made that much easier to configure. The same server is then reachable from Claude, from an IDE, from your own application and from any future orchestrator — you write the capability once instead of once per consumer. That reusability is the main argument for building the boundary as an MCP server rather than a private API. It runs the other way too: n8n's MCP Server Trigger exposes selected workflows as tools to an outside agent.

A realistic migration path

Do this in order. Most teams stop somewhere in the middle, and that's a success, not an incomplete migration.

0. Define "working" first. Pull 20–30 real inputs from execution history — real ones, because synthetic cases miss the edge cases that actually break you — and record the outputs you'd accept.

1. Instrument what you have. Turn on OpenTelemetry export, attach a run ID that survives every hop, capture token counts and latency per model call. After two weeks you have a baseline and a ranked list of which steps are slow, expensive and failure-prone.

2. Extract the hot path only. Pick the subgraph with the most Code, the most error handling and the most spend — usually the same subgraph. Move it behind one idempotent API or MCP endpoint and replace it in n8n with a single tool call.

3. Leave n8n orchestrating. Don't move triggers, credentials or notification fan-out. That's the part you'd have to rebuild, and rebuilding it buys nothing.

4. Move state into the service. Migrate conversation memory and job checkpoints into a schema you own and can version. This is where resumability and multi-turn problems actually get solved.

5. Add evals to CI. Run the golden dataset against the extracted service on every commit and fail the build on regression. Keep n8n's evaluations for end-to-end checks; the two answer different questions.

6. Reassess. With the hard part in code, the remaining workflow is often exactly what n8n is good at. Many teams find they're done.

This avoids the big-bang rewrite, which fails for the usual reason: three months rebuilding integrations you already had, and nothing measurable at the end.

FAQ

Is n8n bad for AI agents?

No. For a large class of agent — a tool-calling loop over your SaaS systems, with a human approving consequential actions — n8n is a good production choice, and the 2.x AI features are serious work. It becomes the wrong tool when correctness depends on durable state, when control flow is model-chosen and dynamic, or when you need engineering-grade testing and review on the logic. Those are architectural mismatches, not quality problems.

How do I know I've actually crossed the line?

Two questions. *Does correctness depend on what happened in previous runs?* And *does the model choose the path rather than you?* Two yeses and you're running a stateful, non-deterministic service on a tool designed for stateless, deterministic ones. A cruder test: if your Code nodes were extracted into a repo, would that repo be the more accurate description of what the system does?

What does a custom agent cost to build and run?

Build cost scales with tool surface and state complexity, not model choice — the loop is a few days of work; integrations, idempotency, evals and observability are the bulk. Runtime cost has three parts: model tokens (dominant, highly sensitive to prompt and context design), infrastructure (usually small, since most agents are I/O-bound), and maintenance (the real one, and why evals in CI pay for themselves). Instrument your existing workflow first — the token line is normally the largest number, and you can measure it now.

Can we keep n8n for some things?

You almost certainly should — the hybrid above is the common end state, not a compromise. Keeping triggers, credentials and human-facing steps in n8n preserves the ability for non-engineers to make changes: often the highest-value property of the setup, and the easiest to destroy in a migration.

What framework should we use?

This matters far less than people think, and it's where teams spend the most time. The agent loop — call model, parse tool calls, execute, append result, repeat — is a small amount of code in any language. What determines production success is the surrounding engineering: tool schema design, idempotency, state persistence, retry semantics, evals and tracing. Frameworks help with the easy part. Pick whatever your team can debug at 3am, prefer thin over magical, and keep prompts and tool definitions as plain versioned data.

How long does a migration take?

Steps 0 through 2 — baseline, instrumentation, first extraction — typically run two to six weeks, depending on how much logic is trapped in Code nodes and how clean the integration boundary is. The full sequence through evals in CI is usually a quarter for a system of meaningful complexity. Anyone quoting a timeline without seeing your execution history is guessing. Each step ships independently and is reversible, which matters more than the total.

If you want a second opinion

If you're still unsure, that's reasonable — the honest answer depends on details a general article can't see.

We build production agent systems and MCP servers, and we're happy to look at your setup: your execution history, where the Code nodes have accumulated, and what your failure modes actually are. Sometimes the answer is a hybrid extraction. Sometimes it's a custom agent. Frequently it's three specific fixes inside n8n and a suggestion to revisit in six months — and we'll say so plainly, because a migration nobody needed is bad for everyone.