Transport Selection Guide
Kruda ships with three transports. The default is Wing on Linux, fasthttp on macOS.
When to use which
| Feature needed | Transport | Why |
|---|---|---|
| Maximum throughput (plaintext, JSON, DB) | Wing (default on Linux) | epoll+eventfd, zero-copy, no goroutine-per-conn |
| SSE (Server-Sent Events) | net/http | SSE requires http.Flusher streaming |
| Session cookies / Set-Cookie headers | Wing or net/http | Wing keeps headers by falling back from its zero-copy fast path when needed |
| HTTP/2, TLS termination | net/http | Wing is HTTP/1.1 only |
| WebSocket | net/http | WebSocket upgrade needs full HTTP semantics |
| Battle-tested HTTP/1.1 (chunked, expect-100) | fasthttp | Mature, widely deployed |
Usage
// Default: Wing on Linux, fasthttp on macOS, net/http on Windows
app := kruda.New()
// Explicit net/http (for SSE, sessions, HTTP/2, TLS)
app := kruda.New(kruda.NetHTTP())
// Explicit fasthttp
app := kruda.New(kruda.FastHTTP())
// Explicit Wing
app := kruda.New(kruda.Wing())Environment override
KRUDA_TRANSPORT=nethttp ./myapp # force net/http
KRUDA_TRANSPORT=wing ./myapp # force Wing
KRUDA_TRANSPORT=fasthttp ./myapp # force fasthttpAutomatic fallback
- Wing + TLS config → auto-falls back to net/http (for HTTP/2)
- Wing on Windows → auto-falls back to net/http
- Unsupported OS → defaults to fasthttp (macOS) or net/http (Windows)
Production TLS: terminate in front of Wing
Wing does not implement TLS. When WithTLS is configured, Kruda automatically serves through the net/http transport instead — you keep HTTPS and gain HTTP/2, but you are no longer running Wing, so Wing benchmark numbers do not apply to a direct-TLS deployment.
To keep Wing's performance in production, terminate TLS in front of the app — nginx, Caddy, HAProxy, or a cloud load balancer — and let Kruda serve plaintext HTTP/1.1 behind it. This is the standard deployment shape for epoll-based Go servers. Two things to set:
app := kruda.New(
kruda.WithTrustProxy(true), // client IPs come from X-Forwarded-For
)and make the proxy strip/overwrite inbound X-Forwarded-For so clients cannot spoof it. If you need TLS directly on the app process (no proxy), use kruda.WithTLS(...) and accept the net/http transport — that is the supported and honest trade.
Wing limitations
Wing is optimized for raw throughput. It intentionally skips some HTTP features:
- Prebuilt static responses bypass middleware —
StaticTextandStaticJSONwrite route-level prebuilt responses directly. Use normal handlers when a response needs middleware, lifecycle hooks, CORS, cookies, orWithSecureHeaders(). - Incremental responses need a preset — plain handlers write fixed
Content-Lengthresponses. SSE and chunked streaming (c.SSE()/c.Stream()) work on Wing via thekruda.Streamroute preset, and WebSocket viaws.HandleFunc(thekruda.Hijackpreset) — but a default route does not stream. - No HTTP/2 — Wing speaks HTTP/1.1 only. Use
kruda.NetHTTP()with TLS for HTTP/2. - No chunked transfer encoding — Wing pre-computes Content-Length.
App.Serve(listener)re-binds on Wing — Wing serves oneSO_REUSEPORTsocket per worker, so it adopts the listener's address and closes the passed file descriptor rather than serving it. For systemd socket activation or graceful-restart fd-passing, usekruda.NetHTTP()(or fasthttp on macOS), which serve the supplied fd directly.
For apps that mix high-throughput API routes with session/SSE routes, run two instances or use net/http for the full app.
