Measured

Speed, measured.

Our own test, on one machine, with authentication off. The n8n and Activepieces speed runs aren’t finished, so no speed is compared.

800calls a second0errors3.66ms median reply

p99 at 800 a second
189 ms
Slowest of 96,000
373 ms
Idle, API + worker
23.2 MB

Our own run, 22 Sep 2026 · one M4 Pro machine · API + worker capped at 2 vCPU / 4 GB, Postgres + Redis on 4 more · dev mode, authentication off · per-address webhook limit lifted from 3,000/min · S3 offload off

What ran.

One workflow, called by webhook 96,000 times in two minutes. It sets two fields and replies with JSON, and the caller waits for the reply.

  1. Catch WebhookWebhook
    total: 740
  2. Edit Fields
    approved: true
  3. Return ResponseWebhook
    200 · JSON
  4. Worked 

The benchmark’s own workflow · every reply was checked · each call is one run

Every call, drawn.

One line for each second at 800 calls a second, for 120 seconds. A line rises where a reply was slower. No call failed.

Every one of the 96,000 calls at 800 a second, one drawn line per second for 120 seconds; the line rises where a call was slow. No call failed. On small screens, the 30 slowest seconds.Every one of the 96,000 calls at 800 a second, one drawn line per second for 120 seconds; the line rises where a call was slow. No call failed. On small screens, the 30 slowest seconds.

each line = 1 seconda rise = a slower reply100 mserror — none

Evidence · All 96,000 calls, one line per secondSeconds 4–33 of 120, the slowest stretch · our own run, 22 Sep 2026 · one M4 Pro machine · dev mode, authentication off

Every step.

From 50 to 800 calls a second the median stays between 3 and 6 ms; at 10 a second it is 10.48 ms. p99 is uneven, printed as it came out.

GoRunner, open-loop, 120 seconds per step
Calls a secondAnswered a secondMedianp99Errors
101010.48 ms18.8 ms0%
50505.24 ms22.3 ms0%
1001003.99 ms12.3 ms0%
2002003.21 ms112.3 ms0%
4004003.18 ms18.2 ms0%
8008003.66 ms189.4 ms0%
The method, in full

Measured by the GoRunner team, not independently, on one Apple M4 Pro machine (Docker Desktop, 12 CPUs), one engine at a time. Each engine’s app containers shared a 2-CPU, 4 GiB limit; Postgres 16 and Redis 7 ran outside it, on 4 other vCPUs, with the same settings for all three. At full load GoRunner drew about 1.1 of those vCPUs, so each capacity figure comes with a CPU cost per answered call that counts app and database together. Every engine ran the same three steps (a webhook, a step that sets two fields, a JSON reply) and stored every run in Postgres; there are no calls to outside services, so this measures engine overhead, not a real workflow. GoRunner ran as one API and one worker, in dev mode with authentication off, because its other modes need sign-in; all load came from one address, so its per-address webhook limit was lifted from its shipped 3,000 a minute (at that limit, 29.9% of calls at 100 a second got HTTP 429). n8n 2.40.5 ran in queue mode (not its default) with one main and one worker at its default concurrency; its default single-process mode held the same 50 a second, with the same capacity, and ran out of memory at 100 a second. Activepieces 0.91.1 ran on its shipped defaults, in one container: the best of four shapes its docs describe (one ran out of memory). By its docs this shape needs about 3.5 CPUs and 6 GB, more than this limit; it peaked at 3.5 GiB. None had S3 offload or a reverse proxy, and telemetry was off; Activepieces says S3 is needed for its own published numbers, and n8n prefers Postgres 17. The load generator ran on the same machine. Calls came at fixed rates, 120 s per step, each timed from when it was due; a call counts only if the correct reply arrived within 30 s, and a rate is held only if every run at it lost under 1% of calls and kept p99 under 10 s. Every engine ran in two sessions, overnight on 22–23 Sep 2026 and on the morning of 24 Sep; the rates shown are GoRunner’s slower session (22 Sep), n8n’s better one (24 Sep) and Activepieces’ best shape, run once on 24 Sep. Capacity is correct answers per second with 64 connections kept busy, in the last 2 of 4 minutes on a fresh stack: the median of three sessions on 24 Sep with the order rotated (Activepieces’ shipped-defaults shape was measured once). GoRunner was not saturated at 64 connections, and 800 a second was the top of the test, so both of its figures are floors, not limits. Idle memory is the app containers’ own memory after 60 s idle, the median of the capacity runs. Also: GoRunner is closed-source, so outsiders cannot rerun its side (its images are available on request); n8n and Activepieces sized their memory from the machine’s 7.75 GiB, not the 4 GiB limit; the machine was in use, with other idle containers and desktop apps running; and all engines got 64 connections, where Activepieces’ own guide suggests one per execution slot. Images are compressed linux/arm64.

Every caveat.

What the numbers above rest on, and what they don’t say.

The raw per-call results, the load generator, the compose files and the workflow are kept with the run, so it can be repeated. Ask us for them.

Image size.

87 MB: four container images, compressed, dashboard included. Postgres and Redis extra.

Size, not speed · compressed linux/arm64 images, measured 22 Sep 2026 with docker image inspect · n8n and Activepieces are one image each, UI included