AWS SAM: AWS Way Of Building Serverless Applications

AWS SAM
author valts

by Valts Ausmanis · January 23, 2024

AWS released AWS serverless application model (AWS SAM) in 2016 to improve the way we build and run serverless applications in AWS cloud. Back then it wasn’t the first choice when compared with Serverless Framework. But what about nowadays? AWS SAM has solid CLI with local development functionality, and community support has grown. In this article we will build a serverless application by using AWS SAM and let’s see how this tool now compares with Serverless Framework – most popular tool for building serverless applications for AWS cloud.

In This Article

What is Serverless Application?

Serverless is the way to build and run serverless applications and services without thinking about servers. There are underlying servers used to run your serverless applications but you don’t have manage those as it’s done by your cloud provider in our case AWS.

Serverless application is the combination of compute services, event sources and other services to fulfil applications use case. AWS introduced AWS Lambda back in 2014 which is more than 10 years ago and I’m pretty sure that today anyone who has some experience with AWS cloud can directly relate Lambda with term Serverless. AWS Lambda is the core compute service for building serverless applications in AWS cloud and is often configured together with other services like API Gateway, S3, Cognito and DynamoDB to build solid production ready cloud applications.

What is AWS Serverless Application Model (AWS SAM)?

The AWS serverless application model (AWS SAM) is an open-source infrastructure as code tool to improve the way we build and run serverless applications in AWS cloud.

AWS SAM consists of two main parts:

AWS SAM Template Specification

AWS SAM templates (YAML) are used to define your AWS serverless application. You can think of SAM template as an extension to CloudFormation templates. In fact, you can have AWS SAM and CloudFormation syntax in the same template. So why to use AWS SAM syntax at all? Well, In order to have a nice short-hand way to define your main AWS serverless application resources like Lambda functions and their event sources (ex. API gateway endpoints).

AWS SAM CLI

AWS SAM CLI is an open-source command line tool to help you to build and deploy your serverless applications to AWS cloud.

Most frequently used commands are:

  • sam init to help you to kick-start your new serverless application project. This will generate complete project structure (which you can easily change) for your selected example application.
  • sam build to package your application and generation files (like CloudFormation templates, Lambda code assets) that are necessary for deployment.
  • sam deploy to deploy your application to AWS cloud.
  • sam local can be used for local development to invoke your Lambdas locally or start local API gateway endpoints to test your Lambdas through HTTP server host.

Let’s Build a Serverless Application

In one of the previous articles, we compared AWS CDK and Serverless Framework tools and we built the sample newsletter serverless application in order to show what it takes to build it by using both of the tools. Now let’s use the AWS SAM to build the same newsletter serverless application:

  • API Gateway with two endpoints:
    • Add new subscriber POST /subscriber
    • Delete subscriber DELETE /subscriber/{subscriberId}
  • Two Lambda functions to add and delete our newsletter subscribers
  • DynamoDB to store the subscriber data

After a hands-on build we will be able to compare it with Serverless Framework.

Defining SAM template

You define your serverless application infrastructure (like Lambda functions, events, roles etc.) via YAML file template.yaml:


# The AWSTemplateFormatVersion identifies the capabilities of the template
AWSTemplateFormatVersion: 2010-09-09
Description: Newsletter sample serverless application using AWS SAM

# Transform section specifies one or more macros that AWS CloudFormation uses to process your template
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs18.x

# Resources declares the AWS resources that you want to include in the stack
Resources:
  subscribe:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/subscribe.handler
      Policies:
        # Give Create/Read/Update/Delete Permissions to the SubscribersTable
        - DynamoDBCrudPolicy:
            TableName: !Ref SubscribersTable
      Environment:
        Variables:
          # Make table name accessible as environment variable from function code during execution
          SUBSCRIBERS_TABLE: !Ref SubscribersTable
      Events:
        Api:
          Type: Api
          Properties:
            Path: /subscriber
            Method: POST

  unsubscribe:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/unsubscribe.handler
      Policies:
        # Give Create/Read/Update/Delete Permissions to the SubscribersTable
        - DynamoDBCrudPolicy:
            TableName: !Ref SubscribersTable
      Environment:
        Variables:
          # Make table name accessible as environment variable from function code during execution
          SUBSCRIBERS_TABLE: !Ref SubscribersTable
      Events:
        Api:
          Type: Api
          Properties:
            Path: /subscriber/{subscriberId}
            Method: DELETE

  # DynamoDB table
  SubscribersTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: subscriberId
        Type: String

Outputs:
  WebEndpoint:
    Description: "API Gateway endpoint URL for deployed stage"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

You can check out AWS SAM specification documentation to see all information about supported AWS SAM resources and properties.

Packaging and Deployment

In order to package and deploy our SAM serverless application we have to first install SAM CLI and if not done already – configure default AWS credentials.

Next step is to define the AWS SAM CLI configuration file samconfig.toml which allows us to pre-configure specific CLI command parameter values (like stack name, region, tags etc.) so you don’t have to provide these each time you want to deploy your application to AWS cloud:


version = 0.1
[default.deploy.parameters]
stack_name = "newsletter-sam-dev"
region = "eu-west-1"
resolve_s3 = true
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
tags = "STAGE=\"dev\""

Let’s update our Lambdas infrastructure code in template.yaml file with metadata to bundle our Lambdas with esbuild. The difference comparing to Serverless Framework is that instead of one global place for AWS SAM you have to add this metadata for each Lambda resource that you define in your application:


    Metadata:
      BuildMethod: esbuild
      BuildProperties:
        Minify: true
        External:
          - "@aws-sdk/*"

I have tried to find the way how to re-use the same metadata config but I didn’t find the simple enough solution.

