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.
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.
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 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 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. 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:
POST /subscriber
DELETE /subscriber/{subscriberId}
After a hands-on build we will be able to compare it with Serverless Framework.
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.
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
:
The build artifacts were stored in .aws-sam
folder which contains:
template.yaml
that describes AWS resources for our serverless application..js
file for each of the Lambda functions.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
:
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.
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
:
Let’s verify in the AWS console that our record was successfully added in DynamoDB table:
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
:
Next we will send the POST /subscribers
request to our local AWS SAM endpoint to add new subscriber:
Below you can see request logs from our terminal were we started SAM local API:
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
Let’s check the CloudWatch logs to verify that our function was actually triggered:
Similarities:
YAML
template to define serverless application.Differences:
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.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.
Looking for a tool to automatically generate AWS architecture diagram?
Try out Cloudviz.io and visualize your AWS cloud environment in seconds
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
Support
Contact
Copyright © 2019 - 2024 Cloudviz Solutions SIA