AWS for DevOps — SAM: Serverless Application Model

2 minute read

9.4 — SAM: Serverless Application Model

AWS SAM is a framework for building serverless applications. It extends CloudFormation with simplified syntax for Lambda, API Gateway, DynamoDB, and more.

SAM vs Raw CloudFormation

Raw CloudFormation SAM
50+ lines for one Lambda function 10 lines
Manually wire API Gateway + Lambda + permissions Automatic with Events property
No local testing sam local invoke, sam local start-api

Installation

# macOS
$ brew install aws-sam-cli

# Verify
$ sam --version
SAM CLI, version 1.120.0

SAM Template

template.yaml:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: "My Serverless API"

Globals:
  Function:
    Runtime: python3.12
    Timeout: 30
    MemorySize: 256
    Environment:
      Variables:
        TABLE_NAME: !Ref DeploymentsTable

Resources:
  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      CodeUri: src/hello/
      Events:
        HelloApi:
          Type: HttpApi
          Properties:
            Path: /hello
            Method: get

  CreateDeploymentFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: app.lambda_handler
      CodeUri: src/create-deployment/
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref DeploymentsTable
      Events:
        CreateApi:
          Type: HttpApi
          Properties:
            Path: /deployments
            Method: post

  DeploymentsTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
        Name: DeploymentId
        Type: String

Outputs:
  ApiUrl:
    Value: !Sub "https://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com"

Project Structure

my-serverless-app/
├── template.yaml           ← SAM template
├── samconfig.toml          ← Deploy configuration
├── src/
│   ├── hello/
│   │   ├── app.py          ← Lambda handler
│   │   └── requirements.txt
│   └── create-deployment/
│       ├── app.py
│       └── requirements.txt
└── tests/
    └── test_hello.py

SAM Workflow

# 1. Build (installs dependencies, packages code)
$ sam build
Building codeuri: src/hello/ runtime: python3.12
Build Succeeded

# 2. Local testing
$ sam local invoke HelloFunction --event events/hello.json
{"statusCode": 200, "body": "{\"message\": \"Hello, World!\"}"}

# Start a local API (mimics API Gateway)
$ sam local start-api
Mounting HelloFunction at http://127.0.0.1:3000/hello [GET]
$ curl http://localhost:3000/hello

# 3. Deploy (guided for first time)
$ sam deploy --guided
Setting default arguments for 'sam deploy'
  Stack Name: my-serverless-app
  AWS Region: ap-south-1
  Confirm changes before deploy: yes
  Allow SAM CLI IAM role creation: yes

# Subsequent deploys
$ sam deploy

SAM Resource Types

SAM Resource Equivalent CloudFormation Simplified?
AWS::Serverless::Function Lambda + IAM Role + permissions Much simpler
AWS::Serverless::HttpApi API Gateway HTTP API Auto-created from Events
AWS::Serverless::Api API Gateway REST API Auto-created from Events
AWS::Serverless::SimpleTable DynamoDB table One-line table

SAM Policy Templates

Instead of writing full IAM policies, use SAM’s shorthand:

Policies:
  - DynamoDBCrudPolicy:
      TableName: !Ref MyTable
  - S3ReadPolicy:
      BucketName: !Ref MyBucket
  - SQSPollerPolicy:
      QueueName: !GetAtt MyQueue.QueueName

samconfig.toml

Save deploy settings so you don’t re-type them:

version = 0.1

[default.deploy.parameters]
stack_name = "my-serverless-app"
region = "ap-south-1"
resolve_s3 = true
capabilities = "CAPABILITY_IAM"
confirm_changeset = true

Common Mistakes

Mistake Why It Hurts Fix
Not running sam build before deploy Old code gets deployed Always build before deploy
Missing Transform line SAM resources not recognized Include Transform: AWS::Serverless-2016-10-31
Not using SAM policy templates Verbose IAM policies, over-permissioned Use built-in policy templates
Skipping local testing Bugs found only after deployment Use sam local invoke and sam local start-api

Quick Reference

Task Command
Init project sam init
Build sam build
Local invoke sam local invoke FunctionName --event event.json
Local API sam local start-api
Deploy (first time) sam deploy --guided
Deploy (subsequent) sam deploy
View logs sam logs -n FunctionName --stack-name STACK --tail
Delete sam delete --stack-name STACK

Next → Event-Driven Architecture

Updated: