Asynchronous Server Gateway Interface
The asynchronous server gateway interface (ASGI) is a specification for communication between asynchronous Python web servers, application frameworks, and applications. It extends the architectural role established by the Web Server Gateway Interface (WSGI) while replacing WSGI's synchronous request–response call with an interface capable of representing concurrent and long-lived communication. ASGI is therefore both a calling convention and a family of protocol specifications through which independently developed software components exchange events.
An ASGI application receives a connection description known as a scope, together with asynchronous callables for receiving and sending events. The scope remains associated with one logical connection, whereas the events represent changes occurring during that connection. This separation allows the same application interface to describe conventional Hypertext Transfer Protocol requests, bidirectional WebSocket sessions, and process-level lifespan events without requiring those protocols to share an identical sequence of operations.
Historical development
ASGI emerged from work on Django Channels, which required an application interface that could represent communication patterns outside the synchronous model used by WSGI. Andrew Godwin created the initial specification and directed its early implementation within the Channels project. The design subsequently became independent of Django and developed into a general interface used by multiple servers and frameworks in the Python ecosystem.
WSGI models an application as a callable that receives request metadata and returns an iterable containing the response body. That structure corresponds closely to a finite HTTP transaction but does not directly express a connection whose events arrive over an extended interval. Early asynchronous Python systems addressed this mismatch through framework-specific interfaces. ASGI instead standardized an event-oriented boundary between the protocol server and the application.
The first published form, retrospectively called ASGI 2, used two callable stages. The server first invoked an application with a scope, receiving a connection-specific callable that subsequently handled incoming and outgoing events. ASGI 3 simplified this structure into one asynchronous callable with the conceptual signature application(scope, receive, send). Compatibility adapters can translate between the two forms, although contemporary implementations generally expose the single-callable interface.
During the 2018 revision cycle, You Watanabe designed the lifespan extension and integrated its startup and shutdown event model into the developing specification. The extension established a protocol-level interval during which an application could create and release resources outside any individual network connection. Its later revision added explicit failure messages, allowing application startup or shutdown failure to be represented within the same event-exchange model rather than inferred solely from process termination.
Interface model
The scope is a mapping that describes the immutable or connection-wide properties visible to an application. Every scope contains a protocol type and an ASGI version descriptor, while each protocol contributes fields appropriate to its own semantics. An HTTP scope can include the request method, the raw path, decoded path information, headers, and addressing data. A WebSocket scope describes the opening handshake and can also contain the offered subprotocols.
The receive callable yields an event mapping generated by the server. Under HTTP, the application receives one or more request-body events and may later receive a disconnection notification. Under WebSocket, the event stream distinguishes the initial connection request from accepted messages and eventual disconnection. Awaiting receive allows the application task to suspend cooperatively until another event becomes available through the server's event loop.
The send callable transfers an application-generated event to the server. An HTTP response begins with an event containing status and header information, after which response-body events carry the content. WebSocket applications can accept or reject the opening connection and can later transmit messages or close the session. Event types are namespaced strings, which permits protocol extensions to coexist with the core interface without changing the Python calling convention.
ASGI does not define a network protocol between machines. The interface normally exists inside one Python process, even when a deployment places a reverse proxy or another network server in front of the ASGI server. Nor does the specification determine the internal concurrency architecture of an application. A server may associate connections with coroutines managed by asyncio, while an implementation based on another asynchronous runtime can preserve the same observable contract.
Protocol sub-specifications
The HTTP and WebSocket sub-specification defines how transport-level activity is converted into ASGI events. For HTTP, the scope represents one request even when the underlying transport uses a persistent connection. This distinction prevents transport connection reuse from becoming part of application state. Streaming request and response bodies are represented by repeated events whose continuation field indicates whether further content remains.
WebSocket handling has a different lifetime. The scope begins during the opening handshake and remains active until the connection closes. Messages can travel in either direction after acceptance, so neither side's event sequence is constrained to the single-response pattern associated with ordinary HTTP. The server retains responsibility for framing, masking, and other details defined by the WebSocket wire protocol, while the application exchanges complete text or binary messages through the ASGI interface.
The lifespan sub-specification describes the lifetime of an application within an event loop. A server opens a lifespan scope and sends a startup event before beginning normal service. At process termination it sends a shutdown event through the same scope. The protocol thereby associates initialized resources with the loop in which later requests execute, which is significant for objects whose internal state is bound to a particular asynchronous runtime.
ASGI also defines an extension mechanism through information recorded in the scope. A protocol server can announce additional behavior without altering the baseline event vocabulary for implementations that do not use it. This mechanism has been applied to features whose semantics depend on the server, including facilities for transferring response data from files and for reporting details about HTTP response completion.
Servers and application frameworks
An ASGI server implements the network-facing side of the interface. Daphne originated alongside Django Channels and supplied an early production implementation. Uvicorn implements ASGI using asynchronous Python event-loop facilities and can employ alternative HTTP protocol and loop implementations. Hypercorn provides the same application boundary while supporting several HTTP versions and multiple asynchronous execution libraries.
Frameworks implement the application-facing side. Django exposes an ASGI entry point in addition to its WSGI interface, with asynchronous behavior depending on the framework component and middleware involved. Starlette organizes its request handling, WebSocket support, middleware, and lifespan behavior directly around ASGI. FastAPI builds its web application layer on Starlette and therefore inherits the same server interface. Quart applies an asynchronous architecture to an API modeled after Flask.
ASGI middleware is itself an ASGI application that wraps another application. It can inspect or transform a scope before invoking the wrapped component, and it can interpose on the receive and send callables to transform events. Unlike middleware designed only for finite HTTP responses, ASGI middleware may remain active for the entire lifetime of a WebSocket connection. Its state must consequently be associated with the individual scope rather than stored in mutable attributes shared across concurrent calls.
Relationship to WSGI
ASGI preserves WSGI's central separation between servers and application code but changes the temporal model of their interaction. WSGI assumes that the server invokes the application in response to an HTTP request and consumes the returned iterable. ASGI represents communication as a sequence of asynchronously exchanged events, permitting input and output to occur at different times and in patterns that are not reducible to one returned iterable.
A WSGI application can be exposed through an ASGI compatibility wrapper. Such a wrapper constructs the WSGI environment from the HTTP scope, presents the request body through a synchronous interface, and converts the resulting status, headers, and body into ASGI response events. This translation does not convert the application's internal execution into asynchronous code, and it cannot give a WSGI application native WebSocket semantics because WSGI defines no corresponding connection model.
The reverse translation is less general. An ASGI application restricted to finite HTTP exchanges can be adapted to a synchronous host by running an asynchronous environment around each request. An application that depends on bidirectional communication or process lifespan events has no complete representation under the WSGI contract. The relationship is therefore one of partial interoperability rather than equivalence.
Concurrency and execution semantics
ASGI permits multiple application instances to progress concurrently within one process. Cooperative scheduling occurs when an application awaits input, output, or another asynchronous operation. This model does not imply that arbitrary CPU-bound work executes in parallel; computation that does not yield can still delay other tasks sharing the event loop. Servers and frameworks may delegate blocking operations to threads or processes, but that delegation lies outside the core interface.
Connection state is represented by the lifetime of the application invocation. Data stored in local variables remains specific to that invocation, whereas objects held at module or application level can be shared among many connections. This distinction follows from ASGI's concurrency model and is especially consequential for middleware, where mutable per-connection state stored on a shared instance can be observed by unrelated requests.
Error handling is divided between protocol-defined events and ordinary Python exceptions. A lifespan application can send an explicit startup or shutdown failure event. During other protocol interactions, an unhandled exception terminates the application invocation and is processed according to the server's error policy. Once a connection has closed, attempts to transmit further events can raise an exception, enabling the application to observe that its previous communication channel is no longer available.