Skip to main content

What We Learned

Self-hosted n8n with a single worker cannot call its own public webhook URL from within an executing workflow. The calling workflow occupies the worker; the callee webhook queues but never executes; the caller times out after 10 minutes. This is a textbook concurrency deadlock with no obvious error message — the failure looks like a connection timeout, not a resource exhaustion. The fix is a one-line URL change in the HTTP Request node: replace the external URL (https://hab.so1.io/webhook/atomiser) with the internal URL (http://localhost:5678/webhook/atomiser). n8n routes localhost calls differently from external calls, allowing concurrent execution even with a single worker configured.

Why It Matters

This pattern applies to any n8n deployment where one workflow orchestrates another on the same instance. The architecture is common — a “dispatcher” workflow that breaks work into chunks and triggers “worker” workflows. If the dispatcher waits for the worker’s response, and both use the public URL, it deadlocks every time. The rule: n8n workflows calling sibling workflows on the same instance must use http://localhost:{port}/webhook/{path} not the public URL.

Operational Implication

When debugging a FORGE execution that runs for exactly 10 minutes then fails at Trigger TOMMY: check the URL. If it contains the public hostname, change it to localhost. If the port is unknown, check what process is listening on 5678 on the n8n host (ss -tlnp | grep 5678). For production deployments expecting blocks longer than 10 minutes, also increase the timeout on the HTTP Request node (options.timeout) beyond 600000ms, or switch to n8n’s native Execute Workflow node which avoids HTTP routing entirely.