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 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.

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]
```text
Wait node configuration:

| Setting          | Value                             |
|------------------|-----------------------------------|
| Resume           | On Webhook Call                   |
| Limit Wait Time  | 24 hours                          |
| On Timeout       | Continue (to failure branch)      |

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

```javascript
// 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'
  }
}];
```text
Configure your payment processor (Stripe) to send its webhook to a relay workflow:

```text
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]
```text
```javascript
// 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"
}
```text
> **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](../error-handling-and-reliability/01-always-set-an-error-workflow-on-every-production-workflow.md) | [Use "Pin Data" to Freeze Node Output](../testing-and-debugging/01-use-pin-data-to-freeze-node-output.md)

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

191 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 a 20-minute call