3 minute read

In this tiny tutorial I will show you how to deploy an AWS Lambda serverless function on AWS using AWS CloudFormation.


  • We will create lambda_handler.py locally and upload it to to some s3 bucket we own
  • Deploy a CloudFormation stack that creates a new Lambda as a resource


First, in this tutorial I assume that you have an active AWS account on which you have the rights to provision infrastructure.

Second, you should be able to connect to the AWS SDK through the CLI with valid credentials. If you don’t have these yet, follow the instructions here

This is what your ~/.aws/config should look like.

[profile sandbox]
sso_role_name = Admin
sso_account_id = 1234
sso_start_url = https://xxx.awsapps.com/start
sso_region = eu-west-1
[profile Admin-1234]
sso_start_url = https://xxx.awsapps.com/start#/
sso_region = eu-west-1
sso_account_id = 1234
sso_role_name = Admin
region = eu-west-1

Step 1: Create the s3 bucket

First thing we should do is create a new s3 bucket

Ideally, this is also handled and deployed automatically, but for now do it manually.

I call mine tmp-jan-bucket.

Step 2: Upload the lambda

Find the code here.

This is the Lambda that we will host as a serverless function. It does nothing except for return the event as a json.

import json

def lambda_handler(event, context):
    response = {
        "statusCode": 200,
        "body": json.dumps(event)
    return response

AWS wants a .zip, so let’s zip the python file using the provided script.

python zip.py 

Which creates lambda_handler.zip. This file we can now upload

aws s3 cp lambda_handler.zip s3://tmp-jan-bucket/tmp-jan-s3-key/lambda.zip --profile Admin-1234

Note that we must pass on the --profile flag.

If you did everything correctly now s3 should show you the uploaded file in the bucket key combination s3://tmp-jan-bucket/tmp-jan-s3-key

The lambda is now uploaded and we can deploy it using our CloudFormation template.

Step 3: Deploying the CloudFormation template

Now take the template in templates/deploy-lambda.yaml

AWSTemplateFormatVersion: '2010-09-09'
Description: 'Example Lambda'

# Code taken from here: https://github.com/aws-quickstart/quickstart-examples/blob/main/patterns/LambdaZips/example.yaml

    AllowedPattern: ^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$
    Default: tmp-jan-bucket
    Type: String
    AllowedPattern: ^[0-9a-zA-Z-/]*$
    Default: tmp-jan-s3-key/
    Type: String

    Type: AWS::IAM::Role
        Version: '2012-10-17'
          - Effect: Allow
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
    Type: AWS::Lambda::Function
      Description: Example
      Handler: lambda_handler.lambda_handler # filename.functionname
      Runtime: python3.7
      Role: !GetAtt 'MyFunctionRole.Arn'
      Timeout: 300
        S3Bucket: !Sub '${StartBucketName}'
        S3Key: !Sub '${S3KeyPrefix}lambda.zip'

And let’s deploy it as a cloud stack using aws cloudformation deploy

λ aws cloudformation deploy --template-file templates/deploy-lambda.yaml --stack-name tmp-jan-stack --capabilities CAPABILITY_NAMED_IAM --profile Admin-1234

Note that, we must use --capabilities CAPABILITY_NAMED_IAM because we provide named IAM resources. See also this link

Deploying might takes 1-2 minutes, but if everything goes as planned you should see this.

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - tmp-jan-stack

And now if you look in CloudFormation you should see this

We have successfully deployed!

Step 4: Testing

The stack is deployed and when we look at our Lambdas we see a new one, the one that the stack created.

Lets create a new test event

And test it

We see that we get back the response that we expect.

Step 5: Cleanup

Of course, when you provision infrastructure on the cloud you always want to gracefully shut down what you start to avoid unnecessary costs.

Let’s not forget to actually stop our cloud stack.

λ aws cloudformation delete-stack --stack-name tmp-jan-stack --profile Admin-1234

After initiating the delete you should see a deletion in progress.

After which the stack is gone. Also check your Lambdas to make sure that they got deleted successfully.

Wrapping up

In this tiny tutorial I showed you how to deploy a serverless AWS Lambda using AWS CloudFormation. Deploying infrastructure through infrastructure-as-code solutions like CloudFormation (and Terraform etc) is very important if you want to build large and complex systems that scale.

I hope you had as much fun as I had making this, and see you next time!

- Jan