AWS SAM Setup for Serverless Backend
AWS SAM (Serverless Application Model) is the official AWS tool for defining serverless resources. It extends CloudFormation with simplified syntax: instead of 50 lines of CloudFormation for Lambda + API Gateway + IAM, write 10 lines of SAM. Output is a full CloudFormation stack, versioned and rollbackable.
Unlike Serverless Framework, SAM is AWS-native with no abstraction over other providers. This is its advantage: full CloudFormation compatibility, native CDK integration, direct SAM CLI for local testing with real service mocks.
Installation and First Project
# macOS
brew tap aws/tap
brew install aws-sam-cli
# Linux
pip install aws-sam-cli
sam --version
sam init --runtime nodejs20.x --dependency-manager npm --app-template hello-world --name my-backend
Project Structure
my-backend/
├── template.yaml
├── samconfig.toml
├── src/
│ ├── handlers/
│ │ ├── api.ts
│ │ └── auth.ts
│ └── shared/
├── events/
└── __tests__/
template.yaml Configuration
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Globals:
Function:
Runtime: nodejs20.x
Architectures: [arm64]
MemorySize: 512
Timeout: 10
Environment:
Variables:
NODE_ENV: !Ref Stage
Parameters:
Stage:
Type: String
Default: dev
AllowedValues: [dev, staging, prod]
Resources:
ApiGateway:
Type: AWS::Serverless::HttpApi
Properties:
StageName: !Ref Stage
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Handler: src/handlers/api.handler
Events:
AnyRoute:
Type: HttpApi
Properties:
ApiId: !Ref ApiGateway
Method: ANY
Path: /api/{proxy+}
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref MainTable
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: es2022
MainTable:
Type: AWS::DynamoDB::Table
Properties:
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- { AttributeName: pk, AttributeType: S }
- { AttributeName: sk, AttributeType: S }
KeySchema:
- { AttributeName: pk, KeyType: HASH }
- { AttributeName: sk, KeyType: RANGE }
Outputs:
ApiUrl:
Value: !Sub 'https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${Stage}'
TableName:
Value: !Ref MainTable
Handler
// src/handlers/api.ts
import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from 'aws-lambda';
export const handler = async (event: APIGatewayProxyEventV2): Promise<APIGatewayProxyResultV2> => {
return {
statusCode: 200,
body: JSON.stringify({ message: 'Hello from SAM!' }),
};
};
samconfig.toml
[default.deploy.parameters]
stack_name = "my-backend-dev"
s3_bucket = "sam-artifacts-eu-west-1"
region = "eu-west-1"
parameter_overrides = "Stage=dev"
[prod.deploy.parameters]
stack_name = "my-backend-prod"
s3_bucket = "sam-artifacts-eu-west-1"
region = "eu-west-1"
parameter_overrides = "Stage=prod"
Local Development
sam build
sam local start-api --env-vars env.json --port 3001
sam local invoke ApiFunction --event events/api-get.json
sam logs --stack-name my-backend-dev --tail
Deployment
sam deploy --guided
sam build && sam deploy
sam build && sam deploy --config-env prod
Timeframe
Basic SAM backend with Lambda + HTTP API + DynamoDB — 1–2 days. Full structure with authorizer, SQS, S3, and multi-environment config — 4–5 days.







