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.