Yesterday I attended the AWS Summit 2025 in Amsterdam where I joined a session about AWS Step Functions hosted by Adriaan de Jonge, a former Xebia colleague. The session provided practical insights on how to optimize workflow orchestration with Step Functions. I summarized my key takeaways that can help you improve your serverless architectures.
VS Code Extension Template
Writing Step Functions using Infrastructure as Code (IaC) can be annoying when you need to copy JSON from the AWS console UI. The AWS Toolkit for VS Code solves this problem by letting you develop and visualize your workflows directly in your IDE. You can create, edit and test Step Functions visually, without the back-and-forth copying. This makes the development process much more efficient and improves the Developer Experience.
From Lambda-lith to Step Function
A common anti-pattern in serverless architecture is creating a “Lambda-lith” – a monolithic Lambda function that handles too many responsibilities. These Lambda-liths can be broken down into Step Functions with multiple smaller, specialized Lambdas. This decomposition offers several advantages:
- Security: Each Lambda can have its own IAM permissions tailored to its specific needs
- Performance: Specialized functions can be optimized for their specific tasks
- Configuration: Different configuration (such as timeout settings) for different steps based on their requirements
HTTP REST Workflow
During the session it was also demonstrated how to create RESTful APIs directly with Step Functions and API Gateway, completely bypassing Lambda functions and their associated cold starts. By configuring a workflow that checks the incoming HTTP method (GET, POST, PUT, DELETE) and routes to the appropriate DynamoDB operation, you can build a fully functional REST API with minimal latency. Every line of code you don’t write, is code you don’t have to maintain.
For example, a GET request can trigger a GetItem operation, while POST executes a PutItem on your DynamoDB table. This direct integration pattern not only eliminates cold start delays but also simplifies your architecture and reduces costs by removing unnecessary Lambda functions from the request path. It’s especially useful for APIs that need consistently fast response times or handle sporadic traffic where cold starts would be particularly noticeable.
Every line of code you don’t write, is code you don’t have to maintain.
Emit and Wait Instead of Loop
For situations that traditionally require polling, Adriaan recommended the “Emit and Wait” pattern instead of implementing loops. This pattern uses EventBridge to emit events and then waits for callback tokens, creating more efficient and responsive workflows that don’t waste resources on continuous checking.
Use Intrinsic Functions and JSONata Where Possible
The session emphasized using Step Functions’ built-in capabilities for data transformation instead of creating Lambda functions for simple operations. This includes both native intrinsic functions (like States.StringToJson, States.Format, etc.) and the recently added JSONata support.
JSONata is particularly powerful as it provides a query and transformation language specifically designed for JSON data. With expressions like $.account.order.product.price.sum()
, you can perform complex data manipulations directly within your workflow definition. You can find more information here: JSONata.
Both intrinsic functions and JSONata reduce overhead, improve performance, and lower costs since they don’t require separate Lambda invocations. Adriaan showed several examples where replacing a transformation Lambda with a JSONata expression not only simplified the workflow but also significantly improved execution speed by eliminating the cold start penalty.
Test Step in Isolation
A practical tip shared was to test each step in isolation before combining them into a workflow. This approach makes debugging much simpler, as you can verify each component works correctly before dealing with the complexity of the entire workflow. For JSONata transformations specifically, testing them independently ensures your data manipulations work as expected.
What helps here, is the ability to inspect the input and output for each task in a workflow. This debugging capability makes it much easier to understand data flow and troubleshoot issues. You can see exactly what goes in and comes out of each step, which saves considerable time when dealing with complex workflows.
Conclusion
AWS Step Functions offer a powerful way to orchestrate serverless applications, and applying these best practices can help you create more maintainable, cost-effective, and robust workflows. If you want to learn more, check out the resources available at ServerlessLand, which contains additional examples and tutorials from re:Invent 2024.