Upstash Workflow JS
UpstashOfficialCreated by Upstash
- Skill
- Tool integration
- Cloud and DevOps
- MIT
- Medium risk
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The Upstash Workflow SDK enables developers to create reliable, multi-step workflows within serverless environments. By leveraging QStash, it allows functions to survive timeouts, retries, and restarts, effectively managing long-running processes that span minutes or days without keeping the underlying function execution active. It supports complex orchestration patterns, including step-by-step execution, external API calls, event waiting, human-in-the-loop approvals, and sophisticated flow control.
What it does
- Exposes serverless endpoints for durable workflow execution.
- Manages multi-step processes that persist across function restarts and timeouts.
- Provides tools for flow control, including concurrency, rate limiting, and parallelism.
- Supports advanced patterns like cross-workflow invocation and waiting for external events.
- Enables local development and testing via the QStash dev server.
- Facilitates human-in-the-loop workflows and real-time updates.
When to use it
- When building long-running tasks that exceed standard serverless function execution limits.
- When implementing saga or orchestration patterns in a distributed system.
- When you need reliable background jobs with built-in checkpointing and retries.
- When building AI agents or orchestrators that require stateful, multi-step execution.
- When integrating human approval steps into automated backend processes.
Advantages
- Eliminates the need to hold serverless functions open for long durations.
- Built-in support for retries, failure callbacks, and dead-letter queues.
- Seamless integration with popular serverless platforms like Vercel and Cloudflare Workers.
- Simplifies complex state management for asynchronous operations.
Usage examples
- “How do I define a basic two-step workflow using the Upstash SDK?”
- The agent provides a code snippet using the serve() function and context.run() to define sequential steps that persist across execution.
- “How can I trigger a workflow from my existing backend code?”
- The agent demonstrates initializing the Workflow Client with a QStash token and using the trigger() method to initiate the workflow URL.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/upstash/upstash-workflow-js/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip upstash-workflow-js.zip -d .agents/skills
Documentation by Upstash
Upstash Workflow SDK
Bundled docs and source
Before writing or debugging SDK code, check node_modules/@upstash/workflow/docs/ for bundled docs and node_modules/@upstash/workflow/src/ for readable TypeScript source. Read and search the relevant files when present; otherwise use the references in this skill.
Quick Start
The Upstash Workflow SDK lets you expose serverless workflow endpoints and run them reliably using QStash under the hood.
Install:
npm install @upstash/workflowDefine a simple workflow endpoint:
import { serve } from "@upstash/workflow";
export const { POST } = serve(async (context) => {
await context.run("step-1", () => console.log("step 1"));
await context.run("step-2", () => console.log("step 2"));
});Trigger it from your backend:
import { Client } from "@upstash/workflow";
const client = new Client({ token: process.env.QSTASH_TOKEN! });
await client.trigger({ url: "https://your-app.com/api/workflow" });Other Skill Files
These files contain the full documentation. Use them for details, patterns, and advanced behavior.
basics:
basics/serve – How to expose workflow endpoints.
basics/context – Full API for workflow
context(steps, waits, webhooks, events, invoke, etc.).basics/client – Using the Workflow client to trigger, cancel, inspect, and notify runs.
features:
features/invoke – Cross‑workflow invocation.
features/reliability – Retries, failure callbacks, and DLQ.
features/flow-control – Rate limits, concurrency, and parallelism.
features/wait-for-event – Notify and wait-for-event patterns.
features/webhooks – Webhook creation and consumption.
how to:
how-to/local-dev – Local QStash dev server (auto via
QSTASH_DEV=true) and tunneling.how-to/realtime – Realtime and human‑in‑the‑loop workflows.
how-to/migrations – Migrating workflows safely.
how-to/middleware – Adding middleware to workflows.
other files:
rest-api – Low-level REST endpoints for interacting with QStash/Workflow.
troubleshooting – Common debugging and environment issues.
agents – Using Workflow with agents, orchestrators, and automation patterns.
Files
- ATTRIBUTION.mdAdded by AutoGineer892 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md3.4 KiB
- agents.md6.7 KiB
- basics/client.md4.1 KiB
- basics/context.md5.1 KiB
- basics/serve.md2.4 KiB
- features/flow-control.md3.9 KiB
- features/invoke.md2.6 KiB
- features/retries-failures-reliability.md6.3 KiB
- features/wait-for-event.md2.8 KiB
- features/webhooks.md2.5 KiB
- how-to/local-dev.md5.0 KiB
- how-to/middleware.md4.7 KiB
- how-to/migrations.md4.8 KiB
- how-to/realtime.md4.8 KiB
- rest-api.md6.6 KiB
- troubleshooting.md4.8 KiB
features/retries-failures-reliability.md
Workflow Reliability Features
This documentation provides a consolidated reference for reliability mechanisms in Upstash Workflow, focusing on retries, failure handling, and the Dead Letter Queue (DLQ). It is optimized for AI‑driven execution but remains clear for developers.
Core Reliability Concepts
Upstash Workflow ensures that workflow runs are durable, recoverable, and traceable. Reliability is achieved through:
Automatic retries for transient failures
Failure handling via
failureFunctionorfailureUrlDLQ for storing permanently failed runs
Manual recovery actions: restart, resume, rerun failure function
Mechanisms to prevent retries when failure is intentional
These mechanisms work together to guarantee that no failed execution is lost and that failures can be observed and handled.
Automatic Retries
Workflow steps automatically retry when they fail, using configurable retry count and delay.
Retry Parameters
retries: How many times the step will retryretryDelay: A math expression (string) returning delay in milliseconds; can useretriedvariable
Common Pitfalls
The delay expression must be a string; raw numbers disable dynamic calculation.
A workflow only moves to DLQ after all retries fail.
Example: Configure Retry Count + Delay
import { Client, WorkflowNonRetryableError, serve } from "@upstash/workflow";
// Trigger with custom retry settings
const client = new Client({ token: process.env.WORKFLOW_TOKEN! });
await client.trigger({
url: "https://example.com/workflow",
retries: 5,
retryDelay: "(1 + retried) * 2000", // 2s, 4s, 6s...
});
// Workflow with steps that may intentionally skip retries
export const { POST } = serve(async (context) => {
const shouldFail = await context.run("check", () => true);
if (shouldFail) {
// Skips retry cycle and sends directly to failure handling
throw new WorkflowNonRetryableError("Bad state");
}
await context.run("process", () => doWork());
});Preventing Retries
When to Stop Retries
Use these when failure is expected or should halt execution immediately:
WorkflowNonRetryableError→ Fail fast, trigger failure function, enter DLQcontext.cancel()→ Stop workflow intentionally, no DLQ, no failure functionConditional returns → Graceful early exit without error
Pitfalls
context.cancel()marks the run as canceled, not failed — no failure handling executes.Throwing any error other than
WorkflowNonRetryableErrorwill still trigger retries.
Failure Handling
You can handle workflow failures using either:
failureFunction(runs in your workflow environment)failureUrl(external callback endpoint)
Only one can be configured — they are mutually exclusive.
Failure Function Behavior
Runs after all retries fail
Receives failure metadata and workflow context
Cannot create new workflow steps;
contextis read‑onlyIs retried if it fails
Can be manually retried from the DLQ
Failure Function Parameters
context.workflowRunIdcontext.urlcontext.requestPayloadcontext.headerscontext.envfailStatusfailResponsefailHeaders
Example: Workflow + Failure Function + Prevent‑Retry Logic
export const { POST } = serve(
async (context) => {
const ok = await context.run("verify", () => verifySomething());
if (!ok) {
throw new WorkflowNonRetryableError("Verification failed");
}
const shouldAbort = await context.run("check", () => false);
if (shouldAbort) {
await context.cancel();
return;
}
await context.run("execute", () => doWork());
},
{
failureFunction: async ({ context, failStatus, failResponse }) => {
// Logging / cleanup / alerts
await logFailure(context.workflowRunId, failStatus, failResponse);
},
}
);Dead Letter Queue (DLQ)
A workflow enters the DLQ when:
A step fails after all retries
A
WorkflowNonRetryableErroris thrownfailureFunctionalso fails (visible as failed in DLQ)
Retention
Free: 3 days
Pay‑as‑you‑go: 1 week
Fixed: Up to 3 months
After retention expires, items cannot be recovered.
DLQ Recovery Actions
You may perform these actions from the dashboard or programmatically.
1. Resume
Continue from the failed step while keeping previous step results.
2. Restart
Start the entire workflow from scratch, discarding previous results.
3. Rerun Failure Function
Retry the failure handler only if it previously failed.
Example: All DLQ Actions
import { Client } from "@upstash/workflow";
const client = new Client({ token: process.env.WORKFLOW_TOKEN! });
await client.dlq.resume({ dlqId: "dlq-1", retries: 3 }); // Continue run
await client.dlq.restart({ dlqId: "dlq-2", retries: 3 }); // Restart
await client.dlq.retryFailureFunction({ dlqId: "dlq-3" }); // Retry failure handlerPitfalls
retryFailureFunctionis only allowed when the failure function failed.resumecannot be used if workflow code changed before the failure point.restartre-executes everything, including expensive steps.
Failure URL (Advanced Option)
Use when failure must be handled by a separate service.
Notes
Use either
failureFunctionorfailureUrl.Recommended only when your primary app might be offline.
Failure URL receives a structured JSON payload about the failed request.
Example
export const { POST } = serve(
async (context) => {
await context.run("work", () => doWork());
},
{
failureUrl: "https://example.com/failure-handler",
}
);Debugging Failed Runs
DLQ entries store:
Request + response headers
Payloads
Failure metadata
Failure function state
Use the dashboard filters (workflow run ID, URL, failure function state) to identify and debug root causes.
Summary
This skill unifies all Workflow reliability controls:
Retries (automatic, configurable)
Failure handling (
failureFunction,failureUrl)DLQ retention + recovery
Fast‑fail mechanisms (
WorkflowNonRetryableError,cancel, conditional exits)Manual recovery operations (resume, restart, retry failure function)
Together these features ensure workflows are resilient, debuggable, and recoverable under all failure scenarios.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Node.js
Security
What our scanner noticed· Medium risk
- Possible data-exfiltration endpoints
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Upstash
- Publisher
- Upstash (Official)
- Source
- upstash/skills · skills/upstash-workflow-js · commit 9f9e3e5
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
AutoGineer is not affiliated with or endorsed by Upstash or Upstash.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download upstash-workflow-js.zip