Basics of Passing Variables Between State Machines in AWS Step Functions

AWS recently added Step Functions to their lineup, which I have found to be one of the most exciting new services they’ve released in a while. It has some amazing potential for allowing you to break up Lambda functions into a lot of component parts and chain them together (including wait conditions and other bells & whistles), but if you don’t already have a strong programming background it won’t be clear to you how to actually make this work, since their documentation isn’t as thorough as it could be, and they assume a certain basic level of background programming knowledge. I come from an Infrastructure/Operations background, so if you’re not a programming expert, but you still want to utilize these tools to automate your life and just get things done, I can sympathize. To that end, here’s a quick run-down of the basics you’ll need to know to dip your toe into this ocean of possibilities. 

I should preface this by saying that all of my coding is done in Python 3.7, so you’ll have to translate to whatever language you’re using if not that.

Let’s start with a very basic Lambda function we’ll call “LAMBDA1”:

LAMBDA1:

def lambda_handler(event, context):
    #First, we'll create two variables called "test" and "two":
     test = "HEllo!"
     two = "bye"
     # Now we'll combine both variables into an array as a single variable:
     comb = [test, two]
     # Finally, we return the contents of the "comb" variable to whatever ran this function:
     return comb

Ok, so far all we’ve done is create two variables, assigned them values, and, using “return“, we’ve passed those values along to the whatever is waiting to hear about them.

In our case the thing that invoked the function is an AWS Step Functions state machine, and so when you return an array of values you’re returning it to AWS Step Functions. So, if we have Step Functions trigger a second Lambda function (we’ll call it “LAMBDA2”) after LAMBDA1 is complete, it will take the output of LAMBDA1 to be the input to LAMBDA2, which LAMBDA2 automatically refers to as “event” when it starts, like so:

LAMBDA2:

def lambda_handler(event, context):
    # "event" contains the contents from what was returned from the previous function.
    # Since it's an array, you can refer to each member by its number, counting up from [0].
    # So, to begin, we'll want to create variables which reflect the incoming data.
    var1 = event[0]
    var2 = event[1]
    both = [var2, var1]
    # This prints the contents of "both" ( ['bye', 'HEllo!'] ) to the CloudWatch log:
    print(both)
    # This returns the contents of the "both" variable to whatever ran this function:
    return both

So now we’ve taken the data from LAMBDA1, which Step Functions has passed to LAMBDA2 as “event” and then we’ve created new variables pointing to each member of the array. Since this is an entirely new Lambda you can give the data different variable names, or use the same names as the previous function used.

OK, so that’s how the Lambdas are written, but how about the Step Functions code? Here’s what you would use to make the basic functions above result in a final output of:

{
  "output": [
    "bye",
    "HEllo!"
  ]
}

 

Step Function code:

{
  "StartAt": "state1",
  "States": {
    "state1": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:12345678912:function:LAMBDA1",
      "Next": "state2"
    },
    "state2": {
       "Type": "Task",
      "Resource": "arn:aws:lambda:us-east-1:12345678912:function:LAMBDA2",
      "End": true
    }
  }
}

So that’s all there is to it! Now that you can take a few variables from your initial Lambda function and pass them through to subsequent functions, the possibilities are endless! It’s funny how being unable to do something so simple can be an obstacle to using any of this cool technology – so I’m surprised this isn’t spelled out anywhere in their docs. If you’d like to read more about the basics of using Step Functions, you may want to check out my follow-up post on how to get Step Functions to take action based on the value of returned variables.

Happy stepping,

Steve