← Blog

Automation

n8n, Make, or Node: 50k events a day, three months in

Same eleven-step pipeline, same Dutch e-commerce brand, three different engines. What two weeks each in production showed us about cost and failure.

Jacob Molkenboer· Founder · A Brand New Company· 4 Jun 2026· 9 min
Three brass relays in a row, a paper telegram with a green tab, linen ribbon and red wax seal on ivory paper.

The brand sells home goods. Mid-seven-figure revenue, a Rotterdam warehouse, four marketplaces, one Shopify storefront. Every customer touch fires an event. Order placed. Shipment created. Return scanned. Review left. Refund issued. Roughly 50,000 a day on a normal Tuesday. Black Friday last year hit 380,000 in eighteen hours.

Those events fan out to seven downstream systems. ERP. Accounting. Email tool. Support desk. BI warehouse. Review aggregator. And a Slack channel where the operations lead watches for anomalies. Most of the work is plumbing. None of it is interesting until it breaks.

When we walked in last September, the brand was on Make. It had been the right call two years earlier, when volume was 4,000 events a day and a marketing intern could glue scenarios together with the visual builder. Now the monthly bill was climbing past €1,400, and one scenario had silently dropped 1,200 refund webhooks over a weekend. The operations lead asked one question. Keep Make, move to n8n, or build a Node worker. Pick one.

We did all three, in production shadow mode, for two weeks each. Here is what we saw.

The workload we were measuring

A typical event path looked like this. Shopify fires orders/create. The pipeline enriches the payload with the customer's lifetime value from BigQuery, runs a fraud rule, posts to the ERP, queues a transactional email, writes a row into the BI warehouse, and updates a tag back on the Shopify customer. Six external calls. One conditional branch. Two retry-on-failure paths.

50,000 events a day at six calls each is 300,000 outbound API calls. That second number is what made the choice non-obvious.

Round one: Make at the new volume

Make charges per operation, and every module in a scenario counts. The order-enrichment scenario was eleven modules wide. At 50k events a day that is 550,000 operations a day. Fifteen and a half million a month.

Make's published pricing stops being published once you cross a few million ops a month, so we got a quote. It was real money. The quote also included a fair-use ceiling on parallelisation that would have throttled the Black Friday burst.

The bigger issue was visibility. When the refund scenario quietly dropped 1,200 webhooks, the failure showed up as a stack of red dots in the scenario history. No alert. No Slack ping. The error handler had been configured against the wrong webhook ID two refactors ago, and nobody had tested the path since. You can fix this in Make, but you have to remember to fix it in Make. The cost of that institutional memory is part of what you are really paying for.

Make stayed fast. The visual builder is genuinely good for the first six months of a workflow's life. The problem is that the workflow does not stay six months old.

Round two: n8n self-hosted on a single VM

We span up a 4-vCPU, 16GB DigitalOcean droplet, ran n8n in Docker behind Caddy, pointed Shopify webhooks at a staging endpoint, and shadow-ran the same eleven-step pipeline against a copy of production traffic.

