Imagine a microservice architecture where 15 Lambda functions process an order sequentially—validation, inventory check, shipping calculation, payment capture, notification. If you chain them with direct calls, you lose execution history, errors are hard to locate, and a single failure stalls the entire process. For a fintech platform handling 1000 orders/sec, we solved this by introducing orchestration via AWS Step Functions. The result—processing time cut by 30% and full traceability of every execution. We've seen similar outcomes in 30+ projects where we applied orchestration, from e-commerce to FinTech. Average infrastructure savings reach 40%, and the ROI period is 3-6 months.
Directly calling one Lambda from another is an anti-pattern: you lose execution history, error handling becomes complex, and there's no progress visibility. Orchestration with Step Functions or Durable Functions solves N+1 database queries, state loss, and monitoring gaps. Our engineers have delivered 30+ orchestration projects—from e-commerce to FinTech. Get your project evaluated in one day—just contact us, and we'll prepare a commercial proposal.
When is orchestration needed instead of direct calls?
A business process consists of multiple stateful steps, requires conditional branching (if step_A succeeded, then step_B, else step_C), parallel execution of several functions with result aggregation, long-running processes (>15 minutes for Lambda), or human approval at some step (wait for callback). In all these cases, direct calls lead to spaghetti code and debugging nightmares.
Function Composition as a solution for serverless orchestration
An orchestrator handles routing, retries, and metrics collection. Instead of dozens of calls in code, you describe the workflow declaratively. This simplifies debugging—each execution is traceable step by step in the console. On failure, the system automatically retries the step or transitions to a compensating action. In our experience, orchestration reduces infrastructure costs by up to 40% through optimized calls. Compare: direct Lambda chaining requires 15 calls per order with timeout risks; an orchestrator performs the same steps with guaranteed error handling 5 times faster.
AWS Step Functions: practical example
Example State Machine (ASL)
{
"Comment": "Order processing",
"StartAt": "ValidateOrder",
"States": {
"ValidateOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:us-east-1:123:function:validate-order",
"Next": "CheckInventory",
"Retry": [{"ErrorEquals": ["Lambda.ServiceException"], "MaxAttempts": 3}],
"Catch": [{
"ErrorEquals": ["ValidationError"],
"Next": "NotifyInvalidOrder"
}]
},
"CheckInventory": {
"Type": "Parallel",
"Branches": [
{"StartAt": "ReserveItems", "States": {"ReserveItems": {"Type": "Task", "Resource": "arn:...:reserve-items", "End": true}}},
{"StartAt": "CalculateShipping", "States": {"CalculateShipping": {"Type": "Task", "Resource": "arn:...:calc-shipping", "End": true}}}
],
"Next": "ProcessPayment"
},
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke.waitForTaskToken",
"Parameters": {
"FunctionName": "arn:...:process-payment",
"Payload": {
"taskToken.$": "$$.Task.Token",
"orderId.$": "$.orderId"
}
},
"Next": "FulfillOrder",
"TimeoutSeconds": 300
},
"FulfillOrder": {"Type": "Task", "Resource": "arn:...:fulfill-order", "End": true},
"NotifyInvalidOrder": {"Type": "Task", "Resource": "arn:...:notify-invalid", "End": true}
}
}
.waitForTaskToken allows Step Functions to wait for a callback from an external system (e.g., payment gateway) without polling. The payment gateway calls SendTaskSuccess with the token when the transaction completes.
Terraform for Step Functions
resource "aws_sfn_state_machine" "order_processing" {
name = "order-processing"
role_arn = aws_iam_role.sfn_role.arn
definition = templatefile("${path.module}/state_machine.json", {
validate_lambda_arn = aws_lambda_function.validate_order.arn
reserve_lambda_arn = aws_lambda_function.reserve_items.arn
payment_lambda_arn = aws_lambda_function.process_payment.arn
fulfill_lambda_arn = aws_lambda_function.fulfill_order.arn
})
logging_configuration {
log_destination = "${aws_cloudwatch_log_group.sfn.arn}:*"
include_execution_data = true
level = "ERROR"
}
tracing_configuration {
enabled = true # X-Ray tracing
}
}
Comparison: AWS Step Functions vs Azure Durable Functions
| Feature | AWS Step Functions | Azure Durable Functions |
|---|---|---|
| Maximum duration | 1 year | Unlimited (checks every 10 sec) |
| Execution visualization | Built-in console | Application Insights |
| Pricing | $0.025/1k transitions (Standard) | Pay per execution time + storage |
| Language integration | JSON/ASL | C#, Python, JavaScript, F# |
| Conditional compilation | No | Yes (if/else in code) |
Your choice depends on your ecosystem: if you're on AWS—Step Functions; if on Azure—Durable Functions. In multi-cloud scenarios, you could use a unified orchestrator like Temporal or Camunda, but that goes beyond serverless.
Azure Durable Functions: an alternative
.NET / Node.js / Python orchestrator based on Azure Functions:
import azure.durable_functions as df
def orchestrator_function(context: df.DurableOrchestrationContext):
parallel_tasks = [
context.call_activity("ReserveItems", context.get_input()),
context.call_activity("CalculateShipping", context.get_input())
]
results = yield context.task_all(parallel_tasks)
approval = yield context.wait_for_external_event("ApprovalReceived")
if approval:
return (yield context.call_activity("FulfillOrder", context.get_input()))
else:
return (yield context.call_activity("CancelOrder", context.get_input()))
main = df.Orchestrator.create(orchestrator_function)
Durable Functions use Azure Storage to persist state. The orchestrator can wait for an external event indefinitely.
How to handle errors in orchestration?
Distributed processes lack built-in transactions. The Saga pattern uses compensating actions on failure:
"ProcessPayment": {
"Type": "Task",
"Resource": "...",
"Catch": [{
"ErrorEquals": ["PaymentFailed"],
"Next": "CompensateReservation"
}]
},
"CompensateReservation": {
"Type": "Task",
"Resource": "arn:...:release-reservation",
"Next": "NotifyPaymentFailed"
}
Each step that needs rollback on error has a compensating function. Visibility is provided via CloudWatch Metrics and X-Ray for Step Functions, and Application Insights for Durable Functions.
Express vs Standard Workflows
| Standard | Express | |
|---|---|---|
| Duration | Up to 1 year | Up to 5 minutes |
| Execution history | Full | CloudWatch Logs |
| Price | $0.025/1k transitions | $0.00001/state transition |
| Best for | Business processes | High-volume, short workflows |
Standard Workflows are 2500 times more expensive per transition than Express Workflows, but support long-running processes with full audit. For projects with more than 10,000 invocations per day, Express is more cost-effective.
What's included
- Architectural documentation describing the workflow and all functions.
- Orchestrator and Lambda (or Azure Functions) code in your repository.
- Infrastructure code (Terraform / Bicep) for deployment.
- Configured monitoring and alerts (CloudWatch / Application Insights).
- Repository access and deployment instructions.
- Training for your team on working with the orchestrator.
Process and timelines
- State machine design + ASL description — 2-3 days.
- Lambda functions for each step — 3-7 days.
- Step Functions state machine + IAM — 2-3 days.
- Error handling + compensations — 2-3 days.
- Monitoring + alerts + testing — 2-3 days.
Contact us for a consultation—order a turnkey Function Composition implementation. Write to us and get a commercial proposal with a detailed plan within one day. Our experience is backed by 30+ successful deployments in fintech, e-commerce, and logistics. Get a free consultation—just reach out.







