green snake
Photo by Pixabay on Pexels.com
目次

Introducción práctica al diseño de clientes de API externas en FastAPI: cómo construir integraciones resilientes con HTTPX, timeouts, reintentos, pools de conexiones y aislamiento de fallos


Resumen

  • El procesamiento de llamadas a APIs externas desde FastAPI no debe tratarse simplemente como una colección de llamadas httpx.get(). Debe diseñarse como infraestructura que afecta a la fiabilidad de tu aplicación. FastAPI es fuerte para el procesamiento asíncrono y funciona bien con integraciones de API que implican mucho I/O externo, pero debes evitar bloquear el event loop o permitir conexiones ilimitadas. 0
  • Con HTTPX, puedes reutilizar un AsyncClient y configurar explícitamente Timeout y Limits para controlar los pools de conexiones y los tiempos de espera. Los timeouts de HTTPX se dividen en cuatro tipos: connect, read, write y pool. El número de conexiones también puede ajustarse con max_connections y max_keepalive_connections. 1
  • Los reintentos se vuelven peligrosos cuando se aplican a ciegas. En la capa de transporte de HTTPX, los reintentos de conexión pueden cubrir cosas como ConnectError y ConnectTimeout. Para condiciones de reintento más amplias o backoff exponencial, una librería de reintentos de propósito general como Tenacity encaja mejor. 2
  • En sistemas reales, es más fácil mantener limpios los routers y las capas de servicio si agrupas timeouts, conversión de excepciones, reintentos, aislamiento de fallos, logs de auditoría y métricas en una sola “capa de cliente de API externa”. HTTPX proporciona una jerarquía de excepciones bien organizada, como RequestError y HTTPStatusError, lo que facilita este tipo de diseño. 3
  • Este artículo explica cuidadosamente el diseño práctico de clientes de API externas en FastAPI en el siguiente orden: principios básicos → AsyncClient compartido → timeouts → reintentos → enfoque de circuit breaker → observabilidad → testing.

Quién se beneficiará de leer esto

Desarrolladores individuales y personas que están aprendiendo

  • Personas que han empezado a integrarse con APIs de clima, pagos, IA generativa, envíos y servicios similares.
  • Personas que usan requests o httpx sobre la marcha sin haber pensado mucho en timeouts o manejo de errores.
  • Personas que quieren pasar de “código que funciona” a “código que no se rompe fácilmente”.

Para este grupo, el artículo ayuda a aclarar cómo ubicar las llamadas a APIs externas en FastAPI para que no se conviertan en un dolor después. FastAPI es muy adecuado para I/O asíncrono, y httpx.AsyncClient es un cliente muy natural en ese contexto. 4

Ingenieros backend en equipos pequeños

  • Personas cuyas llamadas a APIs externas han empezado a dispersarse entre routers y servicios.
  • Personas cuyos ajustes de timeout, número de conexiones y políticas de reintento varían de una persona a otra.
  • Personas que quieren estandarizar cómo se manejan los fallos y los valores de retorno en todo el equipo.

Para este grupo, diseñar clientes de API externas como dependencias o clases dedicadas es especialmente útil. El sistema de dependencias y las funciones de lifespan de FastAPI encajan muy bien para gestionar clientes compartidos. 5

Equipos SaaS y startups

  • Equipos en los que la inestabilidad de APIs externas afecta directamente a la latencia o a las caídas del servicio.
  • Equipos que dependen de múltiples servicios externos como facturación, envíos, notificaciones, plataformas de autenticación o APIs de LLM.
  • Equipos que quieren reforzar más adelante colas de trabajos, circuit breakers y aislamiento de fallos.

Para este grupo, resulta muy eficaz introducir un nivel de abstracción para la capa de cliente y centralizar pools de conexiones, timeouts, reintentos y métricas. Limits y Timeout de HTTPX son especialmente útiles como base de ese diseño. 6


Evaluación de accesibilidad

  • El artículo comienza con los puntos principales y luego avanza paso a paso a través de “por qué esto es arriesgado”, “cómo diseñarlo” y “dónde implementarlo”.
  • Los términos técnicos se explican brevemente en su primera aparición y luego se usan de manera consistente.
  • El código está dividido en bloques cortos y de responsabilidad única, de modo que cada fragmento tenga un propósito claro.
  • El nivel objetivo es equivalente a AA.

