Skip to main content
Sometimes a workflow needs to wait — maybe you want to send a follow-up email a week after sign-up, or pause between API calls to respect rate limits. step.sleep() pauses a workflow for any duration (seconds to months) in a durable way: the resume time is stored in the database, and the worker slot is freed for other work. When the sleep finishes, a worker picks the workflow back up and continues from where it left off. This is different from setTimeout or a regular await sleep(). Those tie up a running process and are lost if the server restarts. With step.sleep(), you can have thousands of sleeping workflows without using any compute.

Basic Usage

How Sleep Works

When a workflow encounters step.sleep():
  1. A step attempt is created with the resume time
  2. The workflow is durably parked in running with workerId = null and availableAt set to the resume time
  3. The worker releases the workflow (frees the slot)
  4. When the sleep duration elapses, the workflow becomes available again
  5. A worker claims it and resumes from after the sleep

Duration Formats

The duration argument accepts a number followed by a unit: Examples:

Sleep Names

Like step.run(), each sleep needs a unique name within the workflow:

Common Patterns

Scheduled Follow-ups

Trial Expiration

Rate Limiting

When to Use Sleep

Use step.sleep() for:
  • Scheduled follow-ups (emails, notifications)
  • Trial periods and expiration workflows
  • Rate limiting between API calls
  • Retry backoff delays
  • Any pause longer than a few seconds
For very short delays (under a few seconds), consider using regular await with a Promise. The overhead of a durable sleep isn’t worth it for sub-second delays.

Sleep and Memoization

Once a sleep completes, it’s memoized like any other step. If the workflow replays after the sleep has finished, it returns immediately: