Caylent Catalysts™
Serverless App
Design new cloud native applications by providing secure, reliable and scalable development foundation and pathway to a minimum viable product (MVP).
Learn how Amazon States Language (ASL) enables seamless orchestration of Lambda functions, making it easier to chain operations and manage workflows efficiently.
One of my favorite games growing up was the 24 Game. In this game, a group of friends took a group of numbers from a card and used the order of operations and basic arithmetic to add, subtract, multiply, and divide the numbers on the card to get to a value of 24. The discovery process to arrive at a solution is complex, and beyond the scope of this demonstration, but we can use this basic paradigm to show how to chain Lambda operations together using Amazon States Language (ASL) to arrive at an answer.
Combined with the Lambda Calculator from the AWS C# SDK, the 24 Game is a good way to demonstrate Amazon Step Functions' ability to incrementally use Lamba functions to arrive at an answer. The scope of this blog is not designed to be the most efficient solution, as basic data manipulation is now possible using JSONata (since Step Functions is billed by State Transition). This blog is intended to give an academic exploration of how ASL works. You can extend the concepts in this blog post to include any of AWS Step Function’s task integrations or use your own code elsewhere in the AWS ecosystem.
The Lambda Calculator takes an input payload in JSON and performs basic math on these inputs, directed by the "action" property in the JSON. We can reuse this same Lambda in a few places in our ASL definition to accomplish the math we need. Here's an initial ASL definition to get us started by doing some basic arithmetic.
The first state assigns the four numbers from our card [2, 4, 6, 8] to variables [“a”,”b”,”c”, and “d”] to start, the second prepares input parameters for the third step, using “a” and “c” to produce a product (we’ll use “b” and “d” later in the solution), and the third step is a lambda function to do the arithmetic.
Here's the visual representation (available in the AWS State Machine Editor or VSCode Toolkit) of the flow above:
The output of the state machine looks like this:
So, now that we have a state machine that does some math in a sequence, let's build one that illustrates how to get to 24. Adding a few more states (and changing the names of some others), our new state machine looks like this:
Note that I used the States.JsonToString()
Intrinsic Function to convert the numeric outputs into string inputs for the Lambda. If an integer is passed, the Lambda will throw an exception when converting the input JSON to a dictionary of strings.
If you navigate to Execution View and scroll down, you will see a convenient Historical Graph explorer that allows you to click through the states and see what the state machine looks like at each stage.
Notice that our math3out
property of the Payload is the answer we're looking for! Mission Accomplished!
Let's imagine that we rearrange the order of operations of this Step Function Flow just a little bit and do this instead:
This new state machine calculates 2 x 6
and 8 + 4
in parallel and sums them at the end. However, the tricky thing here (in addition to the new Parallel
state type) is that the branch functions of a Parallel state create an array with outputs for each branch -- and so to merge those back together we have to have a Pass
state that uses the States.JsonMerge
intrinsic function.
This results in the following result:
There are a number of parallel and iterative options, including the Map
state type, which acts as a Parallel For
container and allows breaking out an array with subroutines. Amazon States Language (and by extension step functions) has numerous options to allow modeling any given process.
Now that we’ve gone through the logic of creating the state machine, let’s refine it a little bit by removing the Prep
states in favor of a more consolidated set of logic. Basically, we’re going to combine the parameters in the prep step with the input of the math steps to make fewer state transitions (and reduce costs):
For this final example, we’re leaving all of the pipeline stuff behind and only passing what each state needs with the Parameters
attribute. This will not include all of the previous json for the state machine, and it will only pass what the output is. In this way, we can trim the json down to just what is necessary at each step.
The result of this is a greatly simplified state machine with only a few Pass
states involved, but the density is higher and slightly more difficult to follow. Sometimes it will be beneficial to carry the entire payload forward (in the event of further downstream processing) and sometimes it won’t. Amazon States Language provides a way to accommodate both.
Using Amazon States Language is a great way to orchestrate workflows between Lambdas and other Step-Functions-Integrated AWS Services. Step Functions provides the functionality to create resilient workflows out of the box in a convenient UI, using Step Functions Workflow Studio. It also has great observability tools built in, to help re-trace the previous executions and debug them.
At Caylent, we take advantage of AWS Step Functions to decompose complex processes into manageable pieces, and the built-in integrations to other AWS Services allow us to quickly implement and orchestrate cloud-native designs. This helps maintain the logical separation between flow control logic and business logic, simplifying the domain-specific code and helping product teams deliver the most targeted value.
I hope you enjoyed exploring AWS Step Functions with my simple 24-game scenario. Even though solving the puzzle and working through the order of operations seems intuitive, it is a great way to introduce state machines and AWS Step Functions.
Jeremy Yelle is a Software Architect at Caylent based in Western New York. He is an advocate for Domain Driven Design and Business Process Modeling, working with product and architecture teams to align technical goals with product objectives. Jeremy has over 20 years of experience as a database engineer, microservice developer, software architect, and technology evangelist. Now, Jeremy is excited to share his experiences with the capabilities of AWS. Outside of work, he enjoys outdoor sports like skiing and mountain biking.
View Jeremy's articlesLeveraging our accelerators and technical experience
Browse GenAI OfferingsExplore our technical analysis of AWS re:Invent 2024 price reductions and performance improvements across DynamoDB, Aurora, Bedrock, FSx, Trainium2, SageMaker AI, and Nova models, along with architecture details and implementation impact.
Get up to speed on all the storage focused 300 and 400 level sessions from re:Invent 2023!
Get up to speed on all the serverless focused 300 and 400 level sessions from re:Invent 2023!