The AWS Serverless Application Model (SAM) is an open-source framework for building serverless applications. Building serverless applications is a core feature of Amazon Web Services. Being able to deploy applications in the cloud in a matter of minutes is every developer’s dream. In this tutorial, we are going to dive deep into the SAM architecture that was developed by AWS.
AWS SAM provides shorthand syntax to express functions, APIs, databases, and event source mappings. With just a few lines per resource, you can define the application you want and model it using YAML. During deployment, SAM transforms and expands the SAM syntax into AWS CloudFormation syntax, enabling you to build serverless applications faster.
Deploy AWS Cloud9 IDE
Cloud9 is a cloud based IDE that will let you write, run, and debug code in your browser without having to install and tools into your local machine. This will save us time and speed up the deployment process.
Go to Cloud9 console: https://console.aws.amazon.com/cloud9

We are going to create a new EC2 instance using the free tier.

I will be accessing the instance using SSH. In that case, go ahead and choose SSH access. You will also need to modify the network settings to use a public subnet instead of a private subnet as we will be connecting via SSH and not SSM.

Welcome to Cloud9 IDE

Upgrade SAM CLI
We will need to upgrade the SAM CLI to the latest version using the below bootstrap script. Run the below command inside the Cloud9 IDE environment:
curl 'https://static.us-east-1.prod.workshops.aws/public/4dab591c-f4d3-465a-8c36-84c423762e2e/static/bin/bootstrap.sh' | bash
You will get the following output:
+ _logger '[+] Updating SAM...'
++ date
+ echo -e 'Wed Nov 23 09:33:29 UTC 2022 \033[1;33m[*] [+] Updating SAM... \033[0m'
Wed Nov 23 09:33:29 UTC 2022 [*] [+] Updating SAM...
+ sudo ./sam-installation/install --update
You can now run: /usr/local/bin/sam --version
+ _logger '[+] Updating Cloud9 SAM binary'
++ date
+ echo -e 'Wed Nov 23 09:33:31 UTC 2022 \033[1;33m[*] [+] Updating Cloud9 SAM binary \033[0m'
Wed Nov 23 09:33:31 UTC 2022 [*] [+] Updating Cloud9 SAM binary
++ which sam
+ ln -sf /usr/local/bin/sam /home/ec2-user/.c9/bin/sam
+ cleanup
+ [[ -d sam-installation ]]
+ rm -rf sam-installation
+ echo -e '\033[0;31m [!!!!!!!!!] To be safe, I suggest closing this terminal and opening a new one! \033[0m'
[!!!!!!!!!] To be safe, I suggest closing this terminal and opening a new one!
+ _logger '[+] Restarting Shell to reflect changes'
++ date
+ echo -e 'Wed Nov 23 09:33:31 UTC 2022 \033[1;33m[*] [+] Restarting Shell to reflect changes \033[0m'
Wed Nov 23 09:33:31 UTC 2022 [*] [+] Restarting Shell to reflect changes
+ exec /bin/bash
Admin:~/environment $
You can run the command sam –version to confirm you have the latest version.
Create SAM (Serverless Application Model) Scaffolding
Developers can create serverless apps on AWS that are fit for production using the open-source AWS Serverless Application Model (AWS SAM).
In order to carry out tasks, a serverless application combines Lambda functions, event sources, and other resources. A serverless application, however, can have extra resources like APIs, databases, and event source mappings in addition to Lambda functions.
You will discover how to quickly design a SAM application and comprehend its structure in this chapter.
You may easily construct and administer serverless applications with the help of AWS SAM’s command-line tool, the AWS SAM CLI. Because it offers the first framework for a hello world application, it makes it especially simple to scaffold a new project. You may take this framework as a starting point and construct your project from there.
Run the following command to start a new project:
sam init
In the wizard, select AWS QuickStart Templates and Hello World Example.
I’ll use nodejs16.x
but feel free to choose python3.7
if you are comfortable reading Python instead of Node JS.
Admin:~/environment $ sam init
SAM CLI now collects telemetry to better understand customer needs.
You can OPT OUT and disable telemetry collection by setting the
environment variable SAM_CLI_TELEMETRY=0 in your shell.
Thanks for your help!
Learn More: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-telemetry.html
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Multi-step workflow
3 - Serverless API
4 - Scheduled task
5 - Standalone function
6 - Data processing
7 - Infrastructure event management
8 - Serverless Connector Hello World Example
9 - Multi-step workflow with Connectors
10 - Lambda EFS example
11 - Machine Learning
Template: 1
Use the most popular runtime and package type? (Python and zip) [y/N]: n
Which runtime would you like to use?
1 - aot.dotnet7 (provided.al2)
2 - dotnet6
3 - dotnet5.0
4 - dotnetcore3.1
5 - go1.x
6 - graalvm.java11 (provided.al2)
7 - graalvm.java17 (provided.al2)
8 - java11
9 - java8.al2
10 - java8
11 - nodejs18.x
12 - nodejs16.x
13 - nodejs14.x
14 - nodejs12.x
15 - python3.9
16 - python3.8
17 - python3.7
18 - ruby2.7
19 - rust (provided.al2)
Runtime: 12
What package type would you like to use?
1 - Zip
2 - Image
Package type: 1
Based on your selections, the only dependency manager available is npm.
We will proceed copying the template using npm.
Select your starter template
1 - Hello World Example
2 - Hello World Example TypeScript
3 - Hello World Example TypeScript w/ Lambda Powertools
Template: 1
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n
Project name [sam-app]:
Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)
-----------------------
Generating application:
-----------------------
Name: sam-app
Runtime: nodejs16.x
Architectures: x86_64
Dependency Manager: npm
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./sam-app/README.md
Commands you can use next
=========================
[*] Create pipeline: cd sam-app && sam pipeline init --bootstrap
[*] Validate SAM template: cd sam-app && sam validate
[*] Test Function in the Cloud: cd sam-app && sam sync --stack-name {stack-name} --watch
Admin:~/environment $
You should see a new folder sam-app
created with a basic Hello World environment.

