Pause between steps with sleep()
Pizzas take time to cook. The workflow has no idea.
If we want it to wait for the kitchen before dispatching a driver, we need a way to pause. In a regular Node app, pausing means a setTimeout and praying the process stays alive. In a serverless function it means... well, you don't pause. Your function dies after 10 seconds.
Workflows have sleep(). You await it like any other promise. The workflow suspends. Vercel stops running anything related to that workflow, no compute, no memory, nothing. When the time elapses, the workflow picks up exactly where it left off.
Today we're going to pause for 30 seconds between the kitchen ack and the next step. Boring on paper. The reason to pay attention: while the workflow is sleeping, we're going to deploy a code change. The workflow should survive it untouched.
Outcome
Add await sleep("30s") to processOrder after the kitchen step. Deploy a change while a workflow is mid-sleep and watch the original run complete cleanly.
Fast Track
- Import
sleepfromworkflowinworkflows/process-order.ts. Addawait sleep("30s")afteracknowledgeKitchen. - Deploy. Place an order. While the dashboard shows the workflow suspended, change the confirmation email subject and push another deploy.
- Watch the original run finish on the new build without re-running the steps that already completed.
Hands-on exercise
1. Add sleep.
Update workflows/process-order.ts:
import { sleep } from "workflow";
import type { Order } from "@/lib/pizza";
import { sendOrderConfirmation } from "./steps/send-order-confirmation";
import { acknowledgeKitchen } from "./steps/acknowledge-kitchen";
export async function processOrder(order: Order): Promise<{ orderId: string }> {
"use workflow";
await sendOrderConfirmation(order);
await acknowledgeKitchen(order);
await sleep("30s");
return { orderId: order.id };
}sleep() accepts a duration string like "30s", "5m", "7 days", or a number of milliseconds. We're using 30 seconds because it's long enough to deploy through.
2. Deploy.
git add .
git commit -m "feat(workflow): pause after kitchen ack"
git pushWait for Vercel to finish the deploy.
Try It
This is the experiment. Pay attention to the timestamps.
Place an order on your production URL. The workflow runs sendOrderConfirmation, then acknowledgeKitchen, then hits sleep("30s") and suspends.
Open the Workflows dashboard in your Vercel project. The run shows as running with the timeline ending at the sleep:
processOrder running
├─ sendOrderConfirmation completed
└─ acknowledgeKitchen completed
─ sleeping 30s
While that's suspended, change something. Open workflows/steps/send-order-confirmation.ts and edit the email subject. Add an emoji. Add "v2". Anything. Then:
git commit -am "tweak: update confirmation subject"
git pushVercel builds and ships the new version.
Now go back to the original run. The sleep elapses. The workflow wakes up on the new deploy. It finishes:
processOrder completed 30.4s
├─ sendOrderConfirmation completed 389ms
└─ acknowledgeKitchen completed 208ms
(slept 30s, resumed after deploy)
The completed steps don't re-run. The new code is now serving new orders, but the old order finishes on the timeline it started with.
This is the unfair part of durable execution. It's also why the directives exist.
Commit
feat(workflow): pause after kitchen with sleep()
Done-When
workflows/process-order.tsimportssleepfromworkflow- The workflow awaits
sleep("30s")afteracknowledgeKitchen - You've shipped a code change while a workflow was mid-sleep
- The original run completed on the new deploy without re-running prior steps
Solution
import { sleep } from "workflow";
import type { Order } from "@/lib/pizza";
import { sendOrderConfirmation } from "./steps/send-order-confirmation";
import { acknowledgeKitchen } from "./steps/acknowledge-kitchen";
export async function processOrder(order: Order): Promise<{ orderId: string }> {
"use workflow";
await sendOrderConfirmation(order);
await acknowledgeKitchen(order);
await sleep("30s");
return { orderId: order.id };
}One line. Workflow sleeps. Deploys don't matter. This is the closest thing this course has to a magic trick.
Was this helpful?