Pattern: Implement a timeout for a step operation within a single Lambda invocation.
Implementation approach:
Use Promise.race() to race the step operation against a timeout promise
The timeout promise rejects after the specified duration
Catch the timeout error and implement fallback logic
Execute fallback operation in a separate step
Important limitation:
In TypeScript, native setTimeout (and patterns like Promise.race using it) will fail during execution replays. To create a reliable timeout that persists across execution (expands over multi invocations), always use the timeout parameter provided by waitForCallback
Pattern: Temporarily stop making requests to a failing external service to prevent cascading failures.
Implementation approach:
Track failure count and last failure time (note: these reset on replay due to closure mutations)
Check if circuit is “open” (too many recent failures)
If open, throw a circuit breaker error and wait before retrying
If closed, attempt the operation
On success, reset failure count
On failure, increment failure count and record timestamp
Configure retry strategy to wait longer when circuit is open
Important caveat: The example implementations use closure variables (failureCount, lastFailureTime) which reset on replay. For production use, store circuit breaker state in:
A step return value that persists across replays
An external store like DynamoDB
A durable variable pattern
Key considerations:
Circuit breaker prevents cascading failures to downstream services
The “open” duration should be long enough for the service to recover