Django cookbook · Advanced

Call external APIs concurrently in async views

A view calls three slow services one after another, so the response takes the sum of their times.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Write the view as async def, call services concurrently with asyncio.gather on a shared httpx.AsyncClient with timeouts, and use the ORM's async methods (aget, acount, async for). Run under an ASGI server.

Solution

import asyncio

import httpx
from django.http import JsonResponse

from shop.models import Product

client = httpx.AsyncClient(timeout=httpx.Timeout(2.0, connect=1.0))


async def fetch_json(url: str) -> dict | None:
    try:
        response = await client.get(url)
        response.raise_for_status()
        return response.json()
    except httpx.HTTPError:
        return None                                      # degrade gracefully


async def product_overview(request, product_id: int):
    product = await Product.objects.aget(id=product_id)
    stock, reviews, shipping = await asyncio.gather(
        fetch_json(f"https://stock.internal/items/{product.sku}"),
        fetch_json(f"https://reviews.internal/products/{product.id}"),
        fetch_json(f"https://shipping.internal/estimate?sku={product.sku}"),
    )
    return JsonResponse({
        "name": product.name,
        "stock": stock and stock["available"],
        "rating": reviews and reviews["average"],
        "ships_in_days": shipping and shipping["days"],
    })

Pitfalls

  • Calling sync code (sync ORM methods, requests) inside async views, blocking the event loop.
  • Async views under WSGI, where they run in a thread per request and gain nothing.
  • No timeouts on outbound calls.

Variations

  • Wrap unavoidable sync code with asgiref.sync.sync_to_async(thread_sensitive=True).
  • Cache the slow services' responses briefly to protect them under load.

Further reading: Asynchronous support

Reference: https://docs.djangoproject.com/en/6.0/topics/async/

More Django recipes

Was this page helpful?