AgentSkillsCN

aws-skills

使用 CDK 模式、无服务器架构、Lambda、API Gateway、DynamoDB、S3 以及基础设施最佳实践,在 AWS 上进行开发与部署。

SKILL.md
--- frontmatter
name: aws-skills
description: AWS development with CDK patterns, serverless architecture, Lambda, API Gateway, DynamoDB, S3, and infrastructure best practices. Use when building or deploying to AWS.

AWS Development Skills

When to Use This Skill

  • Building serverless applications on AWS
  • Writing AWS CDK infrastructure code
  • Configuring Lambda, API Gateway, DynamoDB, S3
  • Setting up CI/CD pipelines with AWS
  • Optimizing AWS costs and performance

AWS CDK Patterns

Project Structure

code
my-service/
├── bin/
│   └── app.ts           # CDK app entry point
├── lib/
│   ├── stacks/          # Stack definitions
│   │   ├── api-stack.ts
│   │   └── database-stack.ts
│   └── constructs/      # Reusable constructs
├── lambda/              # Lambda function code
│   └── handlers/
├── test/                # Tests
└── cdk.json

Stack Pattern

typescript
import * as cdk from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';

export class ApiStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Lambda function
    const handler = new lambda.Function(this, 'Handler', {
      runtime: lambda.Runtime.NODEJS_20_X,
      code: lambda.Code.fromAsset('lambda'),
      handler: 'index.handler',
      memorySize: 256,
      timeout: cdk.Duration.seconds(30),
      environment: {
        NODE_ENV: 'production',
      },
    });

    // API Gateway
    const api = new apigateway.RestApi(this, 'Api', {
      restApiName: 'My Service',
      deployOptions: {
        stageName: 'prod',
      },
    });

    api.root.addMethod('GET', new apigateway.LambdaIntegration(handler));
  }
}

Lambda Best Practices

Handler Pattern

typescript
// lambda/handlers/api.ts
import { APIGatewayProxyHandler } from 'aws-lambda';

// Initialize outside handler for connection reuse
const db = initDatabase();

export const handler: APIGatewayProxyHandler = async (event) => {
  try {
    const body = JSON.parse(event.body || '{}');

    const result = await processRequest(body);

    return {
      statusCode: 200,
      headers: {
        'Content-Type': 'application/json',
        'Access-Control-Allow-Origin': '*',
      },
      body: JSON.stringify(result),
    };
  } catch (error) {
    console.error('Error:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Internal Server Error' }),
    };
  }
};

Performance Optimization

typescript
// Use provisioned concurrency for critical paths
const fn = new lambda.Function(this, 'CriticalFn', {
  // ... config
});

const version = fn.currentVersion;
const alias = new lambda.Alias(this, 'ProdAlias', {
  aliasName: 'prod',
  version,
  provisionedConcurrentExecutions: 5,
});

Cold Start Reduction:

  • Keep deployment package small
  • Use layers for dependencies
  • Initialize connections outside handler
  • Use ARM64 architecture (Graviton2)

DynamoDB Patterns

Single-Table Design

typescript
// Table with GSI for access patterns
const table = new dynamodb.Table(this, 'Table', {
  partitionKey: { name: 'PK', type: dynamodb.AttributeType.STRING },
  sortKey: { name: 'SK', type: dynamodb.AttributeType.STRING },
  billingMode: dynamodb.BillingMode.PAY_PER_REQUEST,
});

table.addGlobalSecondaryIndex({
  indexName: 'GSI1',
  partitionKey: { name: 'GSI1PK', type: dynamodb.AttributeType.STRING },
  sortKey: { name: 'GSI1SK', type: dynamodb.AttributeType.STRING },
});

Access Patterns

typescript
// User by ID: PK=USER#123, SK=PROFILE
// User orders: PK=USER#123, SK=ORDER#timestamp
// Order by ID: GSI1PK=ORDER#456, GSI1SK=ORDER#456

const params = {
  TableName: 'MyTable',
  KeyConditionExpression: 'PK = :pk AND begins_with(SK, :sk)',
  ExpressionAttributeValues: {
    ':pk': 'USER#123',
    ':sk': 'ORDER#',
  },
};

S3 Best Practices

typescript
const bucket = new s3.Bucket(this, 'Bucket', {
  encryption: s3.BucketEncryption.S3_MANAGED,
  blockPublicAccess: s3.BlockPublicAccess.BLOCK_ALL,
  versioned: true,
  lifecycleRules: [
    {
      transitions: [
        {
          storageClass: s3.StorageClass.INTELLIGENT_TIERING,
          transitionAfter: cdk.Duration.days(30),
        },
      ],
    },
  ],
});

API Gateway Patterns

REST API with Validation

typescript
const api = new apigateway.RestApi(this, 'Api', {
  restApiName: 'Service',
  deployOptions: {
    throttlingRateLimit: 1000,
    throttlingBurstLimit: 2000,
  },
});

// Request validation
const model = api.addModel('CreateItemModel', {
  contentType: 'application/json',
  schema: {
    type: apigateway.JsonSchemaType.OBJECT,
    required: ['name'],
    properties: {
      name: { type: apigateway.JsonSchemaType.STRING },
      price: { type: apigateway.JsonSchemaType.NUMBER },
    },
  },
});

const items = api.root.addResource('items');
items.addMethod('POST', integration, {
  requestModels: { 'application/json': model },
  requestValidatorOptions: {
    validateRequestBody: true,
  },
});

IAM Best Practices

typescript
// Least privilege
handler.addToRolePolicy(new iam.PolicyStatement({
  effect: iam.Effect.ALLOW,
  actions: ['dynamodb:GetItem', 'dynamodb:PutItem'],
  resources: [table.tableArn],
  conditions: {
    'ForAllValues:StringEquals': {
      'dynamodb:LeadingKeys': ['${aws:userid}'],
    },
  },
}));

Cost Optimization

ServiceOptimization
LambdaRight-size memory, use Graviton2
DynamoDBOn-demand for variable, provisioned for steady
S3Intelligent tiering, lifecycle rules
API GatewayUse HTTP APIs when possible (cheaper)
CloudWatchSet log retention periods

Security Checklist

  • Encryption at rest enabled
  • Encryption in transit (HTTPS only)
  • VPC for sensitive workloads
  • Secrets in Secrets Manager (not env vars)
  • IAM roles with least privilege
  • CloudTrail enabled
  • GuardDuty enabled
  • Regular security assessments