Skip to content

Add Serve::with_executor and Executor trait for custom task spawning#3704

Open
yulnr wants to merge 3 commits intotokio-rs:mainfrom
yulnr:feat/custom-serve-executor
Open

Add Serve::with_executor and Executor trait for custom task spawning#3704
yulnr wants to merge 3 commits intotokio-rs:mainfrom
yulnr:feat/custom-serve-executor

Conversation

@yulnr
Copy link
Copy Markdown

@yulnr yulnr commented Apr 1, 2026

Closes #3703

Motivation

axum::serve hardcodes TokioExecutor for spawning connection tasks and hyper's internal HTTP/2 tasks. This is the one thing that cannot be customized by wrapping axum's API from the outside, users are forced to reimplement the entire serve loop (~150 lines) just to swap the executor.

This is needed for use cases like runtime telemetry (e.g. dial9-tokio-telemetry) where spawned tasks must be wrapped to capture scheduling delays and wake events.

Solution

  • Add axum::serve::Executor trait for custom task spawning
  • Add Serve::with_executor() and WithGracefulShutdown::with_executor() builder methods that take an Executor

Default remains TokioExecutor so it's fully backward compatible.

Design

We define a new axum::serve::Executor trait rather than reusinghyper::rt::Executor<Fut> directly, because the latter is generic at the trait level and we can't bound E to cover all the internal future types hyper needs. The new trait uses a generic method instead, and a thin HyperExecutor<E> adapter bridges to hyper internally.

Testing

  • Existing serve tests pass
  • New serving_with_custom_executor end-to-end test with duplex IO
  • Compile test covers with_executor in both orderings (before and after with_graceful_shutdown)
  • Doc examples compile and run

@yulnr yulnr force-pushed the feat/custom-serve-executor branch from 95d06b8 to c284a08 Compare April 1, 2026 16:16
axum::serve previously hardcoded TokioExecutor for spawning connection
tasks and hyper's internal HTTP/2 tasks. Users who needed to instrument
or intercept spawned tasks (e.g. for telemetry) had to reimplement the
entire serve loop.

Add a new axum::serve::Executor trait with a with_executor() builder
method on both Serve and WithGracefulShutdown. The default remains
TokioExecutor, so existing code is unaffected.
@yulnr yulnr force-pushed the feat/custom-serve-executor branch from c284a08 to 4fb0c8f Compare April 1, 2026 16:19
@yulnr yulnr changed the title Add Executor trait and Serve::with_executor for custom task spawning Add Serve::with_executor and Executor trait for custom task spawning Apr 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Allow customizing the executor used by axum::serve

1 participant