amazon-web-servicesaws-cloudformationaws-api-gateway

How to manage dev and prod environments in a SAM project with CloudFormation Stacks, API Gateway, Lambda, and other AWS services?


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?


Solution

  • 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:

    1. Separate Stacks for Isolation

    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.

    1. What About API Gateway Stages?

    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.

    1. Deploying Environment-Specific Resources

    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"
    
    1. 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.

    2. 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