Skip to main content
Some processes take days, weeks, or even months. Durable Workflows let you write these as simple code that can pause, wait, and resume—even if servers restart.

What Are Durable Workflows?

Normal serverless functions timeout after 15 minutes. Durable Workflows can:
  • Pause for minutes, days, or up to 1 year
  • Wait for external events (webhook, user action)
  • Resume exactly where they left off
  • Retry failed steps automatically

When to Use Durable Workflows

Most applications don’t need Durable Workflows. Simple event handlers and scheduled jobs cover 90% of use cases.
Use Durable Workflows only when you explicitly need:
  • Human approval waits - Processes that pause for days or weeks waiting for someone to approve
  • Long-running processes - Workflows that must survive beyond Lambda’s 15-minute timeout
  • Saga patterns - Multi-step transactions with compensation logic if steps fail
  • “Human in the loop” - Processes that require human intervention mid-workflow
Don’t use Durable Workflows for:
  • Simple event handlers (use Events instead)
  • Scheduled jobs (use Jobs instead)
  • Basic CRUD operations
  • Workflows that complete quickly

Use Cases

Approval Flows

Wait for manager approval before processing expense reports.

Payment Retries

Retry failed payments with exponential backoff over days.

Onboarding

Multi-step user onboarding over days or weeks.

Subscription Lifecycle

Handle trials, renewals, and cancellations over months.

Defining Workflows

Describe the workflow in natural language:
"When a subscription is created:
1. Send a welcome email immediately
2. Wait 7 days
3. Send a tips & tricks email
4. Wait until 3 days before trial ends
5. Send a trial ending reminder
6. Wait for trial to end
7. If not converted, send a winback email"

How It Works

# This is what Backdrift generates (simplified)
def subscription_workflow(subscription):
    # Step 1: Immediate
    send_welcome_email(subscription.user)

    # Step 2: Wait 7 days (workflow pauses, no server running)
    await sleep(days=7)

    # Step 3: Resume and send
    send_tips_email(subscription.user)

    # Step 4: Wait until specific date
    await sleep_until(subscription.trial_end - days(3))

    # Step 5: Check and send
    send_trial_reminder(subscription.user)

    # And so on...
The magic: This code pauses at each await and resumes later—even if the server restarts, deploys happen, or days pass.

Waiting for Events

Workflows can wait for external signals:
"Wait for the manager to approve the expense report.
If not approved within 7 days, escalate to the director."
# Generated code (simplified)
result = await wait_for_event(
    event="expense_approved",
    timeout=days(7)
)

if result.timed_out:
    escalate_to_director()
else:
    process_approved_expense()

Sending Signals

External systems can signal waiting workflows:
# From your application or webhook
curl -X POST https://your-api/workflows/{workflow_id}/signal \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"event": "expense_approved", "data": {"approved_by": "manager@example.com"}}'

Retry Logic

Workflows automatically retry failed steps:
"If payment fails, retry 3 times over 7 days
with increasing delays."
# Generated retry policy
@retry(
    max_attempts=3,
    delays=[hours(1), days(1), days(3)]
)
def charge_payment(subscription):
    return payment_gateway.charge(subscription)

Monitoring

In the Admin DashboardWorkflows tab:
  • View active workflow instances
  • See current step and status
  • View history of completed steps
  • Send signals to waiting workflows
  • Cancel stuck workflows

Region Requirements

Durable Workflows require deployment to us-east-2 (Ohio).
When creating a project that needs Durable Workflows, select us-east-2 as your region.

Examples

Approval Flow

"When an expense report is submitted:
1. Notify the manager
2. Wait for approval (timeout: 7 days)
3. If approved, process reimbursement
4. If rejected, notify employee
5. If timed out, escalate to director"

Payment Retry

"When a payment fails:
1. Wait 1 hour and retry
2. If still failing, wait 1 day and retry
3. If still failing, wait 3 days and retry
4. If still failing, suspend subscription and notify user"

Order Fulfillment

"When an order is placed:
1. Reserve inventory
2. Charge payment
3. Wait for warehouse confirmation (up to 24 hours)
4. Send shipping notification
5. Wait for delivery confirmation
6. Send review request 3 days after delivery"

Limitations

LimitValue
Maximum workflow duration1 year
Maximum step timeout1 year
Payload size256 KB
Concurrent workflows10,000

File Storage

Learn how to handle file uploads.