2022-01-01 10:00:00+00:00

When migrating from monoliths to microservices, managing service communication and request routing becomes a central challenge. Coupling client applications directly to multiple backend services introduces complexity and security risks. A clean architecture routes all external traffic through a single entry point: an API Gateway.

By leveraging FastAPI's asynchronous handling and HTTP client wrappers, you can design a gateway that proxies requests downstream, buffers traffic spikes, and extracts authorization details efficiently.


1. Designing the Gateway Routing Layer

In our microservices architecture, clients interact solely with api-gateway. This service acts as a reverse proxy, translating request paths into downstream endpoints (such as forwarding /crm to crm-service or /notify to notification-service):

# Proxying request to backend microservices in FastAPI
import httpx
from fastapi import FastAPI, Request, Response

app = FastAPI()
client = httpx.AsyncClient()

@app.api_route("/api/crm/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def crm_proxy(request: Request, path: str):
    url = f"http://crm-service:8000/gq/{path}"
    headers = dict(request.headers)
    # Forward the query or mutation payload
    body = await request.body()
    response = await client.request(
        method=request.method,
        url=url,
        headers=headers,
        content=body,
        timeout=10.0
    )
    return Response(
        content=response.content,
        status_code=response.status_code,
        headers=dict(response.headers)
    )

2. The Benefits of Decoupling

Decoupling downstream microservices behind an API Gateway allows us to standardise rate-limiting, CORS policies, and request tracing in one location, protecting the core business endpoints from unnecessary exposures.