Concept lesson

ASGI Spec & High-Concurrency Servers

Low-level ASGI 3.0 protocol teardown, receive/send channels, and Uvicorn/Granian servers.

lesson
Freshness: current15 min read
Mastery
not started · 0%

Learning outcomes

  • Understand ASGI scope and channel events
  • Deploy high-concurrency async servers

Mental model

ASGI (Asynchronous Server Gateway Interface) is the async successor to WSGI, defining a standardized interface between async web servers (Uvicorn, Granian) and Python frameworks (FastAPI, Starlette).

Socket Client Request
ASGI Server (Uvicorn / Granian)
Build Scope dict & Channels
Async Callable app(scope, receive, send)
Stream response events
Conceptual teaching model synthesized from:FastAPI Framework Architecture & Dependency Injection Specification

Theory

An ASGI 3.0 application is a single async callable with signature app(scope, receive, send):

  • scope: Dictionary containing request metadata (HTTP method, headers, path).
  • receive: Async function to receive incoming request body chunk events (http.request).
  • send: Async function to transmit outgoing response events (http.response.start, http.response.body).
async def raw_asgi_app(scope: dict, receive: callable, send: callable):
    assert scope["type"] == "http"
    event = await receive()

    await send({
        "type": "http.response.start",
        "status": 200,
        "headers": [[b"content-type", b"application/json"]],
    })
    await send({
        "type": "http.response.body",
        "body": b'{"status": "ok", "framework": "raw-asgi"}',
    })

Alternatives and trade-offs

  • WSGI (Gunicorn): Synchronous single-request-per-worker model. Fails at WebSockets or streaming.
  • Uvicorn (uvloop + httptools): Async server using Cython bindings for libuv and C HTTP parser.
  • Granian (Rust core): Rust-based ASGI/WSGI server using hyper for high throughput.

Failure modes and misconceptions

  1. WSGI Middleware on ASGI: Wrapping WSGI blocking middleware around FastAPI breaks asynchronous execution.
  2. Missing http.response.body: Forgetting to send the body event leaves HTTP client connections hanging.
Reflect before revealing the guide

Decision scenario

Deploy production FastAPI applications with multi-worker ASGI process managers (Gunicorn + Uvicorn workers or Granian) to maximize async multi-core CPU throughput.

Learning outcomes

  • Deconstruct the raw app(scope, receive, send) ASGI specification callable.
  • Compare WSGI synchronous request lifecycles with ASGI asynchronous event channels.
  • Deploy Uvicorn and Granian servers with optimal process worker topologies.

Trade-offs

ASGI servers support high-concurrency HTTP/WebSocket connections, but require non-blocking async architecture throughout all route handlers.

Evidence assessment

Theory and decision mastery

not-started · 0%
theory0%
decision0%
activityNot mapped
projectNot mapped
1. What is the standard function signature of an ASGI 3.0 application?
2. Why can WSGI servers like legacy Gunicorn not handle WebSockets natively?
3. What happens if an ASGI application sends `http.response.start` but fails to send `http.response.body`?

Decision scenario

A team is deploying a high-concurrency FastAPI application with 10,000 active Server-Sent Events (SSE) connections.

Which server deployment configuration delivers maximum async concurrency?

Primary sources