# CI/CD > Aliases, versions, traffic shifting, blue/green. Plain CLI → SAM → CDK → Terraform. ## Versions and aliases **Versions** are immutable snapshots of a function's code and configuration. When you publish a version (`aws lambda publish-version`), AWS creates an immutable ARN like `arn:…:function:my-fn:7`. `$LATEST` is the only mutable version — always reflects the most recent code upload. **Aliases** are named pointers to a version. `prod` might point to version 7; `staging` might point to version 8. Event source mappings, API Gateway integrations, and Step Functions tasks should target aliases, not version ARNs — this decouples deployment (publishing a new version) from promotion (updating the alias). ## Traffic shifting (blue/green) An alias can split traffic across two versions with weighted routing: ```bash aws lambda update-alias \ --function-name my-fn \ --name prod \ --function-version 8 \ --routing-config AdditionalVersionWeights={"7"=0.9} # result: 10% of prod traffic goes to v8, 90% still to v7 ``` Start at 10% canary, watch error rates in CloudWatch, shift to 50%, then 100%. Rollback is instant: point the alias back to the stable version. No instance drain, no connection draining — Lambda is stateless, cutover is atomic. ## CodeDeploy integration SAM and CDK can wire up CodeDeploy for automatic traffic shifting with automatic rollback on CloudWatch alarms. You declare the deployment preference in the template: ```yaml # SAM template.yaml DeploymentPreference: Type: Canary10Percent5Minutes # 10% for 5 min, then 100% Alarms: - !Ref ErrorRateAlarm # rolls back if alarm triggers ``` CodeDeploy manages the alias weight changes and calls the rollback if the alarm fires — fully automated blue/green without manual traffic management. ## Deployment tooling progression | Tool | Good for | Caveats | |------|----------|---------| | **AWS CLI / SDK** | One-off deployments, scripting, deep control | Verbose; no state management; drift-prone at scale | | **SAM (CloudFormation extension)** | Lambda-first projects; built-in local testing; CodeDeploy integration | CloudFormation speed; YAML verbosity; AWS-only | | **CDK** | Complex infra in TypeScript/Python; reusable constructs; type safety | Still compiles to CloudFormation; learning curve; bootstrapping required | | **Terraform (AWS provider)** | Multi-cloud orgs; large existing Terraform estate; strong community modules | No built-in Lambda local testing; plan/apply cycle slower than SAM deploy | | **Serverless Framework** | Multi-cloud serverless; plugin ecosystem | V3 → V4 became paid for teams; community plugins vary in quality | ## CI pipeline skeleton ```yaml # GitHub Actions example jobs: deploy: steps: - uses: actions/checkout@v4 - name: Build zip run: | docker run --rm -v $PWD:/var/task \ public.ecr.aws/lambda/python:3.13 \ pip install -r requirements.txt -t package/ cd package && zip -r ../function.zip . && cd .. zip function.zip lambda_function.py - name: Deploy run: | aws lambda update-function-code \ --function-name my-fn --zip-file fileb://function.zip aws lambda wait function-updated --function-name my-fn aws lambda publish-version --function-name my-fn aws lambda update-alias --function-name my-fn \ --name prod --function-version $VERSION ``` The `wait function-updated` call is important — `update-function-code` is asynchronous and `publish-version` must wait for it to complete.