n8n at 50k events a day was not fine out of the box. The default SQLite executions database started locking under load around 8,000 executions an hour. We moved to Postgres, switched to queue mode (n8n's worker model with Redis), and the box held. CPU sat around 35% on a normal Tuesday. We did a synthetic load test at 4× Black Friday volume. It held.

The queue-mode setup was the boring kind of work. One main instance handling webhooks and the UI, three worker containers picking jobs off Redis, Postgres for execution history, restart policies, a health check on /healthz. None of it is hard. All of it is yours.

# docker-compose excerpt for the n8n setup we ran
services:
  n8n-main:
    image: n8nio/n8n:latest
    environment:
      EXECUTIONS_MODE: queue
      QUEUE_BULL_REDIS_HOST: redis
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres
      N8N_PROTOCOL: https
      N8N_HOST: flows.brand.nl
    depends_on: [redis, postgres]

  n8n-worker:
    image: n8nio/n8n:latest
    command: worker --concurrency=10
    deploy:
      replicas: 3
    environment:
      EXECUTIONS_MODE: queue
      QUEUE_BULL_REDIS_HOST: redis
      DB_TYPE: postgresdb
      DB_POSTGRESDB_HOST: postgres

What we liked: the workflows are JSON. They go in git. Pull requests are reviewable. We could write tests against the trickier conditional branches by exporting a workflow, feeding it a payload via the CLI, and asserting on the output. That alone closed the visibility gap that bit the brand on Make.

What we did not like: the connector library is smaller than Make's, and a few of the Dutch tools the brand used (Mollie, Exact Online) needed custom HTTP-request nodes rather than first-party integrations. That added maybe two engineering days to the migration. Not free, but not catastrophic.

The infra cost was one droplet. Forty-eight euros a month, plus our time.

Takeaway

The line where Make stops being the cheapest option is roughly when your monthly operations cross seven figures. Before that, paying for someone else's reliability is usually correct.

Round three: a Node worker on Cloud Run

The third option was the one the brand's technical co-founder wanted. Rip out the workflow tool, write a Node service, deploy it to Cloud Run, done.

We built it. Fastify for the webhook receiver, BullMQ on Redis for the queue, a thin handler-per-event-type pattern, OpenTelemetry for traces. About 1,400 lines of TypeScript including tests.

// handlers/orderCreate.ts
import { Job } from 'bullmq'
import { z } from 'zod'
import { enrichWithLtv, postToErp, queueEmail, writeWarehouseRow, tagCustomer } from '../svc'

const OrderCreate = z.object({ id: z.string(), customer: z.object({ id: z.string() }) })

export async function handleOrderCreate(job: Job) {
  const order = OrderCreate.parse(job.data)
  const ltv = await enrichWithLtv(order.customer.id)
  if (ltv.flag === 'fraud-suspect') return job.moveToFailed(new Error('fraud'), 'manual-review')
  await Promise.all([
    postToErp({ order, ltv }),
    queueEmail({ template: 'order-confirm', order, ltv }),
    writeWarehouseRow({ order, ltv }),
    tagCustomer({ id: order.customer.id, tag: ltv.tier }),
  ])
}

It was the fastest of the three. p95 latency end-to-end was 340ms, against 1.2s for n8n and 2.8s for Make. Cloud Run cold starts were a non-issue because the workload kept at least one instance warm all day. The monthly compute bill came in under €30.

But the speed was not the point. The point was that the Node worker was the only option where adding a new downstream integration meant a code review and a deploy, not a click and a save. That is good when the team can absorb the discipline. It is bad when the marketing manager wants to add a new tag-customer step at 11pm on a Sunday and the only person who can deploy is in a different timezone.

We also burned about nine engineering days getting the worker to feature parity. n8n was two days. Make was zero, because Make was already there.

The cost picture, honestly

Here is what the three months looked like in total cost of ownership, normalised to "ship the same eleven-step pipeline, run it at 50k events a day, keep it running for twelve months":

  • Make: ~€1,800/mo in operations + 0 engineering days to migrate + about 2 days/month of operational toil chasing failed scenarios. Roughly €25k/year all-in.
  • n8n self-hosted: ~€60/mo in infra + 2 engineering days to migrate + 0.5 days/month of toil. Roughly €5k/year all-in.
  • Node worker: ~€30/mo in infra + 9 engineering days to migrate + 0.5 days/month of toil + ongoing dev time for every new integration. Roughly €8k/year in year one, dropping after.

Those numbers are specific to one brand. They will look different at 5k events a day, where Make wins outright, and at 500k events a day, where the Node worker probably wins outright.

The shape of the curve is consistent across the per-operation vendors though. Make, Zapier, n8n Cloud, Pipedream. All of them are cheapest when your workflow count is in the hundreds and your monthly operations in the tens of thousands. None of them are cheapest once you cross a million ops a month. The pricing pages quietly stop showing numbers around then, which is itself the signal.

What we shipped

We picked n8n. Self-hosted, Postgres-backed, queue mode, workflows in git. We migrated all but two of the Make scenarios in twelve working days. The two we left on Make were edge-case marketing automations the marketing manager owned end-to-end. There was no reason to take her tool away.

The migration itself was a Saturday. Export every Make scenario to JSON, walk each one through a small Python translator we wrote for the recurring patterns, hand-port the eight scenarios the translator could not handle, replay two weeks of webhook history from our staging archive, diff the outputs against the Make side, and sign off on the discrepancies that were safe to ignore (mostly timestamp drift on the BI rows). By Sunday morning the traffic was on n8n. The Make scenarios stayed live for two weeks with their webhooks pointed at a swallowing endpoint so we could roll back without a deploy.

The Node worker stayed in the repo, deployed to a staging environment, handling the one path where 340ms mattered: real-time fraud scoring on checkout. Hybrid stack. The right engine for each lane.

The hidden cost nobody quotes

The thing all three options share is that the cost of building the pipeline is roughly 20% of the cost of owning it. The other 80% is in the year after launch, when the ERP changes its webhook schema, the email tool deprecates an endpoint, and a downstream system starts returning 429s during the Sinterklaas rush.

The tool you pick is mostly a bet on who you trust to absorb that 80%. Make absorbs the operational complexity for you and charges per operation. n8n gives you the engine and asks you to own the box. A custom worker gives you everything and asks you to own everything.

Warning

If your workflow tool's failure mode is "the dashboard turns red and nobody notices", you do not have a workflow tool. You have a slow-motion outage waiting for a quarter-end report.

A five-minute audit you can run tomorrow

Open your current workflow tool's execution log. Filter for errors in the last 30 days. For every error, answer two questions. Did anyone get alerted? Did anyone act on it? If the honest answer to either is no, that is your real signal, not the pricing page.

When we built this pipeline for the brand above, the win was not the tool swap. It was wiring the n8n failure path into the same Slack channel the operations lead already watched. If you are at the volume where this matters, we do this kind of process automation work end-to-end; the playbook is the same whether the engine is n8n, a Node worker, or both.

Key takeaway

Workflow tools are priced for one volume and quietly stop working at the next. Pick the engine your team can own at the volume you will have in twelve months, not the volume you have today.

FAQ

At what volume does Make stop being the right choice?

Roughly when your monthly operations cross seven figures. Below that, paying for someone else's reliability and the visual builder is almost always the cheaper answer.

Is self-hosted n8n production-ready at 50k events a day?

Yes, but not on defaults. You need Postgres for the executions database and queue mode with Redis-backed workers. SQLite locks under sustained load.

Why not just build a Node worker from day one?

Because the marketing manager cannot ship a new step without a deploy. A custom worker is the right answer when the team can absorb that discipline and wrong when it cannot.

What about n8n Cloud instead of self-hosting?

It works, but the per-execution pricing puts you back in the same per-operation trap as Make once volume climbs. Self-hosting is what makes the cost curve flatten.

Do you need monitoring beyond what n8n ships with?

At this volume, yes. We pipe execution failures into Slack via a dedicated workflow and ship Postgres metrics to Grafana. The built-in UI is fine for spot checks, not for paging.

automationintegrationsworkflowarchitecturetoolingcase study

Building something?

Start a project