Simple Leave Management with AWS Lambda Durable Functions
Source: Dev.to
Intro
In AWS re:Invent 2025, Lambda introduced Durable Functions with a great set of features.
Key highlights
- A single execution can span up to one year.
- Built‑in checkpointing tracks completed steps, so when an execution is retried after a resume or interruption, already‑finished steps are skipped and the workflow continues from the next step.
When it comes to orchestrating multiple AWS services into a workflow, AWS Step Functions has long been the go‑to choice. With Durable Functions, you can now achieve similar orchestration inside the familiar Lambda environment, which is fantastic!
In this blog post I explain how Durable Functions’ callback feature can be used to implement a human‑in‑the‑loop workflow.
Scenario Overview
When an execution starts, Durable Functions launch a Lambda invocation. For multi‑step executions you can:
- Pause (or wait) at a specific step for a given time period or until a signal is received from an external process.
- Upon receiving the external signal, the execution either resumes (on success) or terminates (on failure).
This native capability is perfect for business processes that require human approval.
Example: Leave Request Workflow
| Step | Description |
|---|---|
| 1 | Employee sends a leave request → Durable Function starts an execution. |
| 2 | A leave record is created in a DynamoDB table with pending state. |
| 3 | Employee receives an email confirming receipt of the request. |
| 4 | Manager receives an email containing a callback ID to approve or reject the leave. |
| 5 | Durable Function holds execution until the manager’s decision is received. |
| 6 | Manager approves or rejects → execution resumes. |
| 7 | If the manager does not act within the timeout, the request expires. |
| 8 | Leave status is updated in DynamoDB. |
| 9 | Employee receives an email with the manager’s decision or an expiry notice. |
Architecture Details
1. Proxy Function
- Purpose: Accept and validate the incoming leave‑request payload.
- Implementation: Exposed via a Lambda Function URL.
- Why needed?
- Durable Functions’ synchronous invocations are limited to 15 minutes.
- To run longer, we invoke the durable function asynchronously (
InvocationType='Event'), i.e., fire‑and‑forget.
2. Durable Function Execution Flow
-
Create leave record in DynamoDB.
-
Send email to the employee confirming receipt.
-
Send email to the manager with a callback ID and a link to approve/reject.
-
Wait for callback (
wait_for_callbackstep). Execution pauses here. -
Callback handling – a separate Lambda (exposed via Function URL) receives
callback_idanddecision.{ "callback_id": "abc123-def456-ghi789", "decision": "approve" } -
The callback Lambda calls the new SDK methods:
# Pseudo‑code lambda_client.send_durable_execution_callback_success( CallbackId=callback_id, Output={"status": "APPROVED"} ) # or lambda_client.send_durable_execution_callback_failure( CallbackId=callback_id, ErrorMessage="Rejected by manager" )Note: These methods are not available in the default boto3 version shipped with Lambda. Package boto3 ≥ 1.42.1 with your function code.
-
Upon receiving the callback, the durable execution restarts.
-
If the manager does not respond within the timeout (e.g., 5 minutes),
wait_for_callbackraises aCallableRuntimeErrorwith the message “Callback timed out.” -
The leave record is updated accordingly (approved, rejected, or expired).
-
A final email is sent to the employee, and the execution completes.
Try This Yourself
A complete sample project (AWS CDK + Python) is available on GitHub:
🔗 Repository: https://github.com/pubudusj/simple-leave-management-with-durable-functions
Setup Steps
-
Clone the repository
git clone https://github.com/pubudusj/simple-leave-management-with-durable-functions.git cd simple-leave-management-with-durable-functions -
Configure environment variables
cp .env.example .env # Edit .env and fill in the required values. # Ensure SYSTEM_FROM_EMAIL is verified in Amazon SES. -
Deploy the stack
cdk deployAfter deployment you will see two Lambda Function URLs in the output:
- Create leave request endpoint
- Process leave request (manager) endpoint
1. Create a Leave Request
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"start_date":"2026-01-10",
"end_date":"2026-01-20",
"employee_email":"employee@email.com"
}' \
<CREATE_LEAVE_REQUEST_URL>
- Result
- The employee receives a confirmation email.
- The manager receives an email containing a callback ID and a link to approve or reject the request.
2. Manager Approves / Rejects
curl -X POST \
-H "Content-Type: application/json" \
-d '{
"callback_id":"<CALLBACK_ID>",
"decision":"approve"
}' \
<PROCESS_LEAVE_REQUEST_URL>
- Result
- The durable execution resumes, updates the DynamoDB record, and sends a final status email to the employee.
3. Timeout Scenario
If the manager does not act within the configured timeout (default 5 minutes for the demo), the leave request is automatically marked expired, and the employee receives an expiry notification.
Summary
- Durable Functions now support long‑running, checkpointed workflows (up to one year).
- The callback pattern enables human‑in‑the‑loop steps without external state machines.
- Using a proxy Lambda allows asynchronous invocation, bypassing the 15‑minute synchronous limit.
- The sample project demonstrates a complete end‑to‑end leave‑request flow with DynamoDB, SES, and Lambda callbacks.
Give it a try, and let me know how you extend this pattern to your own business processes!
OWS
Please try this and let me know your thoughts!