AWS SAM
The AWS Serverless Application Model is an open-source framework that extends CloudFormation
for serverless applications. A SAM template is a CloudFormation template carrying
Transform: AWS::Serverless-2016-10-31; the transform expands SAM’s high-level resource types
into the underlying Lambda functions, API Gateway resources, IAM roles and log groups before
the stack is created. Anything CloudFormation can do, a SAM template can also do, because it is
one.
Template
Section titled “Template”AWSTemplateFormatVersion: '2010-09-09'Transform: AWS::Serverless-2016-10-31
Globals: Function: Runtime: nodejs24.x Timeout: 10 MemorySize: 512 Tracing: Active
Resources: HelloFunction: Type: AWS::Serverless::Function Properties: CodeUri: src/hello/ Handler: index.handler Events: HelloApi: Type: HttpApi Properties: Path: /hello Method: getGlobals sets defaults for every function in the template, which is how a runtime upgrade
becomes a one-line change rather than a search and replace.
Runtime identifiers expire. Lambda deprecates runtimes on a published schedule and eventually blocks creating and then updating functions that use a deprecated one, so check the Lambda runtime support table rather than copying a runtime string from an older template.
Resource types
Section titled “Resource types”| Type | Expands to |
|---|---|
AWS::Serverless::Function | Lambda function, execution role, log group, event source mappings |
AWS::Serverless::Api | API Gateway REST API, stage and deployment |
AWS::Serverless::HttpApi | API Gateway HTTP API |
AWS::Serverless::SimpleTable | DynamoDB table with a single primary key |
AWS::Serverless::StateMachine | Step Functions state machine and its role |
AWS::Serverless::LayerVersion | Lambda layer version |
AWS::Serverless::Application | A nested application from the Serverless Application Repository or a local template |
Mixing plain CloudFormation resources into the same template is normal and expected — use SAM
types where they help and AWS:: types everywhere else.
Policy templates
Section titled “Policy templates”SAM can generate a scoped execution role from a named policy template, which is usually tighter than the managed policy someone would otherwise reach for:
MyFunction: Type: AWS::Serverless::Function Properties: Policies: - S3ReadPolicy: BucketName: !Ref MyBucket - DynamoDBCrudPolicy: TableName: !Ref MyTableLayers
Section titled “Layers” SharedLayer: Type: AWS::Serverless::LayerVersion Properties: ContentUri: ./layer CompatibleRuntimes: - nodejs24.xLocal development
Section titled “Local development”The SAM CLI runs functions and APIs locally in a container that matches the Lambda execution environment:
sam local start-api # local API Gateway in front of the functionssam local invoke # invoke one function with a test eventsam local start-lambda # local Lambda endpoint for SDK clientssam local generate-event apigateway aws-proxy > event.jsonThis is SAM’s main advantage over writing CloudFormation directly, and it is available to CDK users too — the CDK relies on the SAM CLI for local Lambda testing.
Build and deploy
Section titled “Build and deploy”sam build # resolve dependencies, produce build artefactssam deploy --guided # interactive first deployment, writes samconfig.tomlsam deploy # subsequent deployments from that configsam logs -n MyFunction --tailsam tracessam deploy creates a CloudFormation change set and executes it, so a SAM deployment is a
CloudFormation deployment with the same rollback behaviour.
Safe Lambda deployment with CodeDeploy
Section titled “Safe Lambda deployment with CodeDeploy”The feature that makes SAM more than syntactic sugar is its built-in integration with CodeDeploy for gradual traffic shifting between Lambda function versions.
PaymentFunction: Type: AWS::Serverless::Function Properties: CodeUri: src/payment/ Handler: index.handler AutoPublishAlias: live DeploymentPreference: Type: Canary10Percent5Minutes Alarms: - !Ref PaymentErrorAlarm Hooks: PreTraffic: !Ref PreTrafficCheckFunction PostTraffic: !Ref PostTrafficCheckFunctionWhat each part does:
AutoPublishAliaspublishes a new function version on every deployment and points an alias at it, which is what gives CodeDeploy two versions to shift between.DeploymentPreference.Typechooses the shift pattern —AllAtOnce,Linear10PercentEvery1Minute,Canary10Percent5Minutesand similar.Alarmsnames CloudWatch alarms that abort and roll back the deployment automatically if they enterALARMduring the shift. This is the part that makes the strategy safe rather than merely gradual.Hooksnames pre-traffic and post-traffic Lambda functions: the pre-traffic hook validates the new version before any production traffic reaches it, and the post-traffic hook runs after the shift completes. Either can fail the deployment.
The combination — canary shifting, validation hooks, alarm-triggered rollback — is why SAM plus CodeDeploy is a reasonable default for Lambda delivery, and all of it is declared in the template rather than assembled in a pipeline.
Alternatives for Lambda deployment
Section titled “Alternatives for Lambda deployment”AWS CDK. More programmatic control in TypeScript, Python, Java or C#, better suited to complex infrastructure where a general-purpose language earns its keep. It supports the same CodeDeploy traffic shifting, and it uses the SAM CLI for local testing.
Terraform. Sensible when Terraform already manages the rest of the estate and a single state and workflow matter more than serverless-specific ergonomics.
Direct CLI or console deployment. Fastest for a prototype; unsuitable for anything with users, because there is no reviewable record of what changed.
Practices
Section titled “Practices”- Put configuration in environment variables and secrets in Secrets Manager or Parameter Store; never in the template.
- Set timeouts and memory deliberately. The default timeout is too short for some work and far too long for a function that should fail fast, and memory is also the CPU dial.
- Use layers for shared code, and pin their compatible runtimes.
- Enable X-Ray tracing (
Tracing: Active) from the start; retrofitting tracing during an incident is not an option. - Handle errors explicitly and configure a dead-letter queue or an on-failure destination, so a poison event is visible rather than silently retried.
- Integrate with the pipeline through CodePipeline or GitHub Actions rather than deploying from a workstation.