Claude Code for AWS — boto3, CDK, Lambda & CloudFormation Workflows

AWS is the world's largest cloud platform, and Claude Code dramatically accelerates infrastructure and backend work when given the right context about your account structure, IaC tooling, and resource naming conventions. This guide covers CLAUDE.md templates for AWS projects, CDK stack authoring, boto3 scripting, Lambda development, and CloudFormation debugging workflows.

AWS CLAUDE.md Template

# Project: [Your Service Name]

## AWS account structure
- Dev: 111111111111 (us-east-1)
- Staging: 222222222222 (us-east-1)
- Prod: 333333333333 (us-east-1, eu-west-1 — dual region)
- Management: 000000000000 (us-east-1) — SSO, billing, SCPs

## IaC tooling
- CDK (TypeScript, CDK v2) — all new infrastructure
- CloudFormation used for legacy stacks in cfn/
- SAM for Lambda functions in services/*/

## Naming conventions
- Resources: [project]-[service]-[resource-type]-[env] (e.g. acme-payments-table-prod)
- Lambda functions: [project]-[function-name]-[env]
- S3 buckets: [project]-[purpose]-[account-id]-[region]
- SSM Parameters: /[project]/[env]/[service]/[key]
- Tags required: Project, Environment, Owner, CostCenter

## Key commands
```bash
cdk synth                          # synthesize CloudFormation
cdk diff --profile staging         # diff against staging
cdk deploy --profile prod          # deploy (requires approval)
sam local invoke FunctionName      # local Lambda test
sam local start-api                # local API Gateway
aws cloudformation describe-stack-events --stack-name STACK_NAME --profile prod
```

## Guardrails
- Never hardcode account IDs, access keys, or secrets — use SSM Parameter Store or Secrets Manager
- All resources must have deletion protection in prod (removalPolicy: RETAIN)
- IAM: least privilege only — no wildcards (*) in Resource or Action unless justified
- S3 buckets: block all public access by default
- Lambda: always set memory size and timeout explicitly

AWS CDK Stack Workflows

New CDK TypeScript stack

claude "create a CDK TypeScript stack for a serverless API service.
Resources needed:
- Lambda function (Node.js 22, 512MB, 30s timeout) reading from a DynamoDB table
- API Gateway HTTP API (not REST API) with JWT authorizer pointing to our Cognito pool
- DynamoDB table: partition key userId (String), sort key timestamp (Number), on-demand billing
- S3 bucket for uploads: versioning enabled, lifecycle rule deleting old versions after 90d
- All resources tagged with our standard tags from CLAUDE.md
Use CDK v2 constructs. Separate environment config into stack props.
Prod stack: removalPolicy RETAIN on stateful resources."

Add monitoring and alarms

claude "add CloudWatch alarms to our CDK stack for the payments Lambda:
- Error rate alarm: >1% errors over 5min → SNS topic 'pager-duty-prod'
- Duration alarm: p99 >5000ms over 5min → SNS topic 'pager-duty-prod'
- Throttle alarm: any throttles in 5min → SNS topic 'engineering-alerts'
- DynamoDB: ConsumedWriteCapacityUnits >80% of provisioned → SNS alert
Add a CloudWatch dashboard showing all four metrics side by side."

VPC + private subnet pattern

claude "add a VPC to the CDK stack with:
- 3 AZs (us-east-1a/b/c)
- Public subnets for ALB (one per AZ)
- Private subnets for Lambda + ECS (one per AZ)
- Isolated subnets for RDS (one per AZ)
- NAT Gateway in each AZ (3 total, for HA)
- VPC Flow Logs to CloudWatch log group
- Security groups: alb-sg (80/443 from 0.0.0.0/0), app-sg (8080 from alb-sg only), db-sg (5432 from app-sg only)"

Lambda Function Workflows

SQS-triggered Python Lambda

claude "write a Python 3.12 Lambda handler triggered by SQS.
The function processes order events from queue 'orders-prod'.
Each message is JSON: {orderId, userId, items: [{sku, qty, price}], totalAmount}.
It should:
1. Validate the message schema (raise ValueError for malformed messages — SQS DLQ handles retries)
2. Write a record to DynamoDB table 'orders-prod' (use boto3 resource, not client)
3. Send a confirmation email via SES to the userId's email (look up in 'users-prod' table)
4. Log structured JSON (orderId, userId, processingTimeMs) to CloudWatch
Use batch item failure reporting (SQS partial batch response).
Initialize boto3 clients outside the handler for connection reuse."

API Gateway + Lambda (Python)

claude "write a Python Lambda handler for API Gateway HTTP API (payload format 2.0).
Endpoints:
- GET /items/{itemId} — fetch from DynamoDB, return 200 or 404
- POST /items — validate body, write to DynamoDB, return 201 with Location header
- DELETE /items/{itemId} — soft-delete (set deletedAt field), return 204
Use a response helper to set CORS headers (origin: https://app.example.com).
Add structured JSON logging with requestId and route.
Raise HTTPError(status, message) for known errors; catch all others and return 500."

boto3 Scripting Patterns

TaskClaude Code promptKey patterns
Paginated S3 list "write a boto3 script to list all objects in s3://my-bucket/prefix/ older than 30 days and print their keys and sizes" Use paginator — never list_objects_v2 without pagination
DynamoDB scan with filter "scan orders table for all items where status='PENDING' and createdAt < 7 days ago, paginate correctly" Use paginator; avoid scan on large tables — add query index hint
Cross-account assume role "write a boto3 helper that assumes role arn:aws:iam::ACCOUNT_ID:role/ROLE_NAME and returns a session valid for 1h" STS AssumeRole; cache credentials until 5min before expiry
EC2 tag-based inventory "list all EC2 instances across all regions tagged Environment=prod, return instanceId/type/state/privateIp" Iterate regions from ec2.describe_regions(); paginate describe_instances
Secrets Manager rotation "write a Lambda rotation function for a Secrets Manager secret storing RDS credentials (PostgreSQL)" Handle all 4 rotation steps: createSecret, setSecret, testSecret, finishSecret
CloudWatch log export "export all CloudWatch log group '/aws/lambda/payments-prod' entries from the last 7 days to S3 bucket 'log-archive-prod'" create_export_task is async — poll until complete; handle ConcurrentTaskException

CloudFormation Debugging

Diagnose a failed stack

claude "my CloudFormation stack 'acme-payments-prod' failed during UPDATE_ROLLBACK.
Here are the stack events:
[paste output of: aws cloudformation describe-stack-events \
  --stack-name acme-payments-prod \
  --query 'StackEvents[?ResourceStatus==`CREATE_FAILED` || ResourceStatus==`UPDATE_FAILED`]' \
  --output table]
Diagnose the root cause and show the corrected template section."
ErrorCommon causeFix prompt
Resource handler returned message: "User: ... is not authorized to perform: iam:PassRole" Lambda/ECS execution role missing iam:PassRole on the task role "add iam:PassRole permission for LambdaExecutionRole to pass TaskRole"
Export STACK_NAME:ExportName cannot be deleted as it is in use by STACK2 Cross-stack export used before deleting consumer "how do I safely remove this cross-stack export? show delete order"
Circular dependency between resources Two resources reference each other directly "break the circular dependency between [ResourceA] and [ResourceB], use a separate stack or parameter"
ROLLBACK_COMPLETE — stack stuck Failed creation that can't be auto-deleted "what manual cleanup is needed to delete a ROLLBACK_COMPLETE stack with these resources?"

SAM Local Development

claude "create a SAM template.yaml for a REST API with:
- GET /products — Lambda backed, no auth
- POST /orders — Lambda backed, Cognito JWT authorizer (pool ID: us-east-1_XXXXX)
- SQS queue 'order-events' that the POST Lambda writes to
- Both Lambdas share a DynamoDB table defined in the template
- Local dev: sam local start-api should work without AWS credentials (use DynamoDB local on port 8000)
Include a Makefile with targets: build, local, test, deploy-staging, deploy-prod."

5 Tips for AWS + Claude Code

  1. Paste the IAM policy simulator output or an AccessDenied error message directly into Claude Code — it generates the exact missing IAM statement (Action + Resource ARN) without over-provisioning.
  2. Tell Claude your CDK bootstrap version (cdk bootstrap --show-template | grep Version). This matters for cross-account deployments and asset publishing permissions.
  3. When scripting boto3, always say "handle ThrottlingException with exponential backoff using tenacity or botocore retry config". Claude defaults to correct retry logic only when prompted.
  4. For Lambda, tell Claude your function's VPC config and whether it uses Provisioned Concurrency. Both affect cold-start optimization choices (connection pooling, init code placement).
  5. Use aws cloudformation validate-template as a CDK PostToolUse hook — Claude sees validation errors and self-corrects before you run cdk deploy.