Our Angular monorepo talks to a gRPC backend. Every service call passes through six interceptors: auth token injection, custom metadata, retry with backoff, deadline enforcement, request logging, and error mapping. That means six files, six @Injectable() decorators, six classes implementing GrpcInterceptor , and a provider array where the order matters but nothing enforces it. I replaced all of it with composable factory functions. One provider call in app.config.ts . No classes, no decorators, no manual provider registration. The library is nx-grpc-kit . The problem: class-based interceptor sprawl Here is what a single interceptor looked like in the old setup: @ Injectable () export class AuthInterceptor implements GrpcInterceptor { constructor ( private authService : AuthService ) {} intercept < T > ( request : GrpcRequest < T > , next : GrpcHandler ): Observable < GrpcEvent < T >> { const token = this . authService . getToken (); if ( token ) { request . metadata .β¦