5 views
Step Functions is excellent — and expensive in cognitive load — when your workflow is still “invoke, wait on webhook, continue.” Start with durable in-app patterns (token store + callback Lambda + idempotent resume) and graduate to Step Functions only when branching, human gates, or multi-service compensation justify the state machine.
⚡ TL;DR: Prefer DynamoDB task tokens + SQS/EventBridge callbacks for linear wait-and-resume; keep Lambda handlers idempotent with Powertools; move to Step Functions when you need visual branching, parallel fan-out with join, or audit-grade history. Pair with Lambda Timeouts, Retries, and DLQs and LLM Coding Agents on AWS.
Lambda Durable Patterns: production guidance
| Signal | Stay in-app | Step Functions earns it |
|---|---|---|
| Steps | 2–4 linear | 5+ with branches |
| Wait | One external callback | Multiple waits + timers |
| Compensations | Single undo | Saga across 3+ services |
| Auditors | App logs enough | Need execution history UI |
| Team | One squad owns flow | Platform + many producers |
In-app durable wait with a task token
typescript
// lib/durable.ts — illustrative callback pattern
import { DynamoDBClient, PutItemCommand, GetItemCommand } from "@aws-sdk/client-dynamodb";
import { randomUUID } from "node:crypto";
const ddb = new DynamoDBClient({});
const TABLE = process.env.TASK_TABLE!;
export async function startWait(input: { orderId: string }) {
const taskToken = randomUUID();
await ddb.send(new PutItemCommand({
TableName: TABLE,
Item: {
pk: { S: `task#${taskToken}` },
orderId: { S: input.orderId },
status: { S: "WAITING" },
ttl: { N: String(Math.floor(Date.now() / 1000) + 86400) },
},
ConditionExpression: "attribute_not_exists(pk)",
}));
// call external system with taskToken as correlation id
return { taskToken };
}
export async function resume(taskToken: string, result: unknown) {
const got = await ddb.send(new GetItemCommand({
TableName: TABLE,
Key: { pk: { S: `task#${taskToken}` } },
}));
if (!got.Item || got.Item.status.S !== "WAITING") {
// ✅ Idempotent: duplicate callbacks are no-ops
return { ok: false, reason: "not_waiting" };
}
// continue business logic…
return { ok: true, result };
}
When to flip to Step Functions
typescript
Add SFN when Choice/Parallel/Map + execution replay beat bespoke Dynamo state. Until then, the in-app token table is enough — see also Lambda Warm Pools for keeping resume handlers warm.
// Only after complexity earns it — sketch
import * as sfn from "aws-cdk-lib/aws-stepfunctions";
import * as tasks from "aws-cdk-lib/aws-stepfunctions-tasks";
const waitForVendor = new tasks.LambdaInvoke(this, "WaitVendor", {
lambdaFunction: vendorFn,
integrationPattern: sfn.IntegrationPattern.WAIT_FOR_TASK_TOKEN,
payload: sfn.TaskInput.fromObject({
token: sfn.JsonPath.taskToken,
orderId: sfn.JsonPath.stringAt("$.orderId"),
}),
});
const definition = submit
.next(waitForVendor)
.next(new sfn.Choice(this, "VendorOk?")
.when(sfn.Condition.stringEquals("$.status", "OK"), fulfill)
.otherwise(compensate));
Guardrails either way
- Idempotency keys on every resume path
- Explicit TTLs so abandoned waits die
- Alarm on
WAITINGage p99 - Never block a Lambda for wall-clock waits — always callback or SFN
.wait
Closing checklist
✅ Dos – ✅ Start with token store + callback for linear flows – ✅ Idempotent resume; TTL abandoned tasks – ✅ Promote to SFN when branching/saga/audit demand it – ✅ Measure console usage before mandating SFN – ✅ Keep payloads small; park blobs in S3 ❌ Don’ts – ❌ Don’t sleep inside Lambda for long waits – ❌ Don’t invent a second orchestration framework – ❌ Don’t skip compensation design “until later” – ❌ Don’t put secrets in task-token payloadRelated reading
- Lambda Timeouts, Retries, and DLQs
- Lambda Warm Pools
- LLM Coding Agents on AWS
- Secure AI Sandboxes: Ephemeral ECS Tasks
Watch: 100 Days of AI on YouTube
Short videos from CheatCoders, one AI engineering topic per day.
Most viewed
- Python Decorators Explained: From Simple Wrappers to Production Patterns
- Claude Code vs Cursor vs GitHub Copilot: Choose by Workflow, and Set Up One Repo That Works With All Three
- AI Agent Frameworks in 2025: LangGraph vs CrewAI vs AutoGen vs Raw API
- Python String Methods: Every str Method With Real Production Examples
- Css Animation Performance: Performance-Optimized Motion for Modern UIs
Newly added
- AWS Systems Manager Parameter Store: Hierarchical Runtime Config for Coding Agents
- Amazon Cognito Identity Pools: Federate Coding-Agent Tool Callers Without Long-Lived Keys
- Amazon Athena for Coding Agents: Query Tool Audit Logs and Eval Traces on S3 Without a Warehouse
- AWS Batch for Coding Agents: Parallel Overnight PR Reviews and Long-Running Jobs Without Lambda Timeouts
- Amazon Bedrock Prompt Management: Version and A/B Test Coding-Agent System Prompts
Deep-dive PDF
Get the expanded guide for this post — extra diagrams-style checklists, failure modes, and a production walkthrough. Free when you subscribe to CheatCoders.
Already subscribed? or open the subscribe page.
Discover more from CheatCoders
Subscribe to get the latest posts sent to your email.
