Starlette 1.9.0 release shifts ASGI ecosystem priorities
Starlette 1.9.0 introduces a 100% type annotated codebase and 100% test coverage for the lightweight ASGI toolkit. This release provides essential tools for asynchronous web services, including WebSocket support and a TestClient built on httpx2.
The Starlette 1.9.0 release updates
The Oct 18, 2026, release of Starlette 1.9.0 changes how developers view lightweight ASGI foundations. This version uses Python 3 to provide a toolkit for building asynchronous web services. Tom Christie created this framework to maintain a concise codebase with few hard dependencies. I observe 100% test coverage and a 100% type annotated codebase in this release. The toolkit supports both asyncio and trio backends. It includes WebSocket support and in-process background tasks. The framework includes CORS, GZip, Static Files, and Streaming responses. Users also access Session and Cookie support. The release includes a TestClient built on httpx2. I find the framework performance great against independent benchmarks. This update arrived via twine/7.0.0 CPython/3.13.14. The 2.7 MB source distribution and the 80.3 kB wheel file provide production-ready solutions for Python developers. The SHA-256 checksum for the source distribution is 3d931de246ed870e35ce605974440816ef895e592f255d1396cfdf191d4c4318, while the SHA-256 checksum for the wheel file is fd3f159936e882d06c1108f8468f7cda2cf85fc6a592a50edbd175e882c2ddc. The BLAKE2b-256 checksum for the source distribution is adeb4e197bf26b023abafc5e9043ec8710d7de0fcb032d0969045236d72aa0b1, and the BLAKE2b-256 checksum for the wheel is f393181df626999b9aca1d87e5cfda131dac87e3cdaebf668662f7206ca3470. This update provides the necessary tools for modern, high-speed asynchronous web applications.
Middleware chains and the FastAPI foundation
FastAPI builds directly on top of Starlette. This relationship means FastAPI inherits Starlette’s ASGI capabilities. Starlette creates a middleware stack that functions as a chain of responsibility. Each ASGIApp receives another ASGIApp as a dependency. This chain continues until the process reaches the ExceptionMiddleware, which wraps the Router to handle exceptions. The Router itself acts as an ASGIApp and manages a list of routes. The modularity inherent in Starlette’s design promotes the building of reusable components that work across any ASGI framework, which helps to create an ecosystem of shared middleware and mountable applications for developers who require highly scalable web services in production environments. This separation makes understanding each component in isolation easier. The middleware system facilitates tasks like authentication and CORS. I would tell you that the clean API separation helps developers manage individual components. One developer noted that the middleware can modify the request before it reaches the application or alter the response before it goes to the client. The ServerErrorMiddleware sits as the outermost middleware to handle uncaught errors. The ExceptionMiddleware sits as the innermost middleware to deal with handled exception cases in the routing or endpoints. The middleware list contains Middleware objects that run for every request. These objects include the routes, which are a sequence of BaseRoute objects that serve incoming HTTP and WebSocket requests. The exception_handlers parameter provides a mapping of integer status codes or exception class types onto callables. These handlers take request and exc as parameters and return a response. You can define these handlers as either standard functions or async functions. The Router implements its own app function to match a route and execute its path operation function. If the router finds a matching route, it calls the route’s handle function. This handle function calls the endpoint, which is the function or class you passed when creating the Starlette app. This structure ensures that the application can manage various request and response flows efficiently.
Implementation details and required dependencies
Developers use the starlette.applications.Starlette class to create applications. This class includes parameters like debug for error tracebacks and routes for serving requests. It also allows setting max_body_size to limit the total size in bytes of an HTTP request body. The lifespan parameter uses a context function for startup and shutdown tasks, replacing the older on_startup and on_shutdown handlers. You can store extra state on the app instance using the app.state attribute. When a request exists, the developer accesses the app instance via request.app.
| Dependency | Required for |
|---|---|
| httpx2 | TestClient |
| jinja2 | Jinja2Templates |
| opentelemetry-api | OpenTelemetryMiddleware |
| python-multipart | request.form() |
| itsdangerous | SessionMiddleware |
| pyyaml | SchemaGenerator |
Starlette only requires anyio. I note the optional dependencies for specialized tasks. The python-multipart library supports form parsing with request.form(). The itsdangerous library supports SessionMiddleware. The pyyaml library supports SchemaGenerator. The jinja2 library supports Jinja2Templates. For OpenTelemetryMiddleware, you need opentelemetry-api. The TestClient requires httpx2. You can install all of these with pip install starlette[full]. This setup allows for a very minimal footprint if you do not need these extras. Many developers choose between different ASGI frameworks based on how they manage these dependencies. You can run the application using uvicorn, and using the –reload flag enables auto-reloading on code changes. This flexibility allows developers to swap server implementations based on their production needs. The implementation of the Starlette class involves a call method that receives the scope, receive, and send parameters from the ASGI server. This design allows the middleware stack to wrap the router and provide the necessary context for each request. Does the simplicity of the Starlette toolkit outweigh the complexity of larger frameworks?