The serverless-step-functions plugin is a nifty Serverless Framework extension that allows you to define step functions directly within the
serverless.yml. However, the definitions for step functions tend to get messy fast and it's hard to visualize how a workflow actually looks and flows just from looking at the YAML. The Step Functions Workflow Studio helps you with exactly this by allowing you to interactively sketch out your state machine. In this post, I'll give you a brief walkthrough of how we can use the Workflow Studio together with the Step Functions plugin.
Creating a State Machine
To get started, navigate to the Step Functions page in the AWS Console and press "Create state machine".
Next, choose "Design your workflow visually", then go to Next.
From here, you can drag and drop Actions and Flows, tinker with the properties, flow, and error handling until you're happy with the design.
Set any resources that you want to eventually define in your serverless app to refer to a made-up value in the meantime - setting the Lambda Function name to just a string name for example. Once you're done, click "Next".
At last, we have our generated JSON schema for the state machine! But wait. Our Serverless template is in YAML, not JSON - how do we translate this into something that we can actually use?
As it turns out, YAML is just a superset of JSON, meaning all JSON is valid YAML. The JSON that was generated is in the form of Amazon State Languages spec, and that same spec is used by our serverless-step-functions plugin. This means that we can translate our JSON snippet to YAML using an online tool, such as Code Beatify, or a CLI tool such as yq.
Now that we've got the state machine defined in YAML, all we need to do is actually use it in the
Putting it together
If you don't already have a serverless project set up, check out my guide to a simple esbuild setup or just run
serverlessin your terminal to choose from one of the boilerplates.
The serverless-step-functions plugin extends the
serverless.yml format with a root
stepFunctions property. We'll use that to define our step function by pasting in our YAML snippet as the definition of the state machine.
// serverless.yml [...] stepFunctions: stateMachines: myStateMachine: name: MyStateMachine [your generated state machine goes here]
Keep in mind that any references to Lambda functions or other services that we used placeholder references for needs to be updated to refer to the actual resources we want them to point to. As an example, a Lambda definition might look like this when generated:
FirstFunction: Type: Task Resource: arn:aws:states:::lambda:invoke OutputPath: $.Payload Parameters: Payload.$: $ FunctionName: firstFunction
and we can change that to instead refer to a
firstFunction Lambda defined in our stack by changing it to:
FirstFunction: Type: Task Resource: !GetAtt firstFunction.Arn OutputPath: "$.Payload" Parameters: Payload.$: "$"
For the workflow from the examples above, this is what the full
serverless.yml might look like.
service: step-functions-demo plugins: - serverless-step-functions provider: name: aws runtime: nodejs14.x stepFunctions: stateMachines: myStateMachine: name: MyStateMachine definition: Comment: This is your state machine StartAt: First function States: First function: Type: Task Resource: !GetAtt firstFunction.Arn OutputPath: "$.Payload" Parameters: Payload.$: "$" Retry: - ErrorEquals: - Lambda.ServiceException - Lambda.AWSLambdaException - Lambda.SdkClientException IntervalSeconds: 2 MaxAttempts: 6 BackoffRate: 2 Next: Wait Wait: Type: Wait Seconds: 5 Next: Second function Second function: Type: Task Resource: !GetAtt secondFunction.Arn OutputPath: "$.Payload" Parameters: Payload.$: "$" Retry: - ErrorEquals: - Lambda.ServiceException - Lambda.AWSLambdaException - Lambda.SdkClientException IntervalSeconds: 2 MaxAttempts: 6 BackoffRate: 2 End: true functions: firstFunction: handler: src/functions/first.handler secondFunction: handler: src/functions/second.handler
If you enjoyed this post and want to see more, follow me on Twitter at @TastefulElk where I frequently write about serverless tech, AWS, and developer productivity! 👋