Skip to content

Interceptors

Interceptors are the primary mechanism for cross-cutting concerns in Connectum. They wrap RPC calls at the transport level -- adding error handling, timeouts, retries, validation, and more -- without touching business logic.

Quick Start

typescript
import { createServer } from '@connectum/core';
import { createDefaultInterceptors } from '@connectum/interceptors';
import routes from '#gen/routes.js';

const server = createServer({
  services: [routes],
  port: 5000,
  interceptors: createDefaultInterceptors({
    timeout: { duration: 10_000 },
    retry: { maxRetries: 5 },
  }),
  shutdown: { autoShutdown: true },
});

await server.start();

Key Concepts

How Interceptors Work

A ConnectRPC interceptor is a function that receives next and returns a handler. The handler gets control before and after each request, forming a layered pipeline:

Request  -> interceptor1 -> interceptor2 -> ... -> handler
Response <- interceptor1 <- interceptor2 <- ... <- handler

Built-in Chain

createDefaultInterceptors() provides 8 production-ready interceptors in a fixed order:

#InterceptorPurposeDefault
1errorHandlerNormalizes errors into ConnectErrorEnabled
2timeoutLimits request execution timeEnabled (30s)
3bulkheadLimits concurrent requestsEnabled (capacity 10, queue 10)
4circuitBreakerPrevents cascading failuresEnabled (threshold 5)
5retryRetries transient failures with exponential backoffEnabled (3 retries)
6fallbackGraceful degradationDisabled
7validationValidates via @connectrpc/validateEnabled
8serializerJSON serialization for protobufEnabled

Per-Method Routing

Three approaches for applying interceptors selectively:

ScenarioApproach
Interceptor bound to a specific service routerConnectRPC native (router.service())
Declarative routing by patterncreateMethodFilterInterceptor
Dynamic logic, filtering by request contentCustom interceptor

Learn More