FastAPI y AWS Lambda para APIs Serverless

FastAPI y AWS Lambda para APIs Serverless

En la arquitectura en la nube moderna, la directiva es clara: maximizar la escalabilidad y la velocidad del desarrollo, al tiempo que se minimiza la carga operativa. Las APIs monolíticas tradicionales, basadas en servidores, imponen una carga en la gestión, la escalabilidad y los costos. Las arquitecturas sin servidor, específicamente AWS Lambda, ofrecen una alternativa convincente al abstraer la gestión del servidor y proporcionar una escalabilidad real de pago por invocación.

Sin embargo, el modelo de "función como servicio" (FaaS) básico puede carecer de la experiencia del desarrollador, la estructura y la optimización del rendimiento de los modernos frameworks web. Es aquí donde FastAPI entra en juego. FastAPI, basado en Starlette y Pydantic, proporciona un framework asíncrono de alto rendimiento (comparable con NodeJS y Go) con validación de datos automática y documentación de API.

Combinar la excepcional experiencia de desarrollo de FastAPI con la eficiencia operativa de AWS Lambda crea una pila potente para construir APIs robustas, escalables y rentables. Este artículo proporciona un esquema completo y listo para la producción para implementar una aplicación FastAPI como una función de AWS Lambda, con un API Gateway, utilizando el Modelo de Aplicación Servidor de AWS (SAM).

Equipo de Ingeniería de Software Compartido Bajo Demanda, Por Suscripción.

Acceda a un equipo flexible y compartido de ingeniería de software bajo demanda a través de una suscripción mensual predecible. Desarrolladores, diseñadores, ingenieros de control de calidad y un gerente de proyecto gratuito le ayudan a crear MVPs, escalar productos e innovar con tecnologías modernas como React, Node.js y más.

Try 4Geeks Teams

Componentes principales de la arquitectura

  1. FastAPI: El framework web de Python. Lo utilizamos para el enrutamiento, la inyección de dependencias, la validación de datos basada en Pydantic y la generación automática de OpenAPI (Swagger/ReDoc).
  2. AWS Lambda: El servicio de cómputo. Toda nuestra aplicación FastAPI se empaquetará y desplegará como una única función Lambda.
  3. Amazon API Gateway (HttpApi): El punto de entrada. Utilizaremos la API HTTP v2 (que es más rápida y económica que la API REST v1) para recibir solicitudes HTTP y redirigirlas a nuestra función Lambda.
  4. Mangum: El adaptador crítico. AWS Lambda y API Gateway se comunican a través de una estructura de evento JSON específica. FastAPI, como un ASGI framework, espera un ámbito ASGI.Mangum es un adaptador ligero que traduce el evento de Lambda en un ámbito compatible con ASGI que FastAPI entiende.
  5. AWS SAM (Serverless Application Model): El framework de Infrastructure as Code (IaC). Utilizamos SAM para definir nuestra función Lambda, API Gateway y sus permisos en un simple template.yaml archivo, lo que permite desplegues reproducibles y automatizados.

Sección 1: Configuración del proyecto y la aplicación FastAPI

Primero, establezca la estructura del proyecto. Aislaremos el código de la aplicación en un directorio llamado "app".

serverless-fastapi/
├── app/
│   ├── __init__.py
│   ├── main.py
│   └── requirements.txt
└── template.yaml

1.1. Definir Dependencias (app/requirements.txt)

Nuestra aplicación requiere tres bibliotecas principales:

fastapi
uvicorn       # Required by FastAPI, though we won't run it as a server
mangum        # The Lambda-to-ASGI adapter
pydantic      # For data modeling (often a peer dependency of fastapi)

1.2. Crear la aplicación FastAPI (app/main.py)

Crearemos una API sencilla con tres puntos finales para demostrar la funcionalidad principal:

  • GET /: Un punto final raíz.
  • POST /users/: Un punto final que demuestra la validación del cuerpo de la solicitud basada en Pydantic.
  • GET /users/{user_id}: Un punto final que demuestra los parámetros de ruta y un modelo de respuesta de Pydantic.
# app/main.py
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
from typing import Optional

# 1. Define Pydantic Models for data validation
class UserCreate(BaseModel):
    email: EmailStr
    username: str
    is_active: bool = True

class UserResponse(BaseModel):
    id: int
    email: EmailStr
    username: str

