Tips > Building Workflows

Use Wait Nodes to Split Long-Running Workflows into Async Phases

Some business processes span hours or days -- submit an order, wait for payment confirmation, then fulfill.

Some business processes span hours or days -- submit an order, wait for payment, then fulfill. The Wait node pauses a workflow and resumes it later, after a delay or when an external webhook callback arrives. This frees resources during idle periods and models real async processes without polling loops or external schedulers.

What does the Wait node do?

Some business processes span hours or days -- submit an order, wait for payment confirmation, then fulfill. The Wait node pauses execution and resumes it later, either after a time delay, or when an external webhook callback arrives. This avoids holding resources during idle periods and models real-world async processes naturally.

Real-world example: An order fulfillment workflow that submits a payment, waits for the payment processor's webhook confirmation, then proceeds to fulfillment.

How do you pause and resume a workflow?

Workflow structure:

[Webhook: New Order] → [Validate Order] → [Submit Payment to Stripe]
    → [Wait: Resume on Webhook] → [IF: payment_succeeded]
        →── yes ──→ [Reserve Inventory] → [Generate Shipping Label] → [Notify Customer]
        └── no ──→ [Notify Customer: Payment Failed] → [Cancel Order]

Wait node configuration:

SettingValue
ResumeOn Webhook Call
Limit Wait Time24 hours
On TimeoutContinue (to failure branch)

After submitting the payment, store the Wait node's resume URL in your database alongside the order:

// Code node — after Submit Payment, before Wait
const resumeUrl = $execution.resumeUrl;
const orderId = $json.order_id;

// Pass to a database node to store:
return [{
  json: {
    order_id: orderId,
    stripe_payment_intent: $json.payment_intent_id,
    resume_webhook_url: resumeUrl,
    status: 'awaiting_payment'
  }
}];

Configure your payment processor (Stripe) to send its webhook to a relay workflow:

Stripe Webhook Relay workflow:

[Webhook: Stripe Events]
    → [IF: event.type === "payment_intent.succeeded"]
    → [Postgres: Lookup resume_webhook_url by payment_intent_id]
    → [HTTP Request: POST to resume_webhook_url with payment data]

The relay's HTTP Request node POSTs to the stored resume URL:

// The HTTP Request node POSTs to the stored resume URL:
// URL: {{ $json.resume_webhook_url }}
// Body:
{
  "payment_status": "succeeded",
  "payment_intent_id": "pi_abc123",
  "amount_received": 9999,
  "currency": "usd"
}

Why must you set a timeout?

Warning: Always Set a Timeout. Without a timeout, the Wait node holds the execution open indefinitely, consuming resources. Set a reasonable limit (24 hours for payments, 7 days for approvals) and handle the timeout case explicitly -- send a reminder, cancel the order, or escalate.

Wait nodes let you model real business processes faithfully without polling loops or external scheduling systems.

Related: Always Set an Error Workflow on Every Production Workflow · Use "Pin Data" to Freeze Node Output

Showcase builds

19 complete workflows from my own projects, each with its n8n workflow JSON to import. Showcase entries link the file at the end of the article.

See the showcase builds

Keep reading

190 entries grouped by topic, from first workflow to queue mode. Free, no signup.

Browse the encyclopedia

Need it built?

I design, build and run n8n systems for clients. Every engagement starts with a $1,500 diagnostic audit, credited toward the build.

Book an introductory call