AgentStack
SKILL verified MIT Self-run

Aws Serverless

skill-eliecer2000-kiro-bootstrap-aws-serverless · by eliecer2000

Building production-ready serverless applications on AWS. Use when working with Lambda, API Gateway, SQS, SNS, DynamoDB Streams, SAM/CDK deployment or optimizing cold starts.

No reviews yet
0 installs
23 views
0.0% view→install

Install

$ agentstack add skill-eliecer2000-kiro-bootstrap-aws-serverless

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

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

Are you the author of Aws Serverless? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

AWS Serverless

Skill para construir aplicaciones serverless production-ready en AWS. Cubre Lambda functions, API Gateway (REST/HTTP/WebSocket), arquitecturas event-driven con SQS/SNS/DynamoDB Streams, modelado DynamoDB, despliegue con SAM/CDK, y optimización de cold starts.

Principios fundamentales

  • Serverless-first: diseñar para ejecución efímera, stateless y event-driven.
  • Cada Lambda = una responsabilidad. No monolitos Lambda.
  • Inicializar clientes AWS fuera del handler (reutilización en warm starts).
  • Usar partial batch failure reporting en SQS/Kinesis/DynamoDB Streams.
  • Dead Letter Queues (DLQ) obligatorias en toda cola y suscripción.
  • Idempotencia en todo handler que procese eventos (at-least-once delivery).
  • Observabilidad desde el día 1: structured logging, tracing, métricas custom.

Patrones de Lambda Handler

Node.js Handler (TypeScript)

import { Logger } from '@aws-lambda-powertools/logger';
import { Tracer } from '@aws-lambda-powertools/tracer';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, GetCommand } from '@aws-sdk/lib-dynamodb';
import type { APIGatewayProxyEventV2, APIGatewayProxyResultV2 } from 'aws-lambda';

const logger = new Logger({ serviceName: 'mi-servicio' });
const tracer = new Tracer({ serviceName: 'mi-servicio' });

// Inicializar fuera del handler (warm start reuse)
const client = tracer.captureAWSv3Client(new DynamoDBClient({}));
const docClient = DynamoDBDocumentClient.from(client);
const TABLE_NAME = process.env.TABLE_NAME!;

export const handler = async (
  event: APIGatewayProxyEventV2
): Promise => {
  try {
    const body = typeof event.body === 'string' ? JSON.parse(event.body) : event.body;
    const result = await processRequest(body);

    return {
      statusCode: 200,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(result),
    };
  } catch (error) {
    logger.error('Error processing request', { error });
    return {
      statusCode: 500,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ error: 'Internal server error' }),
    };
  }
};

Python Handler

import json
import os
import logging
import boto3
from aws_lambda_powertools import Logger, Tracer, Metrics
from aws_lambda_powertools.utilities.typing import LambdaContext

logger = Logger(service="mi-servicio")
tracer = Tracer(service="mi-servicio")
metrics = Metrics(namespace="MiApp", service="mi-servicio")

# Inicializar fuera del handler
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table(os.environ['TABLE_NAME'])

@logger.inject_lambda_context
@tracer.capture_lambda_handler
@metrics.log_metrics(capture_cold_start_metric=True)
def handler(event: dict, context: LambdaContext) -> dict:
    try:
        body = json.loads(event.get('body', '{}'))
        result = process_request(body)
        return {
            'statusCode': 200,
            'headers': {'Content-Type': 'application/json'},
            'body': json.dumps(result)
        }
    except Exception as e:
        logger.exception("Error processing request")
        return {
            'statusCode': 500,
            'body': json.dumps({'error': 'Internal server error'})
        }

API Gateway Integration

HTTP API (recomendado para casos simples)

# template.yaml (SAM)
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs20.x
    Timeout: 30
    MemorySize: 256
    Environment:
      Variables:
        TABLE_NAME: !Ref ItemsTable
        POWERTOOLS_SERVICE_NAME: mi-servicio

Resources:
  HttpApi:
    Type: AWS::Serverless::HttpApi
    Properties:
      StageName: prod
      CorsConfiguration:
        AllowOrigins: ["*"]
        AllowMethods: [GET, POST, PUT, DELETE]
        AllowHeaders: ["*"]

  GetItemFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/get.handler
      Events:
        GetItem:
          Type: HttpApi
          Properties:
            ApiId: !Ref HttpApi
            Path: /items/{id}
            Method: GET
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref ItemsTable

  CreateItemFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/create.handler
      Events:
        CreateItem:
          Type: HttpApi
          Properties:
            ApiId: !Ref HttpApi
            Path: /items
            Method: POST
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref ItemsTable

  ItemsTable:
    Type: AWS::DynamoDB::Table
    Properties:
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
      BillingMode: PAY_PER_REQUEST

REST API (cuando se necesita validación, throttling, API keys)

  RestApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Auth:
        DefaultAuthorizer: CognitoAuthorizer
        Authorizers:
          CognitoAuthorizer:
            UserPoolArn: !GetAtt UserPool.Arn
      Models:
        CreateItemModel:
          type: object
          required: [name, price]
          properties:
            name: { type: string, minLength: 1 }
            price: { type: number, minimum: 0 }

Patrones Event-Driven

SQS con Partial Batch Failure

Resources:
  ProcessorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/processor.handler
      Events:
        SQSEvent:
          Type: SQS
          Properties:
            Queue: !GetAtt ProcessingQueue.Arn
            BatchSize: 10
            FunctionResponseTypes:
              - ReportBatchItemFailures

  ProcessingQueue:
    Type: AWS::SQS::Queue
    Properties:
      VisibilityTimeout: 180  # 6x Lambda timeout
      RedrivePolicy:
        deadLetterTargetArn: !GetAtt DeadLetterQueue.Arn
        maxReceiveCount: 3

  DeadLetterQueue:
    Type: AWS::SQS::Queue
    Properties:
      MessageRetentionPeriod: 1209600  # 14 días