Now let’s build the AWS SAM cloud application artifacts with command sam build:sam cli packaging and build process

The build artifacts were stored in .aws-sam folder which contains:sam package artifacts

  • CloudFormation template template.yaml that describes AWS resources for our serverless application.
  • Minified .js file for each of the Lambda functions.
  • Autogenerated build.toml file containing function build definitions.

To deploy our newsletter application we will use CLI command sam deploy which will deploy application to AWS cloud by using configured default AWS credentials and deploy parameters from samconfig.toml:sam deployment

To see the overview of the serverless application that we just deployed let’s use Cloudviz.io diagram generator:

You can find complete code for our SAM newsletter serverless application in our cloudviz-io/cloudviz-blog-samples repository.

Local Development

AWS SAM CLI provides functionality to locally test and initiate your Lambda functions and API endpoints.

Let’s create test POST /subscribe event for subscribe Lambda:


{
  "body": "{ \"email\": \"test@test.test\"}"
}

Create environment variables file env.json to tell local Lambda function to work with the deployed DynamoDB table. To find the table name use aws dynamodb list-tables.


{
  "Parameters": {
    "SUBSCRIBERS_TABLE": "newsletter-sam-dev-SubscribersTable-xxxxxxx"
  }
}

You could of course ask a question here: “Why aren't we using DynamoDB local in our development?”. Yes, you can of course spend additional time of spinning up your local DynamoDB environment via docker and most likely you will fix docker networking challenges. But why should we add this additional config to our serverless setup when we can directly connect with and verify using real DynamoDB table in AWS cloud? For most use cases DynamoDB costs shouldn’t be the issue.

To initiate our subscribe Lambda function run command sam local invoke subscribe --event local/events/subscribe.json --env-vars local/env.json:sam cli local lambda invoke

Let’s verify in the AWS console that our record was successfully added in DynamoDB table:aws dynamodb table results

Now let’s start locally our defined serverless application API endpoints to invoke lambdas via real HTTP requestssam local start-api --env-vars local/env.json :sam cli local api init

Next we will send the POST /subscribers request to our local AWS SAM endpoint to add new subscriber:postman post request

Below you can see request logs from our terminal were we started SAM local API:sam cli local api response

Invoke Lambdas in AWS Cloud

Local development is awesome but what about invoking your AWS SAM functions directly in AWS cloud. To be honest in my development workflow (additionally to CI/CD pipelines) it’s must have to verify my infrastructure and Lambda code in real environment like AWS cloud. Local development and testing are nice but your serverless application will run in AWS cloud not locally.

To invoke our SAM defined Lambda function in AWS cloud we can use this command sam remote invoke subscribe --stack-name newsletter-sam-dev --event-file local/events/subscribe.json sam cli remote invoke lambda

Let’s check the CloudWatch logs to verify that our function was actually triggered:c;loudwatch logs

How Does AWS SAM Compare With Serverless Framework?

Similarities:

  • YAML. Both use YAML template to define serverless application.
  • Focus on AWS. Both tools were built with main focus to build and deploy serverless applications for AWS cloud.
  • CLI and Local Development. Both tools have solid CLI functionality – including functionality to invoke and test locally your defined serverless application.
  • AWS CloudFormation. Under the hood serverless applications are deployed to AWS by using AWS CloudFormation thus deployment speed in most scenarios will be the same.
  • Simplicity. Both tools provide simple way to define your main serverless application resources like Lambdas and event sources.

Differences:

  • Plugins. For serverless framework there is solid list of plugins that you can use or you can build your own to extend default framework functionality. For SAM most similar thing could be CloudFormation macros that you can define to implement custom templates processing. But if we are completely fair this is CloudFormation functionality not really the AWS SAM.
  • Open-Source Community. Serverless framework is clear winner with ~46K stars vs AWS SAM ~9.2K stars.
  • Additional config file. For AWS SAM you have additional config file samconfig.toml to define your deployment parameters. For Serverless Framework you put the service name, default stage, region in one template file serverless.yml together with all your serverless application definition. It’s not a deal breaker but I like this keep it simple approach.
  • Connecting Lambdas to New or Existing VPCs. For Serverless Framework there are plugins like VPC discovery to attach Lambdas to existing VPC and serverless VPC plugin to provision new VPC with different resources. For AWS SAM it looks like the only way is to write pure CloudFormation template to provision all the necessary resources and policies.

Summary

AWS SAM during the last years has improved a lot if we compare with the one which was introduced back in 2016. AWS SAM now has solid CLI with functionality not only to package and deploy your AWS serverless application but to invoke your defined resources like Lambda, API gateway endpoints locally. AWS SAM is pretty similar to Serverless Framework regards to defining simple serverless applications with Lambdas and different event sources as triggers, to package your Lambdas code and deploy the application to AWS cloud (under the hood using AWS CloudFormation).

So the question is: “If I had to choose today between AWS SAM or Serverless Framework to build and deploy my next serverless application to AWS cloud, which one would it be?”. My answer would be Serverless Framework. Serverless Framework is more popular in open-source community and one of the most popular IaC tools used in many organizations to manage Lambda functions and of course many plugins that are available to be used for your next serverless project. Additionally, even the AWS SAM is simple to use – overall Serverless Framework seems more “keep it simple and clean” tool. For example, in order to bundle the Lambda functions with esbuild I had to add esbuild related metadata to each Lambda function in AWS SAM template. However, for Serverless Framework I just added that config under custom global parameter which automatically applied to all functions.



Start your free trial

As experienced AWS architects and developers, our goal is to provide users an easy way to create stunning AWS architecture diagrams and detailed technical documentation. Join us to simplify your diagramming process and unleash the beauty of your cloud infrastructure


Copyright © 2019 - 2024 Cloudviz Solutions SIA