# In-memory "database" for demonstration
db_users = {
    1: {"id": 1, "email": "cto@example.com", "username": "chief-tech"},
    2: {"id": 2, "email": "dev@example.com", "username": "lead-dev"},
}

# 2. Create the FastAPI app instance
app = FastAPI(
    title="Serverless FastAPI Demo",
    description="A demonstration of FastAPI on AWS Lambda.",
    version="1.0.0",
)

@app.get("/")
def read_root():
    """
    A simple health-check or root endpoint.
    """
    return {"message": "FastAPI is running on AWS Lambda!"}


@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
    """
    Get a user by their ID.
    """
    user = db_users.get(user_id)
    if not user:
        return {"error": "User not found"}, 404
    return user


@app.post("/users/", response_model=UserResponse, status_code=201)
def create_user(user: UserCreate):
    """
    Create a new user.
    The `user: UserCreate` parameter ensures the request body
    is validated against the UserCreate Pydantic model.
    """
    new_user_id = max(db_users.keys()) + 1
    new_user = user.model_dump()
    new_user["id"] = new_user_id
    db_users[new_user_id] = new_user
    
    # Note: Pydantic v2 uses model_dump(), v1 used .dict()
    return new_user

Este es una aplicación estándar y limpia de FastAPI. Críticamente, no tieneningún conocimiento de su entorno sin servidor.

Sección 2: Integración de Mangum - El adaptador ASGI

Para permitir que Lambda invoque nuestra aplicación FastAPI, introducimos Mangum. Modificamos app/main.py para añadir un controlador de Lambda.

Añada las siguientes líneas al final de app/main.py:

# ... (all the FastAPI code from above) ...

# 3. Import Mangum and create the handler
from mangum import Mangum

# This 'handler' is the entry point for AWS Lambda.
# Mangum(app) creates an adapter that AWS Lambda can invoke.
handler = Mangum(app, lifespan="off")

# Note: lifespan="off" is recommended for simple Lambda functions
# to avoid potential issues with startup/shutdown events.
# For more complex needs (e.g., database connection pools),
# you may need to manage the 'on' lifespan carefully.

El objeto es ahora el elemento invocable que AWS Lambda ejecutará. Mangum inspecciona el diccionario de evento que llega de API Gateway, lo traduce en un ámbito ASGI, lo pasa a app, espera la respuesta, y luego formatea la respuesta de FastAPI de nuevo en la estructura de diccionario que API Gateway espera.

Sección 3: Definición de la infraestructura con AWS SAM

Ahora definiremos nuestra infraestructura sin servidor utilizando la plantilla "template.yaml" de AWS SAMEste archivo declara nuestra función Lambda y la API HTTP que la activa.