1. Por qué importa el diseño de clientes de API externas

Dentro de un router de FastAPI, es muy tentador escribir algo como esto.

import httpx
from fastapi import APIRouter

router = APIRouter()

@router.get("/weather")
async def get_weather():
    async with httpx.AsyncClient() as client:
        resp = await client.get("https://api.example.com/weather")
        return resp.json()

Esto funciona, pero en sistemas reales, pequeños problemas se van acumulando gradualmente.

  • Creas un nuevo AsyncClient en cada petición y no reutilizas el pool de conexiones
  • Los timeouts quedan vagos, por lo que una API externa lenta arrastra también a tu propia API
  • Los errores suben como excepciones crudas de httpx, así que el manejo de errores es inconsistente en todo el servicio
  • Las condiciones de reintento son diferentes en cada sitio
  • No hay métricas ni logs, así que no puedes saber qué API externa es lenta

La documentación oficial de HTTPX también explica que en entornos asíncronos debes usar AsyncClient, y que reutilizar instancias de cliente es importante. Aconseja explícitamente no crear nuevos clientes sin cuidado en bucles calientes. 7

En otras palabras, en vez de colocar llamadas a APIs externas de forma improvisada, a largo plazo es mejor organizarlas en una capa de cliente.


2. Política básica: mover las llamadas a APIs externas a clases dedicadas

Una estructura básica recomendada es dividir las responsabilidades así.

  • Router
    • Maneja solo la entrada y salida HTTP
  • Capa de servicio
    • Maneja la lógica de negocio
  • Capa de cliente de API externa
    • Maneja la comunicación mediante HTTPX, timeouts, conversión de excepciones y reintentos

Esto hace posible estandarizar en un solo lugar “qué debe devolverse cuando falla una API externa” y “hasta dónde deben llegar los reintentos”.

Por ejemplo, imagina un cliente dedicado a una API de envíos.

# app/clients/shipping_client.py
class ShippingClient:
    async def create_shipment(self, payload: dict) -> dict:
        ...

Con esta estructura, routers y servicios solo necesitan expresar la intención “solicitar la creación de un envío”, mientras que el control HTTP detallado se queda dentro de la capa de cliente.


3. Gestionar un AsyncClient compartido en FastAPI: usar Lifespan

En FastAPI, puedes definir el procesamiento de arranque y apagado con lifespan. La documentación oficial lo describe como un mecanismo para crear recursos al iniciar y liberarlos al cerrar. 8

Uno de los recursos compartidos más comunes para clientes de APIs externas es httpx.AsyncClient.

3.1 Ejemplo mínimo con lifespan

# app/main.py
from contextlib import asynccontextmanager

import httpx
from fastapi import FastAPI

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.http_client = httpx.AsyncClient()
    try:
        yield
    finally:
        await app.state.http_client.aclose()

app = FastAPI(lifespan=lifespan)

Con esta configuración, toda la aplicación puede reutilizar un único AsyncClient. HTTPX proporciona connection pooling a través de AsyncClient, por lo que reutilizarlo es especialmente beneficioso al hacer múltiples solicitudes al mismo host. 9

3.2 Obtenerlo mediante una dependencia

# app/deps/http_client.py
import httpx
from fastapi import Request

def get_http_client(request: Request) -> httpx.AsyncClient:
    return request.app.state.http_client

Esto te permite inyectar el cliente compartido en routers o clases de cliente a través del sistema de dependencias de FastAPI. La inyección de dependencias de FastAPI funciona muy bien para este tipo de gestión de componentes compartidos. 10


4. Define siempre los timeouts de forma explícita: comprende los cuatro tipos de timeout de HTTPX

HTTPX permite un control bastante fino de los timeouts. Según la documentación oficial, hay cuatro tipos: connect, read, write y pool. 11

  • connect
    • Tiempo máximo permitido para establecer una conexión
  • read
    • Tiempo máximo de espera mientras se leen datos del servidor
  • write
    • Tiempo máximo de espera mientras se envían datos de la solicitud
  • pool
    • Tiempo máximo de espera para adquirir una conexión disponible del pool

En vez de fijar el mismo valor para todos de manera mecánica, es más estable pensarlos en función del comportamiento de la API externa.

