I want to create a SAM project encapsulated with CloudFormation. I will be using technologies like API Gateway, Lambda, Cognito, SES, and SNS. How should I handle (prod | dev) environment management in this setup? Should I create separate stacks for dev and prod and name my Lambdas and API Gateways separately for each environment? If so, what is the purpose of the stage concept in API Gateway? How can I structure this architecture properly?
When building a SAM (Serverless Application Model) project with AWS services like API Gateway, Lambda, Cognito, SES, and SNS, managing dev and prod environments effectively is crucial. Here’s how you can handle it:
It’s best to create separate CloudFormation stacks for dev and prod. This ensures isolation and prevents issues in one environment from affecting the other.
To distinguish resources, use parameterized names:
Resources:
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "my-app-${Environment}-lambda"
...
MyApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub "my-app-${Environment}-api"
...
Here, Environment is a parameter set to dev or prod.
API Gateway stages (dev, prod, etc.) allow you to configure multiple environments for a single API. However, stages don’t isolate resources like Lambda, Cognito, or databases.
For production-grade systems, stages should complement separate stacks, not replace them. You can still use stages within an environment for versioning or testing.
You can pass Parameters During Deployment:
sam deploy --stack-name my-app-dev --parameter-overrides Environment=dev
sam deploy --stack-name my-app-prod --parameter-overrides Environment=prod
Set Environment Variables for Lambda:
Resources:
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
ENV: !Ref Environment
TABLE_NAME: !Sub "my-app-${Environment}-table"
Resource Isolation for Shared Services
• Cognito: Separate User Pools for dev and prod.
• SES: Different configurations for dev and prod email sending.
• SNS: Separate topics or environment-based filtering.
Example Structure
Project structure:
├── template.yaml
├── deploy/
├──├── dev-params.json
├──└── prod-params.json
Example template.yaml:
Parameters:
Environment:
Type: String
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub "my-app-${Environment}-api"
MyLambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub "my-app-${Environment}-lambda"
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
RestApiId: !Ref MyApi
Deploy with:
sam deploy --config-file deploy/dev-params.json
sam deploy --config-file deploy/prod-params.json
You can get some free API Gateway-SAM workshops, which will help you to understand better these things : https://workshops.aws/categories/API%20Gateway