Funciones Serverless en TypeScript: nivel avanzado en AWS Lambda
\n\nLa arquitectura serverless se ha convertido en el estándar de facto para construir aplicaciones escalables y rentables. AWS Lambda es uno de los servicios más populares para implementar funciones sin servidor. Si ya domina la sintaxis básica y los disparadores (API Gateway, S3, DynamoDB), es hora de pasar a técnicas avanzadas. En este artículo, exploraremos aspectos clave del desarrollo profesional de funciones Lambda en TypeScript: desde la optimización del arranque en frío hasta la integración con VPC y el uso de patrones complejos.
\n\n1. Optimización del arranque en frío y gestión de memoria
\n\nEl arranque en frío (cold start) es el principal enemigo del rendimiento de las aplicaciones serverless. En TypeScript, este problema se agrava con la etapa de compilación. Veamos tres métodos principales para combatirlo.
\n\n1.1. Reducción del tamaño del paquete de despliegue
\nUtilice esbuild para la compilación en lugar del estándar tsc. Realiza tree-shaking y minificación, lo que reduce el tamaño del bundle entre 5 y 10 veces. Ejemplo de configuración para serverless.yml:
plugins:\n - serverless-esbuild\ncustom:\n esbuild:\n bundle: true\n minify: true\n sourcemap: false\n target: 'node18'\n exclude: ['aws-sdk'] # SDK ya está en el entorno Lambda\n\n1.2. Uso de Provisioned Concurrency
\nPara funciones críticas en cuanto a latencia (por ejemplo, las que procesan solicitudes API), configure Provisioned Concurrency. Esto mantiene una cantidad determinada de contenedores "calientes" ejecutándose constantemente:
\n\nfunctions:\n apiHandler:\n handler: src/handler.apiHandler\n provisionedConcurrency: 5 # Siempre 5 instancias listas\n\n1.3. Optimización de importaciones y código
\nEvite bibliotecas "pesadas" dentro de la función. Por ejemplo, en lugar de importar todo aws-sdk v3, importe solo los clientes necesarios:
// Mal: import * as AWS from 'aws-sdk';\n// Bien:\nimport { DynamoDBClient } from '@aws-sdk/client-dynamodb';\nimport { DynamoDBDocumentClient } from '@aws-sdk/lib-dynamodb';\n\n2. Trabajo con Lambda Layers y dependencias
\n\nLambda Layers permiten extraer código común y dependencias (por ejemplo, ORM, validadores) fuera de la función. Esto acelera el despliegue y reduce el tamaño de cada paquete individual.
\n\n2.1. Creación de una capa con utilidades comunes
\nLa estructura del proyecto podría verse así:
\n\nproject/\n├── layers/\n│ └── common/\n│ └── nodejs/\n│ ├── package.json\n│ └── node_modules/\n├── functions/\n│ ├── createUser.ts\n│ └── getUser.ts\n└── serverless.yml\n\nEn serverless.yml conectamos la capa:
layers:\n commonLibs:\n path: layers/common\n compatibleRuntimes:\n - nodejs18.x\nfunctions:\n createUser:\n handler: functions/createUser.handler\n layers:\n - { Ref: CommonLibsLambdaLayer }\n\n2.2. Tipado para capas
\nPara que TypeScript "vea" los tipos de la capa, cree un tsconfig.json con rutas:
{\n "compilerOptions": {\n "paths": {\n "@common/*": ["layers/common/nodejs/*"]\n }\n }\n}\n\nAhora en la función se puede escribir:
\nimport { validateEmail } from '@common/validators';\n\n3. Trabajo con VPC y seguridad
\n\nLas funciones Lambda que operan dentro de una VPC pierden el acceso a Internet público (a menos que se configure un NAT Gateway). Esto es crítico para conectarse a RDS, ElastiCache o API privadas.
\n\n3.1. Configuración de Lambda en VPC
\nConfiguración a través de serverless.yml:
provider:\n vpc:\n securityGroupIds:\n - sg-12345\n subnetIds:\n - subnet-abc\n - subnet-def\n\nfunctions:\n dbHandler:\n handler: src/db.handler\n vpc: true # hereda la configuración del proveedor\n\n3.2. Patrón "Thin Handler" para conexiones
\nLe