4.1 Ejemplo: ajustes de timeout algo más detallados

# app/core/http.py
import httpx

DEFAULT_TIMEOUT = httpx.Timeout(
    connect=2.0,
    read=5.0,
    write=5.0,
    pool=1.0,
)

4.2 Aplicarlo a AsyncClient

# app/main.py
from contextlib import asynccontextmanager
import httpx
from fastapi import FastAPI

from app.core.http import DEFAULT_TIMEOUT

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.http_client = httpx.AsyncClient(timeout=DEFAULT_TIMEOUT)
    try:
        yield
    finally:
        await app.state.http_client.aclose()

app = FastAPI(lifespan=lifespan)

Si los timeouts no se configuran, o son demasiado flexibles, una API externa lenta se convierte directamente en una API lenta de tu lado.
Decidir cuánto tiempo puedes tolerar esperar en el peor caso es extremadamente importante en las integraciones externas. HTTPX soporta oficialmente control granular de timeouts, y usarlo hace que todo sea mucho más fácil de gestionar. 12


5. Controla el pool de conexiones: añade Limits

HTTPX también te permite controlar los límites del pool de conexiones mediante Limits. La documentación oficial describe max_keepalive_connections, max_connections y keepalive_expiry, y también proporciona valores por defecto. 13

5.1 Ejemplo de Limits

# app/core/http.py
import httpx

DEFAULT_LIMITS = httpx.Limits(
    max_keepalive_connections=20,
    max_connections=100,
    keepalive_expiry=5.0,
)

5.2 Aplicarlo a AsyncClient

# app/main.py
from contextlib import asynccontextmanager
import httpx
from fastapi import FastAPI

from app.core.http import DEFAULT_TIMEOUT, DEFAULT_LIMITS

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.http_client = httpx.AsyncClient(
        timeout=DEFAULT_TIMEOUT,
        limits=DEFAULT_LIMITS,
    )
    try:
        yield
    finally:
        await app.state.http_client.aclose()

app = FastAPI(lifespan=lifespan)

Si dejas las conexiones sin límite, una API externa lenta también puede empezar a consumir recursos de tu propia aplicación.
Si haces los límites demasiado estrictos, es posible que veas más fallos de pool timeout, así que el enfoque realista es ajustarlos gradualmente mientras observas métricas.


6. No dejes escapar excepciones crudas: convierte las excepciones de HTTPX en las tuyas propias

HTTPX tiene una jerarquía de excepciones bien organizada. La documentación oficial y la lista de excepciones incluyen RequestError, HTTPStatusError y excepciones más específicas como ConnectTimeout, ReadTimeout y PoolTimeout. 14

En lugar de dejar que suban directamente, normalmente es mejor convertirlas en excepciones específicas de tu aplicación para que el manejo se mantenga consistente.

6.1 Define tus propias excepciones de aplicación

# app/clients/exceptions.py
class ExternalAPIError(Exception):
    pass

class ExternalAPITimeoutError(ExternalAPIError):
    pass

class ExternalAPIUnavailableError(ExternalAPIError):
    pass

class ExternalAPIBadResponseError(ExternalAPIError):
    pass

6.2 Convertir excepciones de HTTPX

# app/clients/base.py
import httpx

from app.clients.exceptions import (
    ExternalAPIBadResponseError,
    ExternalAPITimeoutError,
    ExternalAPIUnavailableError,
)

async def safe_request(client: httpx.AsyncClient, method: str, url: str, **kwargs) -> httpx.Response:
    try:
        response = await client.request(method, url, **kwargs)
        response.raise_for_status()
        return response
    except httpx.TimeoutException as exc:
        raise ExternalAPITimeoutError(str(exc)) from exc
    except httpx.HTTPStatusError as exc:
        raise ExternalAPIBadResponseError(str(exc)) from exc
    except httpx.RequestError as exc:
        raise ExternalAPIUnavailableError(str(exc)) from exc

Aquí, los fallos relacionados con timeout se agrupan bajo TimeoutException, los problemas de conexión bajo RequestError, y las respuestas HTTP no exitosas bajo HTTPStatusError. Esto sigue la estructura de excepciones documentada por HTTPX. 15


7. Construye una clase cliente de API externa: ejemplo de API de envíos

Ahora vamos a combinar las piezas anteriores en una clase cliente concreta.

