If you’ve used AWS SAM long enough, you are probably familiar with this workflow:
sam init
sam build
sam deploy“Nice! Everything works.”
A few weeks later…
“Why is everything deploying everywhere and why do I always have #to run cli commands to deploy new stuff?”
This is one of the most common issues I see with teams adopting AWS SAM for production.
SAM makes it easy to start, but you must implement customization beyond what is written in AWS documentation to make it scale safely.
This article shows why you should not rely blindly on the auto-generated SAM GitHub Actions pipeline, and how to evolve it into environment-specific pipelines with proper tagging, automation, and control as well as some notable gotchas while using AWS SAM
This article assumes you are familiar with building a CI/CD pipeline for AWS SAM
Quick Refresher: What AWS SAM Actually Is
AWS SAM (Serverless Application Model) is:
- An extension of AWS CloudFormation
- Optimized specifically for serverless workloads
- Focused on Lambda, API Gateway, DynamoDB, SQS, SNS, etc.
- Backed by CloudFormation under the hood
If you know CloudFormation, SAM feels familiar — just simpler and faster for serverless.
And yes, SAM supports OIDC authentication with GitHub Actions by default, which is already best practice (no access keys stored in GitHub secrets 👏).
The Problem with the Default SAM Pipeline
When you select 1 - AWS Quick Start Pipeline Templates after running
sam pipeline init --bootstrap
SAM allows you to generate a single pipeline for your choice of CI/CD system that provides this default setup:
- Dev and prod deploy from the same pipeline without much specific environment or branch control
- Focuses on speed not operational safety and scaling
This works for demos - not best for real world environments
The Better Approach: Environment-Specific Pipelines
Instead of the default pipeline.yaml, create multiple pipelines
To do this, copy content of default pipeline.yaml into the environment or stage specific pipeline and modify to keep only environment specific configurations and remove all others.
Example in the prod.yaml, you remove all development and test related resources and steps
By default, sam pipeline init allows configuration for only 2 environments or stages, to create a 3rd stage or environment for testing or staging;
Simply copy and run one of the auto generated cloudformation template in the 3rd account or region to create the supporting resources for that environment
Then update the relevant pipeline.yaml and pipelineconfig.toml in the project codebase
After creating all custom pipelines, delete the default `pipeline.yaml' file.
Finally, your
.github/workflows/should be looking like this
.github/workflows/
├── dev.yaml
├── test.yaml
└── prod.yaml
This ensures that, each pipeline
- Triggers and deploy to a similarly named github branch or environment
- Uses its own configuration
- Applies environment / stage specific tags
Example: Branch-Based Deployment
yaml
on:
push:
branches:
- dev
yaml
on:
push:
branches:
- test
yaml
on:
push:
branches:
- main
Modifying `samconfig.toml for easier ci/cd pipeline setup
Sam auto generates samconfig.toml when you start a new sam project, it contains configuration of how sam deploys your resources.
Default samconfig.toml
version = 0.1
[default.global.parameters]
stack_name = "sam-article-project"
[default.build.parameters]
cached = true
parallel = true
[default.validate.parameters]
lint = true
[default.deploy.parameters]
capabilities = "CAPABILITY_IAM" #must be changed
confirm_changeset = true # must be removed
resolve_s3 = true # remove # must be removed
[default.package.parameters] # must be removed
resolve_s3 = true # must be removed
[default.sync.parameters]
watch = true
[default.local_start_api.parameters]
warm_containers = "EAGER"
[default.local_start_lambda.parameters]
warm_containers = "EAGER"
This default configurations throws error when you configure a ci/cd pipeline for github actions to deploy resources because,
The following default configuration values are incompatible with ci/cd pipelines and lead to errors:
confirm_changeset = true causes cloudformation to require manually confirm cloudformation stack changes deploying, which is not possible in when deploying based on a predefined pipeline. So remove that configuration
resolve_s3 = true remove this config because s3 artifact buckets are precreated and don't need to be recreated during deployment
Another key change to make in your various custom or default pipelines as well as samconfig.toml
Change
--capabilities CAPABILITY_IAM
to
--capabilities CAPABILITY_NAMED_IAM
This is because sam needs permission when creating explicitly named resources such as buckets , roles etc.
So your final samconfig.toml should be looking like this:
Ci/Cd optimized samconfig.toml
version = 0.1
[default.global.parameters]
stack_name = "sam-article-project"
[default.build.parameters]
cached = true
parallel = true
[default.validate.parameters]
lint = true
[default.deploy.parameters]
capabilities = "CAPABILITY_NAMED_IAM"
[default.sync.parameters]
watch = true
[default.local_start_api.parameters]
warm_containers = "EAGER"
[default.local_start_lambda.parameters]
warm_containers = "EAGER"
Top comments (0)