Retries and idempotency
Make transient failure safe to retry.
Retry transient failures while using a stable idempotency key to prevent duplicate business work.
The default retry policy is three attempts with a one-second initial delay, a 30-second maximum delay, factor two, and no jitter.
/** Produces demonstration CSV through the ordinary order helper and emits validated progress around the durable export. */
import { defineTask } from "@relkit/app/tasks";
import { z } from "@relkit/app/schema";
import { exportOrderCsv } from "../helpers/fake-business.js";
const exportOrders = defineTask({
id: "orders.export-orders",
version: "1",
execution: "durable",
input: z.object({ orderIds: z.array(z.string()) }),
output: z.object({ csv: z.string(), exported: z.number().int().nonnegative() }),
progress: z.object({
completed: z.number().int().nonnegative(),
total: z.number().int().positive(),
}),
handler: async ({ orderIds }, context) => {
await context.progress.emit({ completed: 0, total: orderIds.length });
const csv = exportOrderCsv(orderIds);
await context.progress.emit({ completed: orderIds.length, total: orderIds.length });
return { csv, exported: orderIds.length };
},
});
export default exportOrders;
Set retry on defineTask, using maxAttempts, readable initialDelay and maxDelay, factor, and
jitter. A job can add an admission idempotency key and retention policy, but it cannot multiply the
task’s retry budget.
Retries are at-least-once. Use an idempotency key for every external side effect and store the result before acknowledging the step. A run ID is not an idempotency key: a retry keeps the run identity but may execute the task again.
The dedupe scope is part of compatibility. Changing it can create duplicate work even when the task source is unchanged, so migration diagnostics treat it as a deliberate change.
Classify permanent validation and authorization failures as terminal. Let transient network, rate-limit, and provider failures retry. Never log credentials or full untrusted input while diagnosing a retry loop.