# app/clients/shipping_client.py
import httpx

from app.clients.base import safe_request

class ShippingClient:
    def __init__(self, client: httpx.AsyncClient, base_url: str, api_key: str):
        self.client = client
        self.base_url = base_url.rstrip("/")
        self.api_key = api_key

    async def create_shipment(self, payload: dict) -> dict:
        response = await safe_request(
            self.client,
            "POST",
            f"{self.base_url}/shipments",
            json=payload,
            headers={"Authorization": f"Bearer {self.api_key}"},
        )
        return response.json()

    async def get_shipment(self, shipment_id: str) -> dict:
        response = await safe_request(
            self.client,
            "GET",
            f"{self.base_url}/shipments/{shipment_id}",
            headers={"Authorization": f"Bearer {self.api_key}"},
        )
        return response.json()

La ventaja de esta clase es que routers y servicios ya no necesitan conocer httpx directamente.
También estandariza cómo se adjuntan las API keys, cómo se construyen las URL y cómo se convierten las excepciones.


8. Ensambla el cliente con dependencias de FastAPI

Puedes usar dependencias de FastAPI para construir un ShippingClient a partir del AsyncClient compartido.

# app/deps/clients.py
from fastapi import Depends
import httpx

from app.clients.shipping_client import ShippingClient
from app.deps.http_client import get_http_client

def get_shipping_client(
    client: httpx.AsyncClient = Depends(get_http_client),
) -> ShippingClient:
    return ShippingClient(
        client=client,
        base_url="https://shipping.example.com/api",
        api_key="replace-me",
    )

8.1 Mantén el router delgado

# app/api/v1/routers/shipments.py
from fastapi import APIRouter, Depends

from app.clients.shipping_client import ShippingClient
from app.deps.clients import get_shipping_client

router = APIRouter(prefix="/shipments", tags=["shipments"])

@router.post("")
async def create_shipment(
    payload: dict,
    shipping_client: ShippingClient = Depends(get_shipping_client),
):
    result = await shipping_client.create_shipment(payload)
    return result

Con esta estructura, la complejidad de la integración con APIs externas queda confinada a la capa de cliente, y el router sigue siendo mucho más fácil de leer.


9. Ten cuidado con los reintentos: cómo usar los reintentos de transporte de HTTPX y Tenacity

En la capa de transporte de HTTPX, los reintentos de conexión están soportados. La documentación oficial explica que estos reintentos se aplican a ConnectError y ConnectTimeout, y recomienda herramientas más generales como Tenacity para comportamientos de reintento más amplios. 16

9.1 Ejemplo: reintentos de conexión a nivel de transporte

# app/core/http.py
import httpx

TRANSPORT = httpx.AsyncHTTPTransport(retries=1)
# app/main.py
from contextlib import asynccontextmanager
import httpx
from fastapi import FastAPI

from app.core.http import DEFAULT_TIMEOUT, DEFAULT_LIMITS, TRANSPORT

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.http_client = httpx.AsyncClient(
        timeout=DEFAULT_TIMEOUT,
        limits=DEFAULT_LIMITS,
        transport=TRANSPORT,
    )
    try:
        yield
    finally:
        await app.state.http_client.aclose()

app = FastAPI(lifespan=lifespan)

Esto ayuda en casos como un fallo momentáneo de conexión, pero no encaja bien para reintentos flexibles que involucren respuestas HTTP 503 o 429. Ahí es donde una librería como Tenacity se vuelve útil. Tenacity es una librería de reintentos de propósito general con soporte para cosas como backoff exponencial. 17

9.2 Ejemplo: backoff exponencial con Tenacity

# app/clients/retry.py
from tenacity import (
    retry,
    retry_if_exception_type,
    stop_after_attempt,
    wait_exponential,
)

from app.clients.exceptions import (
    ExternalAPITimeoutError,
    ExternalAPIUnavailableError,
)

@retry(
    retry=retry_if_exception_type((ExternalAPITimeoutError, ExternalAPIUnavailableError)),
    wait=wait_exponential(multiplier=0.5, min=0.5, max=5),
    stop=stop_after_attempt(3),
    reraise=True,
)
async def retryable_call(func, *args, **kwargs):
    return await func(*args, **kwargs)

