πŸ™ tako
Concepts

Runtimes

Tako's dual-runtime model β€” Tokio vs Compio, which transports each supports, TLS and HTTP/2 coverage, and how to switch.

Tako runs on two async runtimes, chosen at build time. The application model β€” Router, handlers, extractors, middleware, responders β€” is identical on both. Transport availability and some middleware adapters differ. Router and route timeouts work on both; middleware::timeout::Timeout exists only on Tokio.

  • Tokio (default) β€” multi-threaded, work-stealing scheduler with Send futures end-to-end. This is what the standalone Server builder targets.
  • Compio (opt-in via the compio feature) β€” single-threaded thread-per-core over io_uring / IOCP / kqueue. Futures are !Send and pinned to the runtime thread that produced them.

One runtime selection per build

Without compio, Tako selects Tokio. Enabling compio switches the HTTP server, router timers, middleware, queues, and per-thread workers to Compio. cargo build --all-features compiles and selects Compio; the Tokio-only raw QUIC helper (RawQuicSession) is excluded from that build. To use it, choose a Tokio feature set without compio.

Switching runtimes

By default you get Tokio. To build on Compio, disable defaults and enable the compio feature; add compio-tls for TLS on that runtime. Transport features such as ws work on either runtime.

[dependencies]
tako-rs = "2"
[dependencies]
tako-rs = { version = "2", default-features = false, features = [
  "compio",
  "compio-tls",
  "ws",
] }

The umbrella crate swaps the server type for you: with compio on, the re-exports surface CompioServer / CompioServerBuilder instead of Server / ServerBuilder. The core router API is shared by both. Start servers with the selected builder and its try_spawn_* methods.

Transport coverage

Every transport runs on both runtimes:

ProtocolTokioCompioFeature flag
HTTP/1.1yesyesdefault
HTTP/2yesyeshttp2
HTTP/3 (QUIC)yesyeshttp3
TLS (rustls)yesyestls / compio-tls
WebSocketyesyesws
WebTransportyesyeswebtransport
SSEyesyessse
gRPC (unary and streaming)yesyesgrpc
Raw TCPyesyesdefault
Raw UDPyesyesudp
Unix socketsyesyesdefault (unix only)
PROXY protocol v1/v2yesyesproxy-protocol

HTTP/2 over TLS, cleartext h2c, HTTP/3, WebTransport, Unix sockets, and PROXY protocol are supported on both runtimes. Only the raw QUIC helper (RawQuicSession) is Tokio-only. Raw TCP and UDP use each runtime’s native I/O API.

Crossing the runtime boundary internally

Where the framework itself must cross the boundary β€” for example, hyper's HTTP/2 service running over Compio TLS β€” it uses send_wrapper::SendWrapper to satisfy hyper's Send bound at the type level. The wrapper panics on cross-thread access, so a misuse becomes a loud panic rather than undefined behaviour. The soundness contract is per-runtime, not global: every wrapped future is constructed and polled on the same Compio runtime thread and never handed back to a multi-threaded Tokio executor.

Thread-per-core

The per-thread and per-thread-compio features host the same thread-safe Router on N current-thread workers, fanned out with SO_REUSEPORT; Tokio workers also hand new connections to the least busy worker. serve_per_thread(addr, router, config) blocks until Ctrl+C or SIGTERM and then drains the workers. spawn_per_thread(addr, router, config) returns the worker thread handles and a PerThreadShutdown for explicit control. Enabling per-thread-compio also selects Compio for all shared runtime-dependent code. These entry points live in tako-rs-server-pt.

Last updated on

On this page