Lambda
AWS Lambda ejecuta manejadores de Python sin necesidad de administrar servidores. boto3 te permite invocar funciones, publicar versiones y conectar automatización en torno a despliegues, manteniendo el código de la función en tu repositorio.
Receta
import json
import boto3
client = boto3.client("lambda")
resp = client.invoke(
FunctionName="process-order",
InvocationType="RequestResponse",
Payload=json.dumps({"order_id": "ord_123"}),
)
print(resp["StatusCode"], resp["Payload"].read())Cuándo usar esto:
- Tareas basadas en eventos (S3, SQS, EventBridge)
- Cargas de trabajo infrecuentes donde los servidores siempre activos desperdician dinero
- Expansión asíncrona (fan-out) con
InvocationType="Event" - Código de pegamento (Glue code) entre servicios de AWS administrados
Ejemplo de Trabajo
Actualización de metadatos de artefactos, invocación síncrona e invocación asíncrona con manejo de errores.
import json
import logging
import boto3
from botocore.exceptions import ClientError
log = logging.getLogger(__name__)
lambda_client = boto3.client("lambda")
def invoke_sync(function_name: str, payload: dict) -> dict:
try:
resp = lambda_client.invoke(
FunctionName=function_name,
InvocationType="RequestResponse",
Payload=json.dumps(payload).encode(),
)
except ClientError as exc:
log.error("la invocación falló: %s", exc.response["Error"]["Code"])
raise
raw = resp["Payload"].read()
return json.loads(raw or b"{}")
def invoke_async(function_name: str, payload: dict) -> int:
resp = lambda_client.invoke(
FunctionName=function_name,
InvocationType="Event",
Payload=json.dumps(payload).encode(),
)
return resp["StatusCode"]
if __name__ == "__main__":
result = invoke_sync("demo-python-fn", {"action": "ping"})
print(result)
status = invoke_async("demo-python-fn", {"action": "enqueue"})
print("estado asíncrono", status)Lo que esto demuestra:
RequestResponseespera el retorno del manejador;Eventes "dispara y olvida"- El Payload debe ser bytes JSON para eventos estructurados
- Los códigos de
ClientErrorincluyenResourceNotFoundException,TooManyRequestsException
Inmersión Profunda
Cómo Funciona
- Sube un archivo zip/imagen de contenedor a Lambda; la cadena del manejador apunta a
módulo.función - El arranque en frío (cold start) carga el runtime de Python y las importaciones; reutiliza clientes fuera del manejador
- Los límites de concurrencia y la concurrencia reservada protegen los sistemas descendentes
- Las versiones y los alias (
prod) permiten despliegues seguros
Notas de Empaquetado
| Enfoque | Pros |
|---|---|
| Zip + capas (layers) | Separación simple de dependencias |
| Imagen de contenedor | Dependencias pesadas (librerías de ML) |
| SAR / IaC | Despliegues repetibles |
Notas de Python
# handler.py - crea clientes boto3 fuera del manejador
import boto3
s3 = boto3.client("s3")
def handler(event, context):
return {"ok": True, "remaining_ms": context.get_remaining_time_in_millis()}Errores Comunes
- Crear un cliente boto3 por invocación - ralentiza los arranques en frío/tibios. Solución: reutilización del cliente a nivel de módulo.
- Paquetes de despliegue enormes - arranques en frío lentos. Solución: dependencias ligeras, capas o contenedor con venv precompilado.
- Bloquear el bucle de eventos en manejadores asíncronos - tiempos de espera (timeouts). Solución: descargar trabajo de CPU o usar un manejador síncrono con tiempo de espera/memoria apropiados.
- Falta de idempotencia en reintentos asíncronos - efectos secundarios duplicados. Solución: manejadores idempotentes con claves de deduplicación (escrituras condicionales de SQS FIFO o DynamoDB).
- Registrar solo en stdout sin estructura - difícil de rastrear. Solución: logs JSON con
request_iddecontext.aws_request_id.
Alternativas
| Alternativa | Usar Cuando | No Usar Cuando |
|---|---|---|
| ECS/Fargate | HTTP de larga duración, websockets | Tareas cortas y esporádicas |
| Step Functions | Orquestación de múltiples pasos | Transformaciones de una sola función |
| Workers Celery | Cultura de operaciones Redis/Rabbit existente | Quieres cero administración de servidores |
Preguntas Frecuentes
¿Cómo empaqueto Python 3.14 para Lambda?
Coincide con la versión del runtime de Lambda en AWS; compila las dependencias en un contenedor de Amazon Linux o una imagen de CI que coincida con la ABI del runtime.
¿Qué tiempo de espera (timeout) debo establecer?
Justo por encima del p99 de tiempo de ejecución con margen; emparejar con el tiempo de espera de visibilidad de SQS > tiempo de espera de Lambda para disparadores de cola.
¿Cómo invoco desde otra cuenta?
Política basada en recursos en la función que permite la entidad principal de la cuenta que llama.
¿RequestResponse vs Event?
RequestResponse para estilo RPC; Event para procesamiento desacoplado donde el llamador no necesita el resultado en línea.
¿Cómo funcionan las versiones y los alias?
Publica una versión inmutable desde $LATEST, apunta el alias prod a la versión para revertir volviendo a apuntar el alias.
¿Puedo usar pydantic en los manejadores?
Sí - valida el diccionario de eventos temprano; mantén los modelos pequeños para reducir el tiempo de importación.
¿Cómo limito la concurrencia?
Concurrencia reservada en la función o límites de cuenta; concurrencia máxima de SQS para el mapeo de origen de eventos.
¿Qué pasa con los secretos?
Obtén de Secrets Manager al inicializar si es necesario; prefiere variables de entorno inyectadas desde SSM/Secrets al desplegar.
¿Cómo pruebo localmente?
Invoca la función manejadora directamente en pytest con eventos de muestra; usa SAM o LocalStack para integración.
¿Cómo despliega código boto3?
update_function_code sube un zip desde CI; prefiere IaC (SAM, Pulumi, Terraform) que envuelva esa API.
Relacionado
- AWS Lambda y Serverless - empaquetado y arranques en frío
- SQS y SNS - fuentes de eventos
- S3 - disparadores de objetos
- Conceptos básicos de Boto3 - patrones de cliente
- Secrets Manager y SSM - secretos de entorno
Versiones de la pila: Esta página fue escrita para Python 3.14.0 (estable 3.14, mantenimiento 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+ y uv 0.6+.