9.3 Úsalo en el cliente

# app/clients/shipping_client.py
from app.clients.retry import retryable_call

class ShippingClient:
    # omitted

    async def create_shipment(self, payload: dict) -> dict:
        response = await retryable_call(
            safe_request,
            self.client,
            "POST",
            f"{self.base_url}/shipments",
            json=payload,
            headers={"Authorization": f"Bearer {self.api_key}"},
        )
        return response.json()

El punto importante aquí es que no debes reintentar operaciones de escritura a ciegas. Reintentar solicitudes POST puede causar creación duplicada.
Si la API externa acepta claves de idempotencia, deberías usarlas siempre que pretendas reintentar de forma segura.


10. Qué puede reintentarse de forma segura: separa operaciones de lectura de operaciones de escritura

Los reintentos son útiles, pero aplicarlos a todas las llamadas a API externa sin distinción puede causar accidentes.

Más fácil de reintentar

  • Operaciones de lectura como GET
  • Fallos en el establecimiento de conexión
  • Errores de red temporales
  • Algunas respuestas 429 / 503, si la especificación del proveedor lo permite

Reintentar con cautela

  • Operaciones POST / PATCH / DELETE con efectos secundarios
  • Ejecución de pagos, confirmación de pedidos, envío de notificaciones externas
  • APIs de escritura sin claves de idempotencia

Por tanto, la política de reintentos no debe ser “simplemente intenta tres veces”.
La pregunta correcta es si es seguro reintentar esta llamada.


11. Enfoque de circuit breaker: no dejes que una dependencia que falla te arrastre para siempre

Un circuit breaker es la idea de “detener temporalmente las llamadas a una dependencia que sigue fallando, para que toda tu aplicación no se hunda con ella”.
Este artículo no entra en profundidad en librerías dedicadas, pero incluso tener presente el concepto de diseño ya resulta útil.

Por ejemplo, si una API externa es inestable durante varios minutos, y cada llamada espera hasta el timeout completo, tu propia API también se vuelve lenta.
En cambio, tras cierto número de fallos, a menudo es mejor decidir “esta API no está sana ahora mismo” y fallar rápido durante un tiempo para reducir el radio de impacto.

No necesitas un circuit breaker completo desde el primer día. Una progresión práctica sería así.

  1. Empieza añadiendo timeouts cortos
  2. Convierte excepciones crudas en excepciones de aplicación
  3. Añade reintentos de alcance reducido
  4. Observa métricas de tasa de fallo y, solo si hace falta, introduce un circuit breaker

12. Logs y métricas: haz visible qué API externa es lenta

Un problema común con las integraciones de APIs externas es que después no puedes saber qué es lo que iba lento.
Como mínimo, ayuda registrar o medir lo siguiente.

  • Qué servicio externo era
  • Qué endpoint se llamó
  • Si tuvo éxito o falló
  • Cuántos segundos tardó
  • Cuántos reintentos se realizaron
  • Qué excepción ocurrió

12.1 Ejemplo mínimo de logging

# app/clients/base.py
import logging
import time
import httpx

logger = logging.getLogger("external_api")

async def safe_request(client: httpx.AsyncClient, method: str, url: str, **kwargs) -> httpx.Response:
    started = time.perf_counter()
    try:
        response = await client.request(method, url, **kwargs)
        response.raise_for_status()
        logger.info(
            "external api success",
            extra={
                "method": method,
                "url": url,
                "status_code": response.status_code,
                "elapsed_ms": int((time.perf_counter() - started) * 1000),
            },
        )
        return response
    except httpx.HTTPError as exc:
        logger.warning(
            "external api failure",
            extra={
                "method": method,
                "url": url,
                "elapsed_ms": int((time.perf_counter() - started) * 1000),
                "error_type": exc.__class__.__name__,
            },
        )
        raise

Incluso este nivel de logging puede decirte más tarde cosas como “esa API de envíos es la lenta”.


13. Estrategia de testing: no golpees directamente la API externa real

El principio clave al probar clientes de API externa es no llamar directamente al endpoint real de producción.
La razón es simple: es inestable, costoso y difícil de reproducir de forma fiable.

