If you’re running FastAPI, you’re running Starlette underneath it, whether you think about it or not. At Scout, we spend a lot of time thinking about what happens at that ASGI layer, since that’s exactly where our Python agent hooks in to give you request-level visibility. Starlette 1.7.0 just landed, and it’s a release worth reading closely if you care about tracing, routing, or just keeping your app running on a supported dependency chain.
This is the release version of a change we covered back in August while it was still an open PR — it’s now shipped, and it brought a breaking change along with it.
What Changed
Starlette 1.7.0 ships three headline changes: an experimental OpenTelemetryMiddleware, direct exposure of the matched route through scope["route"], and a dependency bump that drops AnyIO 3 support entirely.
The OpenTelemetryMiddleware is the biggest addition. Starlette now ships its own opt-in HTTP server tracing middleware, with support for URL exclusions and custom tracer providers. That’s a meaningful shift: until now, getting OpenTelemetry spans out of a Starlette app meant reaching for opentelemetry-instrumentation-asgi or building your own middleware. Having it built in lowers the barrier for teams who want basic request tracing without adding another dependency.
There’s a catch worth flagging clearly: this middleware is explicitly marked experimental. The Starlette maintainers note its API and emitted telemetry may change in minor releases without a deprecation period. If you’re adopting it, treat it the way you’d treat any pre-1.0 API: pin your Starlette version and read the changelog before every upgrade.
The second change is quieter but arguably more useful day to day: the matched route is now available directly on the ASGI scope via scope["route"]. Previously, anything that needed to know “which route handled this request” (middleware, instrumentation libraries, logging setups) had to do its own route-matching logic, often by walking the router’s route list and re-running the match. Now that information is just sitting on the scope, ready to read.
Why This Matters for Your App
For most FastAPI and Starlette users, the practical impact of this release breaks down into three buckets.
If you use custom middleware for logging or metrics, scope["route"] removes a whole category of brittle code. Route-matching heuristics tend to drift out of sync with the actual router, especially in apps with mounted sub-applications or dynamically registered routes. Reading the match directly from the scope is both simpler and more accurate.
If you’ve been putting off adding tracing, the built-in OpenTelemetryMiddleware is a reasonable place to start, especially for smaller services where pulling in a separate instrumentation package felt like overkill. Just remember the experimental label applies here, so this is a “try it in staging first” kind of feature, not a “flip it on in production Friday afternoon” one.
If you’re pinned to AnyIO 3, this release will break your upgrade path. Starlette 1.7.0 now requires anyio>=4.0.0,<5, and support for AnyIO 3 is gone, not deprecated. If your app or one of your dependencies still pins AnyIO 3, you’ll need to resolve that before you can take 1.7.0. Worth checking your lockfile now rather than finding out during a routine dependency update.
The release also includes a long list of smaller fixes worth a skim: QUERY HTTP method support across HTTPEndpoint, CORS, and OpenAPI 3.2 schema generation; response trailers exposed through TestClient; partitioned cookie support in SessionMiddleware; and a fix that moves debug traceback rendering in ServerErrorMiddleware off the main thread and onto a worker thread, which matters if you’ve ever seen a slow error page block other requests.
Where This Intersects With Monitoring
Route naming is one of those things that sounds trivial until it’s wrong. If your monitoring tool can’t tell that /users/123 and /users/456 are the same endpoint, your dashboards fill up with noise instead of signal. That’s exactly the kind of problem scope["route"] helps solve at the framework level, and it’s the same problem Scout’s Python monitoring agent works to solve at the instrumentation level, whether Starlette exposes the route cleanly or not.
The tracing story is worth thinking through carefully if you’re evaluating Starlette’s new middleware alongside an APM tool like Scout. Running two tracing systems on the same request path isn’t inherently a problem, but it’s worth verifying they’re not both wrapping the same spans redundantly, especially while OpenTelemetryMiddleware is still labeled experimental and its behavior could shift under you.
If you’d rather not manage that overlap yourself, that’s the kind of thing application performance monitoring is built for: request tracing, database query timing, and background job visibility, all in one place, without needing to hand-roll OpenTelemetry configuration or worry about double-instrumenting a request.
Try Scout on Your Starlette or FastAPI App
Whether or not you adopt Starlette’s new experimental tracing middleware, you still need a clear picture of where your app is spending time in production. Sign up for Scout Monitoring for free and get that out of the box for FastAPI, Starlette, Flask, and Django apps.
For application monitoring with errors, logs, and traces, Scout Monitoring provides the fastest insights without the bloat.