0PricingLogin
NestJS Enterprise Backend APIs · Lesson

Timeouts, Retries, and Bulkheads with Interceptors

Implement RxJS-based timeout and retry interceptors plus concurrency bulkheads for outbound calls.

Why Resilience Patterns Belong in Interceptors

Outbound calls to other services fail in three classic ways: they hang forever, they fail transiently, or they flood a slow dependency until it (and you) collapse. The three matching defenses are timeouts, retries, and bulkheads.

  • Timeout — cap how long any one call may run.
  • Retry — re-attempt a failed call a bounded number of times, ideally only for transient errors.
  • Bulkhead — cap how many calls run concurrently so one dependency can't exhaust your resources.

In NestJS these compose cleanly as NestInterceptors. An interceptor wraps the handler's RxJS stream, so we can layer timeout and retry operators on the response Observable without touching business logic.

The Interceptor Contract

A NestJS interceptor implements intercept(context, next) and returns an Observable. Calling next.handle() runs the route handler and gives you its result stream. Anything you pipe onto that stream — timeout, retry, catchError — applies to the response.

  • This is why resilience logic lives here: it is cross-cutting and stream-based.
  • Operators run in order, so placement of timeout vs retry changes behavior — we will exploit that.
import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

@Injectable()
export class LoggingInterceptor implements NestInterceptor {
  intercept(ctx: ExecutionContext, next: CallHandler): Observable<unknown> {
    const started = Date.now();
    // next.handle() executes the route handler; we pipe onto its stream.
    return next.handle().pipe(
      tap(() => console.log(`took ${Date.now() - started}ms`)),
    );
  }
}

All lessons in this course

  1. Timeouts, Retries, and Bulkheads with Interceptors
  2. Circuit Breakers for Downstream Failures
  3. Distributed Tracing with OpenTelemetry
  4. Defining SLOs and Error Budgets
← Back to NestJS Enterprise Backend APIs