Workflow context
A workflow’s context is a JavaScript object provided by the serve function and is used to define your workflow endpoint. This context object offers utility methods for creating workflow steps, managing delays, and performing timeout-resistant HTTP calls.
import { serve } from "@upstash/qstash/nextjs"
export const POST = serve(
// 👇 the workflow context
async (context) => {
// ...
}
)
This context object provides utility methods to create workflow steps, wait for certain periods of time or perform timeout-resistant HTTP calls.
Further, the context object provides all request headers, the incoming request payload and current workflow ID.
Context Object Properties
-
qstashClient
: QStash client used by the serve method -
workflowRunId
: Current workflow run ID -
url
: Publically accessible workflow endpoint URL -
failureUrl
: URL for workflow failure notifications. -
requestPayload
: Incoming request payload -
rawInitialPayload
: String version of the initial payload -
headers
: Request headers -
env
: Environment variables
Core Workflow Methods
context.run
Defines and executes a workflow step.
context.sleep
Pauses workflow execution for a specified duration.
Always await
a sleep
action to properly pause execution.
import { serve } from "@upstash/qstash/nextjs"
import { signIn, sendEmail } from "@/utils/onboarding-utils"
export const POST = serve<User>(
async (context) => {
const userData = context.requestPayload;
const user = await context.run("sign-in", async () => {
const signedInUser = await signIn(userData);
return signedInUser;
});
// 👇 Wait for one day (in seconds)
await context.sleep("wait-until-welcome-email", 60 * 60 * 24);
await context.run("send-welcome-email", async () => {
return sendEmail(user.name, user.email);
});
},
);
context.sleepUntil
Pauses workflow execution until a specific timestamp.
Always await a sleepUntil
action to properly pause execution.
import { serve } from "@upstash/qstash/nextjs"
import { signIn, sendEmail } from "@/utils/onboarding-utils"
export const POST = serve<User>(async (context) => {
const userData = context.requestPayload
const user = await context.run("sign-in", async () => {
return signIn(userData)
})
// 👇 Calculate the date for one week from now
const oneWeekFromNow = new Date()
oneWeekFromNow.setDate(oneWeekFromNow.getDate() + 7)
// 👇 Wait until the calculated date
await context.sleepUntil("wait-for-one-week", oneWeekFromNow)
await context.run("send-welcome-email", async () => {
return sendEmail(user.name, user.email)
})
})
context.call
Performs an HTTP call as a workflow step, allowing for longer response times.
Can take up to 15 minutes or 2 hours, depending on your QStash plans max HTTP connection timeout.
import { serve } from "@upstash/qstash/nextjs"
export const POST = serve<{ topic: string }>(async (context) => {
const request = context.requestPayload
const longEssayResponse = await context.call(
"generate-long-essay", // Step name
"https://api.openai.com/v1/chat/completions", // Endpoint URL
"POST", // HTTP method
{ // Request body
model: "gpt-4o",
messages: [
{
role: "system",
content:
"You are a helpful assistant writing really long essays that would cause a normal serverless function to timeout.",
},
{ role: "user", content: request.topic },
],
},
{
authorization: `Bearer ${process.env.OPENAI_API_KEY}`,
}
)
})
context.call attempts to parse the response body as JSON. If this is not possible, the body is returned as it is.
In TypeScript, you can declare the expected result type as follows:
type ResultType = {
field1: string,
field2: number
};
const result = await context.call<ResultType>( ... );
Error handling and retries
- context.run and context.call automatically retry on failures.
- Default: 3 retries with exponential backoff.
- Future releases will allow configuration of retry behavior.
Limitations and Plan-Specific-Features
- Sleep durations and HTTP timeouts vary based on your QStash plan.
- See your plan’s “Max Delay” and “Max HTTP Connection Timeout” for specific limits.
Was this page helpful?