Durable Jobs
Durable Jobs workflows
LiveUse steps and events to build multi-step jobs that can retry, pause, and resume.
Goal
Build a backend flow that survives retries and external waiting.
Current status
Live
This area is documented as current, user-reliable behavior.
Workflow
- 1Wrap side effects in named steps.
- 2Wait for external events with a correlation key.
- 3Let StackShift save progress and resume the job when the event arrives.
- 4Handle timeout behavior explicitly.
Onboarding workflow
This flow creates a user, sends email, waits for verification, then unlocks the account.
create user -> send email -> wait -> unlock
stackshift.job<{ userId: string; email: string }>('userOnboarding', async ({ payload, step }) => {
const { userId, email } = payload
const user = await step.run('create-user', () => {
return createUser({ id: userId, email })
})
await step.run('send-verification-email', () => {
return sendVerificationEmail(user.email)
})
const event = await step.waitForEvent<{ userId: string }>('email.verified', {
correlationKey: `user:${userId}`,
timeout: '24h',
onTimeout: 'fail',
})
await step.run('unlock-account', () => {
return unlockAccount(event.payload.userId)
})
return { onboarded: true }
})Resume behavior
- Before the wait, completed step results are saved.
- While waiting, the run is not consuming compute.
- When the matching event arrives, StackShift invokes the handler again with the event result.
- Completed steps return their saved outputs and the job continues after the wait.
Failure handling
- If a step throws, the run is retried according to its retry policy.
- Completed steps are not repeated on retry.
- If the wait times out, StackShift follows the configured timeout behavior.
Expected result
A multi-step job resumes from saved state instead of starting over.