
Description
Build a durable multi-step pipeline on Convex where each step runs in order and is retried independently on failure (transcribe→summarize→email, ETL, order fulfillment, any 'do A then B then C, retry each' job). Use @convex-dev/workflow — do NOT hand-roll a chain of scheduler calls or a custom jobs table. TRIGGER on multi-step / pipeline / 'retry each step' / long-running orchestration requests.
SKILL.md
Durable multi-step workflows → @convex-dev/workflow
When the task is "do step A, then B, then C, and retry each step independently if it fails" — a pipeline, ETL, or orchestration that must survive crashes — use the workflow component. Do NOT hand-roll it with a jobs table + chained ctx.scheduler.runAfter calls: that reinvents durability, loses per-step retry/backoff, and (measured) scores worse than a plain implementation. Copy this pattern.
Wire the component
// convex/convex.config.ts
import { defineApp } from "convex/server";
import workflow from "@convex-dev/workflow/convex.config";
const app = defineApp();
app.use(workflow);
export default app;
Define the workflow — one step.run* call per stage, retried independently
// convex/workflows.ts
import { WorkflowManager } from "@convex-dev/workflow";
import { components, internal } from "./_generated/api";
import { v } from "convex/values";
export const workflow = new WorkflowManager(components.workflow, {
// Per-step default: retry each failed step independently with backoff.
defaultRetryBehavior: { maxAttempts: 4, initialBackoffMs: 1000, base: 2 },
retryActionsByDefault: true,
});
export const transcribeAndSummarize = workflow.define({
args: { url: v.string(), userEmail: v.string() },
handler: async (step, args): Promise<void> => {
// Each step.runAction is durable + independently retried. If summarize fails
// 3× then succeeds, transcribe is NOT re-run — completed steps are memoized.
const transcript = await step.runAction(internal.youtube.transcribe, { url: args.url });
const summary = await step.runAction(internal.llm.summarize, { transcript });
await step.runAction(internal.email.sendSummary, { to: args.userEmail, summary });
},
});
- The handler's first arg is
step, notctx. Callstep.runAction/step.runMutation/step.runQuerywith a codegen'dinternal.*reference — neverctx.run*inside a workflow (that breaks durability/memoization). - Each
step.run*is a durable checkpoint. On crash or retry, completed steps are replayed from their stored result, not re-executed — so steps must targetinternalAction/internalMutations that do the real work. - Override retry per step when one stage is flakier:
step.runAction(ref, args, { retry: { maxAttempts: 6, initialBackoffMs: 500, base: 2 } }). Set{ retry: false }for a step that must not repeat (already-idempotent external charge). - The actual work (the YouTube fetch, the LLM call, the email send) lives in ordinary
internalActions — external APIs go in actions (seeconvex-external-apis), email via@convex-dev/resend(seecrons).
Start it (and optionally track status)
// from a public mutation/action the client calls:
const workflowId = await workflow.start(
ctx,
internal.workflows.transcribeAndSummarize,
{ url, userEmail },
);
// status later: await workflow.status(ctx, workflowId) → cleanup: workflow.cleanup(ctx, workflowId)
Don't
- ❌ A custom
jobs/pipelinetable +ctx.scheduler.runAfterchain to fake retries/ordering — that's what the component exists to replace. - ❌
ctx.runActioninside the workflow handler — usestep.runActionor you lose durability. - ❌ Long synchronous work in one action to dodge steps — you lose independent retry and the 10-min action ceiling still applies per step.
More skills from the convex-codex-plugin repository
View all 19 skillsadd
add capabilities to Convex applications
Jul 12BackendConvexNext.jsagent
build AI agents with Convex
Jul 12AgentsEngineeringRAGSearchauth
add authentication to Convex applications
Jul 18AuthAuthenticationConvexOAuthbilling
integrate Stripe billing in Convex apps
Jul 12ConvexPaymentsStripeWebhookscheck-updates
upgrade Convex component versions
Jul 12ConfigurationConvexMaintenanceconvex-authz
audit and harden Convex authorization
Jul 12AuthCode AnalysisConvexSecurity
More from Convex
View publisherconvex
guide Convex project setup and usage
agent-skills
Jul 12BackendConvexDatabaseconvex-create-component
build reusable Convex components
agent-skills
Jul 12API DevelopmentArchitectureBackendConvexconvex-migration-helper
plan Convex schema and data migrations
agent-skills
Jul 12BackendConvexData EngineeringMigrationconvex-performance-audit
audit Convex application performance
agent-skills
Jul 12ConvexDebuggingMonitoringPerformanceconvex-quickstart
initialize Convex in applications
agent-skills
Jul 12CLIConvexFrontendOnboardingconvex-setup-auth
set up authentication and access control
agent-skills
Jul 12Access ControlAuthBackendConvex