Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generics and Tower Stacks

Linkerd is an unusually strong example of generics as architecture.

Service<Req> associates a response, error, and future with one request type. NewService<T> associates a constructed service with one target type. Layer<S> maps an inner service type to a wrapped service type. Param<P> proves a target can supply a layer’s configuration. Together, they make invalid stack wiring a compile error.

Builder methods return impl Layer<..., Service = ...> and each .push() changes the enclosing Inbound<S>/Outbound<S> type. The enormous final type is optimized into direct calls. Enums such as Either<A, B> retain static dispatch for closed runtime branches.

Type erasure is applied at pressure points: buffered services need a uniform queued request type; recursive/dynamic routing needs cached heterogeneous boundaries; public application structs sometimes hide futures. BoxService, BoxCloneSyncService, boxed bodies, and the shared linkerd_error::Error stop type growth where flexibility outweighs inlining.

The design does not choose “generics or trait objects.” It composes statically for the hot path, then erases at queues, recursive boundaries, and application storage.