Install
$ agentstack add skill-noah-sheldon-ai-dev-kit-aws-deployment ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ● Environment & secrets Used
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
AWS Deployment
Production AWS deployment patterns: ECS Fargate, Lambda, EC2, App Runner, infrastructure as code with CDK and Terraform, deployment strategies (blue-green, rolling, canary), auto-scaling, health checks, CloudWatch integration, and CI/CD pipeline patterns.
When to Use
- Deploying applications or services to AWS
- Writing Infrastructure as Code (CDK, Terraform, CloudFormation)
- Choosing between ECS Fargate, Lambda, EC2, or App Runner
- Implementing blue-green or rolling deployment strategies
- Configuring auto-scaling policies and health checks
- Setting up CloudWatch monitoring, alarms, and dashboards
- Building CI/CD pipelines for AWS deployments
- Migrating workloads between AWS services
Core Concepts
1. Service Selection Guide
| Service | Best For | Startup | Scaling | Cost Model | Max Concurrent | |---|---|---|---|---|---| | Lambda | Event-driven, sporadic traffic | $ECSTASKDEFINITION
- name: Deploy to ECS (rolling update)
uses: aws-actions/amazon-ecs-deploy-task-definition@v2 with: task-definition: ${{ env.ECSTASKDEFINITION }} service: ${{ env.ECSSERVICE }} cluster: ${{ env.ECSCLUSTER }} wait-for-service-stability: true wait-for-minutes: 15 # Max wait for health checks
- name: Run post-deploy smoke tests
run: | # Wait for ALB health check to pass sleep 60 # Smoke test against the service URL curl -f --retry 3 --retry-delay 10 \ https://api.myapp.com/health \ -H "Authorization: Bearer $SMOKETESTTOKEN"
### 7. CloudWatch Monitoring Dashboard
```typescript
// lib/monitoring.ts
export function createServiceDashboard(
scope: Construct,
id: string,
props: { serviceName: string; clusterName: string; loadBalancerArn: string },
): cloudwatch.Dashboard {
const dashboard = new cloudwatch.Dashboard(scope, id, {
dashboardName: `${props.serviceName}-production`,
});
// Row 1: Latency and error rate
dashboard.addWidgets(
new cloudwatch.GraphWidget({
title: "Response Time (p50, p90, p99)",
left: [
new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "TargetResponseTime",
dimensionsMap: { LoadBalancer: props.loadBalancerArn },
statistic: "p50",
period: cdk.Duration.minutes(1),
}).with({ color: cloudwatch.Color.GREEN, label: "p50" }),
new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "TargetResponseTime",
dimensionsMap: { LoadBalancer: props.loadBalancerArn },
statistic: "p90",
period: cdk.Duration.minutes(1),
}).with({ color: cloudwatch.Color.ORANGE, label: "p90" }),
new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "TargetResponseTime",
dimensionsMap: { LoadBalancer: props.loadBalancerArn },
statistic: "p99",
period: cdk.Duration.minutes(1),
}).with({ color: cloudwatch.Color.RED, label: "p99" }),
],
}),
new cloudwatch.GraphWidget({
title: "Error Rate (5xx)",
left: [
new cloudwatch.Metric({
namespace: "AWS/ApplicationELB",
metricName: "HTTPCode_Target_5XX_Count",
dimensionsMap: { LoadBalancer: props.loadBalancerArn },
statistic: "Sum",
period: cdk.Duration.minutes(1),
}),
],
}),
);
// Row 2: CPU, memory, task count
dashboard.addWidgets(
new cloudwatch.GraphWidget({
title: "ECS CPU Utilization",
left: [
new cloudwatch.Metric({
namespace: "AWS/ECS",
metricName: "CPUUtilization",
dimensionsMap: { ClusterName: props.clusterName, ServiceName: props.serviceName },
statistic: "Average",
period: cdk.Duration.minutes(1),
}),
],
}),
new cloudwatch.SingleValueWidget({
title: "Running Tasks",
metrics: [
new cloudwatch.Metric({
namespace: "AWS/ECS",
metricName: "RunningTaskCount",
dimensionsMap: { ClusterName: props.clusterName, ServiceName: props.serviceName },
statistic: "Average",
period: cdk.Duration.minutes(1),
}),
],
}),
);
return dashboard;
}
8. Health Check Endpoint
Every service MUST expose a /health endpoint. This is the gate for deployment success.
# FastAPI health check
from fastapi import FastAPI, status
from pydantic import BaseModel
import asyncpg
app = FastAPI()
class HealthStatus(BaseModel):
status: str
version: str
database: str
uptime_seconds: int
START_TIME = time.time()
@app.get("/health")
async def health():
"""Liveness + readiness check."""
db_status = "healthy"
try:
conn = await asyncpg.connect(dsn=DATABASE_URL, timeout=5)
await conn.fetchval("SELECT 1")
await conn.close()
except Exception:
db_status = "unhealthy"
return HealthStatus(
status="healthy" if db_status == "healthy" else "degraded",
version=os.getenv("APP_VERSION", "unknown"),
database=db_status,
uptime_seconds=int(time.time() - START_TIME),
)
@app.get("/ready")
async def readiness():
"""Readiness probe — fails if dependencies unavailable."""
try:
conn = await asyncpg.connect(dsn=DATABASE_URL, timeout=5)
await conn.fetchval("SELECT 1")
await conn.close()
return {"status": "ready"}
except Exception as e:
raise HTTPException(status_code=503, detail=f"Not ready: {e}")
Security Checklist
- [ ] No hardcoded secrets — use AWS Secrets Manager or SSM Parameter Store
- [ ] Least-privilege IAM roles — ECS task role has only needed permissions
- [ ] Private subnets for ECS tasks (no public IPs)
- [ ] Security groups — ALB allows 443 inbound, ECS allows ALB SG on container port only
- [ ] TLS everywhere — ALB terminates TLS, internal traffic via VPC
- [ ] ECR image scanning — enable scan-on-push
- [ ] CloudWatch Logs — all services log to CloudWatch with retention policy
- [ ] VPC flow logs — enabled for production VPCs
- [ ] Deployment approval — require manual approval for production deployments
- [ ] Rollback capability — always keep previous task definition available
Anti-Patterns
| Anti-Pattern | Risk | Fix | |---|---|---| | Deploying directly to ECS without CI | Inconsistent builds | Use CI/CD pipeline | | No health check | Bad deploys go unnoticed | /health + /ready endpoints | | deployment_minimum_healthy_percent=0 | Downtime during deploy | Set to 50+ | | Hard-coded credentials in env vars | Secret exposure | Use Secrets Manager | | No auto-scaling | Overprovisioned or crashes | CPU + request-based scaling | | No CloudWatch alarms | Incidents undetected | Alarm on errors, latency, CPU | | Single AZ deployment | AZ outage = full outage | Multi-AZ subnets | | No rollback strategy | Stuck with bad deploys | CodeDeploy with auto-rollback |
Success Checklist
- [ ] Infrastructure defined as code (CDK or Terraform)
- [ ] CI/CD pipeline builds, pushes to ECR, deploys to ECS
- [ ] Health check (
/health) and readiness (/ready) endpoints - [ ] Auto-scaling configured (CPU + request count)
- [ ] CloudWatch dashboard and alarms
- [ ] Secrets in AWS Secrets Manager (not env vars)
- [ ] IAM roles follow least-privilege
- [ ] Multi-AZ deployment
- [ ] Deployment strategy documented (rolling, blue-green, or canary)
- [ ] Rollback tested and automated
- [ ] Container image scanning enabled
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: noah-sheldon
- Source: noah-sheldon/ai-dev-kit
- License: MIT
- Homepage: https://noahsheldon.dev
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.