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.

TipAdvanced2 min read

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)

Want this running in your stack?

I build production n8n and Cloudflare automation for teams — the same engineering behind HarperFlow. Fixed-price, escrow-protected, US-based.