AWS SAM (Serverless Application Model) is an open-source framework for building serverless applications. It extends CloudFormation with simplified syntax and provides a CLI for local development and deployment. Think of SAM as CloudFormation’s serverless-specific dialect — you write 20 lines of SAM and it expands into 200 lines of CloudFormation behind the scenes. The trade-off is less flexibility (you cannot control every CloudFormation property), but for 90% of serverless use cases, SAM’s defaults are exactly what a senior engineer would configure anyway.What You’ll Learn:
AWSTemplateFormatVersion: '2010-09-09'Transform: AWS::Serverless-2016-10-31Description: My Serverless Application# Globals apply to ALL functions in the template -- the DRY principle for# serverless. Instead of repeating Runtime and Timeout on every function,# set them once here. Individual functions can override any Global value.Globals: Function: Runtime: python3.11 Timeout: 30 MemorySize: 256 Tracing: Active # Enables X-Ray on all functions Environment: Variables: LOG_LEVEL: INFO TABLE_NAME: !Ref OrdersTableParameters: Environment: Type: String Default: dev AllowedValues: [dev, staging, prod]Resources: # Lambda Function OrderFunction: Type: AWS::Serverless::Function Properties: Handler: app.lambda_handler CodeUri: src/ Description: Process orders Events: ApiEvent: Type: Api Properties: Path: /orders Method: POST Policies: - DynamoDBCrudPolicy: TableName: !Ref OrdersTable # DynamoDB Table OrdersTable: Type: AWS::DynamoDB::Table Properties: TableName: !Sub ${Environment}-orders # PAY_PER_REQUEST (on-demand) is ideal for dev/staging and unpredictable # workloads. For steady production traffic (>100 reads/sec consistently), # PROVISIONED with auto-scaling is 20-30% cheaper. BillingMode: PAY_PER_REQUEST AttributeDefinitions: - AttributeName: order_id AttributeType: S KeySchema: - AttributeName: order_id KeyType: HASHOutputs: ApiUrl: Description: API Gateway URL Value: !Sub https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/
# HTTP API (API Gateway v2) - simpler, cheaper# Cost comparison: HTTP API costs $1.00/million requests vs REST API at# $3.50/million. HTTP API also has lower latency (~10ms vs ~29ms added).# Use REST API only when you need: request validation, WAF integration,# API keys/usage plans, or caching. For most microservice-to-microservice# or simple CRUD APIs, HTTP API is the better choice.MyHttpApi: Type: AWS::Serverless::HttpApi Properties: StageName: prod CorsConfiguration: AllowOrigins: - "https://myapp.com" AllowMethods: - GET - POST AllowHeaders: - Content-TypeMyFunction: Type: AWS::Serverless::Function Properties: Events: HttpApiEvent: Type: HttpApi Properties: ApiId: !Ref MyHttpApi Path: /items Method: GET
┌────────────────────────────────────────────────────────────────────────┐│ SAM CLI Workflow │├────────────────────────────────────────────────────────────────────────┤│ ││ Development Workflow: ││ ───────────────────── ││ ││ sam init # Create new project from template ││ │ ││ ▼ ││ sam build # Build and package application ││ │ ││ ▼ ││ sam local invoke # Test single function locally ││ sam local start-api # Start local API Gateway ││ │ ││ ▼ ││ sam validate # Validate template ││ │ ││ ▼ ││ sam deploy --guided # Deploy to AWS (first time) ││ sam deploy # Deploy using saved config ││ │ ││ ▼ ││ sam logs -n MyFunction # View CloudWatch logs ││ sam traces # View X-Ray traces ││ │└────────────────────────────────────────────────────────────────────────┘
# Initialize new projectsam init --runtime python3.11 --name my-app# Build the applicationsam build# Start local API Gateway -- spins up a Docker container mimicking# API Gateway + Lambda. Requests to localhost:3000 invoke your handler.# Common mistake: Assuming local behavior matches production. Local invoke# does NOT simulate IAM permissions, VPC networking, or concurrency limits.# Always run integration tests against a deployed stack before production.sam local start-api --port 3000# Invoke function with event filesam local invoke MyFunction --event events/order.json# Generate sample eventsam local generate-event apigateway aws-proxy > events/api.jsonsam local generate-event s3 put > events/s3.json# Start Lambda with hot reloadsam local start-lambda --host 0.0.0.0# Debug with VS Code (attach debugger on port 5858)sam local invoke -d 5858 MyFunction --event event.json