Understanding ASGI (The Foundation of FastAPI)

03 Jun 2026, Updated: 29 Jul 2026 4 min read
1
In this article, we will explore ASGI (Asynchronous Server Gateway Interface) from first principles and understand why it became the foundation of modern Python web frameworks such as FastAPI.

What Problem Was ASGI Trying to Solve?

Before ASGI existed, most Python web applications used WSGI (Web Server Gateway Interface).

WSGI was introduced to standardize communication between Python web servers and Python web applications.

It enabled frameworks such as Flask and Django to run on different web servers without requiring framework-specific integrations.

A simplified request flow looked like this - Client β†’ Web Server β†’ WSGI Server β†’ Python Application

For many years this architecture worked extremely well because most web applications followed a simple request-response pattern.

A client sends a request, the server processes it, the application generates a response, and the connection is then closed.
WSGI was designed for synchronous request-response communication and became the foundation of Python web development for more than a decade.
However, modern applications must support thousands of concurrent users, long-lived connections, WebSockets, real-time notifications, streaming requests and responses, and Server-Sent Events (SSE).

WSGI was not designed to handle these workloads efficiently.

ASGI was introduced to address these limitations while remaining flexible enough to support both synchronous and asynchronous applications.

Understanding the Limitation of WSGI

Consider a traditional synchronous request.
def get_user():
    data = database.fetch_user()
    return data
While the application waits for the database response, the thread remains blocked.

If 10,000 users connect simultaneously, thousands of threads may be required. This approach eventually becomes expensive because threads consume memory and operating system resources.
WSGI is not inherently slow. The limitation is that WSGI was designed around synchronous communication and cannot efficiently support modern asynchronous protocols.

Introducing ASGI

ASGI was introduced as the successor to WSGI. Its primary goal was to support asynchronous communication while maintaining compatibility with modern networking requirements.

A simplified ASGI architecture looks like this: Client β†’ Uvicorn β†’ ASGI Interface β†’ FastAPI Application

Unlike WSGI, ASGI applications are not limited to one blocking request per thread. Instead, they can handle many concurrent requests using an event loop.

This allows the application to continue processing other requests while waiting for network operations, database calls, or external APIs.

How ASGI Works Internally?

At its core, ASGI defines a communication contract between the server and the application.

The server provides three componentsβ€”scope, receive, and sendβ€”and the application receives these components to process requests and generate responses.

A simplified ASGI application looks like this:
async def app(scope, receive, send):
    await send({
        "type": "http.response.start",
        "status": 200
    })
    await send({
        "type": "http.response.body",
        "body": b"Hello World"
    })
Although developers do not usually write raw ASGI applications, understanding the ASGI contract is important because FastAPI ultimately operates on top of it.

When a client sends an HTTP request, Uvicorn accepts the network connection and parses the incoming request.

It then converts the request into ASGI messages, constructs a scope object containing information about the request, and invokes the FastAPI application using the ASGI protocol.

A simplified scope object looks like this:
{
    "type": "http",
    "method": "GET",
    "path": "/users/1"
}
The scope contains metadata about the incoming connection and request, and remains available throughout the request lifecycle. You can think of it as the request context maintained by the ASGI server.

After FastAPI finishes processing the request, it returns ASGI response messages to Uvicorn. Uvicorn converts those messages into an HTTP response and sends it back to the client.

Why WebSockets Need ASGI?

One of the most important reasons ASGI became popular is WebSocket support.

Consider a chat application. The connection remains open for a long time. Messages can flow in both directions at any time. This communication pattern does not fit the traditional request-response model used by WSGI.

ASGI was designed to support protocols beyond HTTP, including WebSockets. Example:
@app.websocket("/chat")
async def chat(websocket):

    await websocket.accept()

    while True:
        message = await websocket.receive_text()
        await websocket.send_text(message)
Without ASGI, frameworks such as FastAPI would not be able to support WebSockets natively.

ASGI vs WSGI

Feature WSGI ASGI
Communication Model Synchronous Asynchronous
WebSockets No Native Support Native Support
Streaming Limited Supported
Concurrent Connections Thread Based Event Loop Based
Real-Time Applications Difficult Excellent

Conclusion

ASGI is the architectural foundation on which FastAPI is built.

It defines a standard communication contract between asynchronous Python applications and web server and enables capabilities such as high concurrency, WebSockets, streaming, and non-blocking request processing.
Nagesh Chauhan

Nagesh Chauhan

Principal Software Engineer β€’ Java β€’ Python β€’ Distributed Systems β€’ AI/ML

Principal Software Engineer with 14+ years of experience designing and delivering large-scale distributed systems, cloud-native applications, and AI-powered platforms.

Passionate about solving complex engineering problems using strong data structures and algorithms, along with expertise in Java, Spring Boot, Python, System Design, Microservices, Cloud, Kafka, Elasticsearch, and Generative AI.

Share this Article

πŸ’¬ Comments

Join the Discussion