Serverless Application Model Architecture
When the Hello World SAM project is deployed, the following architecture will be constructed. It just contains one Lambda function, which is invoked when an HTTP GET request is made to an API Gateway that exposes the /hello resource. In order to connect with other AWS services, such as a database, the Lambda function assumes an IAM execution role.

Let’s explore the SAM template, which describes the architecture of your Serverless application, to better grasp the structure of a SAM application. Open the sam-app/template.yaml file right away. It ought to be organised as shown below. This is your template and a Node application. If using a different runtime, yaml will have a somewhat different appearance.
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
sam-app
Sample SAM Template for sam-app
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs16.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
Because SAM templates are an extension of CloudFormation templates, you may have noticed that the syntax is identical to that of AWS CloudFormation. In other words, you can declare any resource in a SAM template that you can declare in CloudFormation. Let’s examine the template’s elements more closely.
Transform
Take note of the template’s morph line, which is highlighted below. This line informs CloudFormation that the template complies with the AWS Serverless Application Model specification, which is an open source document:
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals
This section outlines the characteristics that all of your Serverless functions and APIs share. In this instance, it is defining that the default timeout for all functions in this project shall be 3 seconds.
Globals:
Function:
Timeout: 3
Hello World Function
A Lambda function with an IAM execution role is created in the next section. Additionally, it indicates that the code for this Lambda function may be found in the folder indicated by the CodeUri key. The entrypoint’s file and function names are specified by the Handler key.
It’s important to note that the IAM role is not explicitly defined because SAM will automatically establish one. By defining the Role argument, you can override this behaviour and pass your own role. Check the SAM reference for a comprehensive list of the parameters you can supply for a Lambda function.
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs16.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Event Triggers
The Events section is part of the function definition. This section specifies the different events that will trigger the Lambda function. In this case, we are specifying an HTTP GET request to an API Gateway with an endpoint of /hello.
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs16.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Outputs
The Outputs area of the CloudFormation console lets you designate output values that you may import into other CloudFormation stacks (to make cross-stack references) or just view. In this instance, we’re making the IAM Role ARN, the Lambda function ARN, and the API Gateway endpoint URL accessible as Outputs to make them simpler to find.
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
Hello World Function
Let’s examine the Hello World Lambda function’s source code.
// const axios = require('axios')
// const url = 'http://checkip.amazonaws.com/';
let response;
/**
*
* Event doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html#api-gateway-simple-proxy-for-lambda-input-format
* @param {Object} event - API Gateway Lambda Proxy Input Format
*
* Context doc: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html
* @param {Object} context
*
* Return doc: https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html
* @returns {Object} object - API Gateway Lambda Proxy Output Format
*
*/
exports.lambdaHandler = async (event, context) => {
try {
// const ret = await axios(url);
response = {
'statusCode': 200,
'body': JSON.stringify({
message: 'hello world',
// location: ret.data.trim()
})
}
} catch (err) {
console.log(err);
return err;
}
return response
};
Your Lambda function’s handler method handles event processing. The handler method is launched by the runtime whenever you call a function. Your function becomes available to handle another event when it ends or returns a result. The CodeUri and Handler keys in the SAM template.yaml file allow you to change the handler function’s name or location. Code that can be reused across invocations should be placed outside of the handler scope because the Lambda handler is run on every invocation. Initializing database connections outside of the handler is a typical example.
Event Object
The event object, which includes data from the invoker, is supplied as the first input to the handler function. The HTTP request data is passed as a JSON-formatted string to API Gateway, the invoker in this instance, and is converted to an object by the Lambda runtime. Examples of event payloads are available at this link.
Context Object
The context object, the second argument, contains details about the environment for the invocation, function, and execution. You can obtain details such as the CloudWatch log stream name or the function’s remaining execution time.
Handler Response
API Gateway anticipates the handler to deliver a response object with the following contents: statusCode, body, and optional headers. The documentation for the integration of Lambda with API Gateway has more information regarding the return format.
We have reached the end of Part #1. In the second section, we will dive deep into running and testing the SAM application using AWS SAM CLI.
Now that you have a SAM application. You will learn how to run it and test it locally using the AWS SAM CLI. This is significant because it is a regular part of the development workflow.
Amazing article. Thanks!