Una división útil sería esta.

  • Tests unitarios
    • Verifican que la clase cliente construye la URL, las cabeceras y la conversión de excepciones correctas
  • Tests de integración
    • Usan un servidor simulado o un test transport para simular solicitudes de HTTPX
  • Tests E2E
    • Verifican solo los flujos realmente necesarios contra el entorno de pruebas del proveedor

HTTPX incluye un mecanismo de transporte, y la documentación oficial explica transportes personalizados y usos relacionados con testing. 18

13.1 Ejemplo de orientación para tests unitarios en la capa de cliente

# pseudo example
# check whether create_shipment sends a POST with Authorization header
# check whether 404 or timeout is converted into your own custom exception

Los tests más valiosos suelen centrarse en tu propia lógica de conversión y política de reintentos.


14. Patrones comunes de fallo

14.1 Crear AsyncClient() dentro del router cada vez

HTTPX funciona de manera más eficiente cuando los clientes se reutilizan. Un cliente compartido te permite beneficiarte más del connection pooling. 19

14.2 Dejar los timeouts sin configurar

Si la API externa es lenta, tu propia API también se vuelve lenta. HTTPX soporta control detallado de timeouts, así que los ajustes explícitos son más seguros. 20

14.3 Reintentar operaciones de escritura sin condiciones

Esto provoca fácilmente ejecuciones duplicadas de POST. Comprueba siempre las claves de idempotencia y la especificación de la API externa.

14.4 Dejar que las excepciones de httpx suban sin cambios

Esto hace que el diseño de errores sea inconsistente en todo el servicio. Es más fácil de gestionar si las conviertes en tus propias excepciones. La jerarquía de excepciones de HTTPX está bien organizada, así que clasificarlas es sencillo. 21

14.5 No observar qué API externa es lenta

Hacer visibles el número de conexiones, la latencia y las tasas de fallo ayuda muchísimo más adelante.


15. Hoja de ruta según el tipo de lector

Desarrolladores individuales y personas que están aprendiendo

  1. Usa httpx.AsyncClient en lugar de requests
  2. Crea un cliente compartido con lifespan
  3. Define explícitamente timeouts y Limits
  4. Convierte excepciones en tus propios tipos de excepción
  5. Considera reintentos solo para operaciones de lectura al principio

Ingenieros en equipos pequeños

  1. Haz inventario de todas las llamadas a APIs externas
  2. Deja de escribirlas directamente en los routers y muévelas a una capa de cliente
  3. Estandariza pools de conexiones, políticas de timeout y reglas de reintento
  4. Añade logs y métricas
  5. Crea módulos de cliente separados según la responsabilidad de cada servicio externo

Equipos SaaS y startups

  1. Clasifica las APIs externas por criticidad, efectos secundarios e idempotencia
  2. Establece un cliente HTTPX compartido y controles de conexión
  3. Diseña la conversión de excepciones, reintentos e integración con colas de trabajos
  4. Supervisa la tasa de fallo, la tasa de timeout y el número de reintentos
  5. Añade circuit breakers o estrategias de fallback donde sea necesario

Enlaces de referencia


Conclusión

  • En FastAPI, las integraciones con APIs externas se vuelven mucho más resilientes cuando se diseñan como una capa de cliente, en lugar de como llamadas HTTP dispersas y aisladas.
  • Compartir AsyncClient, definir explícitamente Timeout y Limits, convertir excepciones y organizar las reglas de reintento forman una base muy eficaz a cualquier escala. HTTPX soporta oficialmente estas funciones, y encajan de forma natural con los sistemas de lifespan y dependencias de FastAPI. 32
  • Los reintentos son útiles, pero deben aplicarse con cuidado. En lugar de reintentar todo, decide según si la llamada es de solo lectura, si tiene efectos secundarios y si el proveedor soporta idempotencia. Los reintentos de transporte en HTTPX son adecuados para fallos a nivel de conexión, mientras que las políticas más amplias se manejan mejor con una librería general como Tenacity. 33
  • No necesitas un aislamiento de fallos perfecto desde el principio, pero simplemente extraer una capa de cliente hace que futuras incorporaciones como circuit breakers, colas de trabajos y métricas más sólidas sean mucho más fáciles.

Un siguiente artículo natural a partir de aquí sería algo como “Patrones de diseño para construir APIs internas de administración con FastAPI” o “Diseño práctico de circuit breaker y fallback en FastAPI”.

por greeden

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)