Coloque esto en la raíz de su proyecto (plantilla.yamltemplate.yaml

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  A serverless application deploying a FastAPI backend on AWS Lambda.

Globals:
  Function:
    Timeout: 30
    MemorySize: 256
    Runtime: python3.11 # Specify a modern Python runtime

Resources:
  # 1. The Lambda Function resource
  FastApiLambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: app/  # Points to the directory containing our app
      Handler: main.handler  # The file is 'main.py', the callable is 'handler'
      Events:
        # 2. The API Gateway (HttpApi) event source
        ApiEvent:
          Type: HttpApi
          Properties:
            # 3. The "catch-all" proxy integration. This is critical.
            # It forwards ALL paths and methods to our Lambda.
            Path: /{proxy+}
            Method: ANY
            
            # This payload format is required by Mangum
            PayloadFormatVersion: '2.0' 

Outputs:
  # 4. Output the URL of the deployed API
  ApiEndpoint:
    Description: "API Gateway endpoint URL for Prod stage"
    Value: !Sub "https"://${ServerlessHttpApi}.execute-api.${AWS::Region}.amazonaws.com/

Decisiones de Arquitectura en este Plantilla:

  • Handler: main.handler: Esto le indica a Lambda que busque en main.py el objeto handler (que es nuestra instancia de Mangum(app)).
  • Tipo: HttpApi: Elegimos explícitamente la API HTTP v2 debido a su menor latencia y coste.
  • Ruta: /{proxy+} y Método: ANY: Esta es la parte más crucial. Esta única integración crea una ruta "catch-all". Cualquier solicitud, independientemente de la ruta (por ejemplo, /, /users/1, /docs) o del método (GET, POST, PUT), se redirige directamente a la aplicación FastAPI. Esto permite que el enrutador interno de FastAPI gestione toda la lógica de enrutamiento, tal como lo haría en un servidor tradicional.
  • PayloadFormatVersion: '2.0': Mangum funciona mejor con el formato de carga útil v2, que es más limpio y estructurado.

Equipo de Ingeniería de Software Compartido Bajo Demanda, Por Suscripción.

Acceda a un equipo flexible de ingeniería de software compartido bajo demanda a través de una suscripción mensual predecible. Desarrolladores, diseñadores, ingenieros de control de calidad y un gerente de proyecto gratuito le ayudan a crear MVPs, escalar productos e innovar con tecnologías modernas como React, Node.js, y más.

Try 4Geeks Teams

Sección 4: Procedimiento de Construcción e Implementación

Con el código de la aplicacióntemplate.yaml implementados, utilizamos la herramienta AWS SAM CLI para construir y desplegar.

Paso 1: Instalar dependencias y construir

SAM necesita empaquetar tu aplicación y sus dependencias.

# First, install dependencies locally for SAM to package
# (SAM will copy these from app/ into its build directory)
pip install -r app/requirements.txt -t app/

# Next, build the SAM application
# --use-container is highly recommended. It builds your dependencies
# inside a Docker container that mimics the Lambda environment,
# preventing "glibc" or "openssl" errors from compiled libraries.
sam build --use-container

Este comando crea un directorio /aws-sam/build que contiene el paquete de despliegue final.

Paso 2: Implementar la Aplicación

Ahora, desplegamos el artefacto creado en AWS.

# The --guided flag will walk you through a one-time setup
# for your stack name, AWS region, and other parameters.
sam deploy --guided

Siga las instrucciones:

  1. Nombre del Stack: serverless-fastapi-api (o el nombre que prefieras).
  2. Región de AWS: us-east-1 (o la región de destino).
  3. Confirme los cambios antes de implementar: y. Esto le permite revisar el changeset de AWS CloudFormation.
  4. Permite la creación de un rol IAM con SAM CLI: y.
  5. Guarda los argumentos en samconfig.toml: y. Esto guarda tus opciones, por lo que futuras implementaciones solo requieren sam deploy.

SAM ahora provisionará el stack de CloudFormation, que creará la API Gateway, la función Lambda y los roles IAM necesarios. Una vez completado, mostrará el Punto final de la APIApiEndpoint de tu template.yaml

---------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------
Key                 ApiEndpoint
Description         API Gateway endpoint URL for Prod stage
Value               https://xxxxxxxxxx.execute-api.us-east-1.amazonaws.com/
---------------------------------------------------------------------------------

Sección 5: Verificación y pruebas

Ahora puede interactuar con su API completamente sin servidor. Deje que $API_URL sea el valor de ApiEndpoint que obtenga de su salida.

Prueba 1: Punto final principal

curl $API_URL/

Respuesta esperada:

{"message":"FastAPI is running on AWS Lambda!"}

Prueba 2: Envío de datos POST con validación Pydantic

curl -X POST "$API_URL/users/" \
     -H "Content-Type: application/json" \
     -d '{"email": "engineer@example.com", "username": "senior-engineer"}'

Respuesta esperada:

{"id":3,"email":"engineer@example.com","username":"senior-engineer"}

Prueba 3: GET con parámetro de ruta

curl $API_URL/users/1

Respuesta esperada:

{"id":1,"email":"cto@example.com","username":"chief-tech"}

Prueba 4: Documentación API automática

La característica más potente: navegar a $API_URL/docs en su navegador. Verá la interfaz Swagger UI completa e interactiva, generada automáticamente por FastAPI, que funciona completamente en una infraestructura sin servidor.

Sección 6: Consideraciones avanzadas para la producción

1. Lanzamientos fríos

Un "inicio en frío" es la latencia que se produce en la primera solicitud a una función Lambda inactiva (descarga de código, inicialización del entorno y de tu aplicación).

  • Impact: FastAPI y Mangum son ligeros, por lo que los arranques fríos suelen ser rápidos (200-800 ms). Sin embargo, esto puede ser significativo para aplicaciones críticas en cuanto a latencia.
  • Mitigación: Para garantizar la latencia en el 99%, habilite Concurrencia Preasignada en su función Lambda. Esto mantiene un número especificado de instancias "calientes" y listas, eliminando por completo los arranques fríos, a un costo adicional.

2. Gestión y tamaño de la implementación de dependencias

  • Lambda Layers: Si su aplicación crece y comparte dependencias grandes (p.ej., pandas, numpy, scipy) con otras funciones, muéstelas en una Lambda Layer. Esto reduce el tamaño del paquete de despliegue de su función, acelerando los despliegues y los tiempos de inicio.
  • Imágenes de Contenedor: Para aplicaciones que exceden el límite de 250MB (descomprimido) del paquete .zip, despliegue su función como una Imagen de Contenedor. SAM es compatible con esto (PackageType: Image en template.yaml). Esto permite paquetes de hasta 10GB.

3. Observabilidad

  • Registro estructurado: No utilizarprint(). Utilice una biblioteca de registro estructurado. AWS Lambda Powertools for Python es el estándar de la industria. Proporciona registro estructurado, seguimiento (X-Ray) y métricas personalizadas con una mínima sobrecarga.
  • Seguimiento: Habilite el AWS X-Ray seguimiento activo tanto en API Gateway como en su función Lambda (una simple Seguimiento: Activo bandera en su plantilla.yaml). Esto proporciona un seguimiento completo de las solicitudes, desde la puerta de enlace hasta la invocación de Lambda y cualquier llamada downstream del SDK de AWS.

Finalmente

Esta arquitectura ofrece una solución "de lo mejor de ambos mundos". Conservamos todo el conjunto de funciones y la experiencia de desarrollo de primer nivel de FastAPI, incluyendo la inyección de dependencias, la validación de Pydantic y la documentación automática, al tiempo que obtenemos la enorme escalabilidad, la resiliencia y el modelo de costes "pago por uso" de AWS Lambda.

Al aprovechar Mangum para la adaptación y AWS SAM para una infraestructura reproducible, los equipos de ingeniería pueden implementar APIs de Python robustas y de alto rendimiento con una carga operativa casi nula, lo que les permite centrarse únicamente en la entrega de valor empresarial.

Equipo de Ingeniería de Software Compartido Bajo Demanda, Por Suscripción.

Acceda a un equipo flexible y compartido de ingeniería de software bajo demanda a través de una suscripción mensual predecible. Desarrolladores, diseñadores, ingenieros de QA y un gerente de proyecto gratuito le ayudan a crear MVPs, escalar productos e innovar con tecnologías modernas como React, Node.js y más.

Try 4Geeks Teams

Preguntas frecuentes

¿Qué es una arquitectura de FastAPI sin servidor?

Una arquitectura de FastAPI sin servidor es un método para construir y desplegar APIs que combina el potente framework de Python FastAPI con AWS Lambda, un servicio de computación sin servidor. En esta configuración, una API Gateway de Amazon recibe las solicitudes HTTP y las redirige a una única función Lambda, que ejecuta toda la aplicación FastAPI. Este modelo ofrece una alta escalabilidad, rentabilidad (pago por invocación) y una mínima sobrecarga operativa, ya que no hay servidores que gestionar.

¿Cómo funciona FastAPI en AWS Lambda si utilizan diferentes estructuras de eventos?

FastAPI, como un framework ASGI, espera recibir un scope ASGI para procesar las solicitudes. AWS Lambda, por otro lado, se activa a partir de una estructura de evento JSON específica proveniente de API Gateway. Esta brecha se supera mediante un adaptador ligero, como Mangum. Mangum traduce el evento de Lambda entrante en un scope compatible con ASGI que FastAPI puede entender, y luego formatea la respuesta de FastAPI de nuevo en la estructura que API Gateway espera.

¿Qué es AWS SAM y por qué se utiliza para implementar una aplicación FastAPI sin servidor?

AWS SAM (Modelo de Aplicación sin Servidor) es un marco de Infraestructura como Código (IaC) utilizado para definir y desplegar aplicaciones sin servidor. Para un proyecto FastAPI, se utiliza un archivo template.yaml para declarar todos los recursos necesarios, como la función AWS Lambda, la API Gateway de Amazon y sus permisos. Esto permite despliegues reproducibles y automatizados, y simplifica el proceso de gestión de toda la pila sin servidor.