// Handler con partial batch failure reporting
import type { SQSEvent, SQSBatchResponse } from 'aws-lambda';

export const handler = async (event: SQSEvent): Promise => {
  const batchItemFailures: SQSBatchResponse['batchItemFailures'] = [];

  for (const record of event.Records) {
    try {
      const body = JSON.parse(record.body);
      await processMessage(body);
    } catch (error) {
      console.error(`Failed message ${record.messageId}:`, error);
      batchItemFailures.push({ itemIdentifier: record.messageId });
    }
  }

  return { batchItemFailures };
};

SNS Fan-Out

  OrderTopic:
    Type: AWS::SNS::Topic

  EmailNotificationFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/email.handler
      Events:
        SNSEvent:
          Type: SNS
          Properties:
            Topic: !Ref OrderTopic
            FilterPolicy:
              type: [order_confirmed]

  InventoryUpdateFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/inventory.handler
      Events:
        SNSEvent:
          Type: SNS
          Properties:
            Topic: !Ref OrderTopic

DynamoDB Streams

  StreamProcessorFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/stream.handler
      Events:
        DDBStream:
          Type: DynamoDB
          Properties:
            Stream: !GetAtt OrdersTable.StreamArn
            StartingPosition: TRIM_HORIZON
            BatchSize: 100
            MaximumBatchingWindowInSeconds: 5
            FunctionResponseTypes:
              - ReportBatchItemFailures
            FilterCriteria:
              Filters:
                - Pattern: '{"eventName": ["INSERT", "MODIFY"]}'

Step Functions (orquestación)

  OrderStateMachine:
    Type: AWS::Serverless::StateMachine
    Properties:
      DefinitionUri: statemachine/order.asl.json
      Policies:
        - LambdaInvokePolicy:
            FunctionName: !Ref ValidateOrderFunction
        - LambdaInvokePolicy:
            FunctionName: !Ref ProcessPaymentFunction
        - DynamoDBCrudPolicy:
            TableName: !Ref OrdersTable

Optimización de Cold Starts

Estrategias generales

| Estrategia | Impacto | Complejidad | |---|---|---| | Minimizar bundle size | Alto | Bajo | | Lazy loading de dependencias | Medio | Bajo | | Inicializar clientes fuera del handler | Alto | Bajo | | Aumentar memoria (más CPU) | Medio | Bajo | | Provisioned Concurrency | Alto | Medio | | SnapStart (Java) | Alto | Bajo | | Evitar VPC si no es necesario | Alto | Bajo |

Node.js específico

// ✅ Lazy loading para dependencias pesadas
let heavyLib: typeof import('heavy-lib') | undefined;

const getHeavyLib = async () => {
  if (!heavyLib) {
    heavyLib = await import('heavy-lib');
  }
  return heavyLib;
};

// ✅ Tree shaking: importar solo lo necesario
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';  // ✅
// import AWS from 'aws-sdk';  // ❌ SDK v2 completo

Python específico

# ✅ Lazy loading
_s3_client = None

def get_s3_client():
    global _s3_client
    if _s3_client is None:
        _s3_client = boto3.client('s3')
    return _s3_client

Configuración de memoria

# Usar AWS Lambda Power Tuning para encontrar el sweet spot
# https://github.com/alexcasalboni/aws-lambda-power-tuning
sam deploy --template-file power-tuning.yaml

Seguridad Serverless

  • IAM: least privilege por función. Usar SAM policy templates.
  • No hardcodear secretos. Usar SSM Parameter Store o Secrets Manager.
  • Validar todo input del evento.
  • CORS restrictivo en producción (no *).
  • API keys + usage plans para rate limiting en REST API.
  • Cognito o Lambda authorizers para autenticación.

Anti-patrones

  • ❌ Lambda monolítico con múltiples responsabilidades.
  • ❌ Dependencias pesadas que inflan el bundle (SDK v2 completo, ORM pesados).
  • ❌ Crear clientes AWS dentro del handler (nuevo cliente por invocación).
  • ❌ No usar DLQ en colas SQS ni suscripciones SNS.
  • ❌ Ignorar partial batch failure reporting (reprocesar todo el batch).
  • ❌ Timeout de Lambda > VisibilityTimeout de SQS (mensajes duplicados).
  • ❌ Llamadas síncronas en cadena entre Lambdas (usar Step Functions).
  • ❌ VPC sin necesidad real (agrega latencia al cold start).
  • console.log sin estructura (imposible de filtrar en CloudWatch Insights).
  • ❌ No tener idempotencia en handlers event-driven.

Checklist de revisión Serverless

  • [ ] Cada Lambda tiene una sola responsabilidad.
  • [ ] Clientes AWS inicializados fuera del handler.
  • [ ] Partial batch failure reporting habilitado en SQS/Kinesis/Streams.
  • [ ] DLQ configurada en todas las colas y suscripciones.
  • [ ] Idempotencia implementada donde aplica.
  • [ ] Structured logging con Powertools.
  • [ ] Tracing activo (X-Ray o Powertools Tracer).
  • [ ] IAM least privilege por función.
  • [ ] Input validado en cada handler.
  • [ ] Cold start medido y optimizado.
  • [ ] Timeout y memoria configurados según carga real.
  • [ ] Tests unitarios y de integración.

Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.