Bird
Raised Fist0
NestJSframework~5 mins

Timeout interceptor in NestJS

Choose your learning style10 modes available
Introduction

A timeout interceptor helps stop a request if it takes too long. This keeps your app fast and avoids waiting forever.

When you want to limit how long a request can take before stopping it.
To avoid slow responses blocking other users.
When calling external services that might hang or be slow.
To improve user experience by failing fast on delays.
When you want to add a global timeout rule for all or some requests.
Syntax
NestJS
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, RequestTimeoutException } from '@nestjs/common';
import { Observable, throwError, TimeoutError } from 'rxjs';
import { timeout, catchError } from 'rxjs/operators';

@Injectable()
export class TimeoutInterceptor implements NestInterceptor {
  intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
    return next.handle().pipe(
      timeout(5000), // time in milliseconds
      catchError(err => {
        if (err instanceof TimeoutError) {
          return throwError(() => new RequestTimeoutException());
        }
        return throwError(() => err);
      }),
    );
  }
}

The timeout operator sets the max wait time in milliseconds.

If the timeout happens, it throws a TimeoutError, which we catch and convert to a NestJS RequestTimeoutException.

Examples
Use this to set a 3-second timeout for the request.
NestJS
timeout(3000) // sets timeout to 3 seconds
Use this to allow a longer 10-second timeout.
NestJS
timeout(10000) // sets timeout to 10 seconds
This catches the timeout error and sends a clear message back.
NestJS
catchError(err => {
  if (err instanceof TimeoutError) {
    return throwError(() => new RequestTimeoutException('Request took too long'));
  }
  return throwError(() => err);
})
Sample Program

This controller has two routes. The fast route responds quickly within the timeout. The slow route takes longer than the 5-second timeout and will cause a timeout error.

NestJS
import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { Observable, of } from 'rxjs';
import { delay } from 'rxjs/operators';
import { TimeoutInterceptor } from './timeout.interceptor';

@Controller('test')
@UseInterceptors(TimeoutInterceptor)
export class TestController {
  @Get('fast')
  fastResponse(): Observable<string> {
    return of('Fast response').pipe(delay(1000)); // responds in 1 second
  }

  @Get('slow')
  slowResponse(): Observable<string> {
    return of('Slow response').pipe(delay(6000)); // responds in 6 seconds
  }
}
OutputSuccess
Important Notes

Set the timeout value based on your app's needs and expected response times.

Use this interceptor globally or on specific controllers/routes.

Remember to import and provide the interceptor properly in your module.

Summary

A timeout interceptor stops requests that take too long.

It uses RxJS timeout and catches errors to send a timeout response.

Use it to keep your app responsive and avoid waiting forever.

Practice

(1/5)
1.

What is the main purpose of a TimeoutInterceptor in a NestJS application?

easy
A. To stop requests that take too long and prevent hanging.
B. To log every request made to the server.
C. To cache responses for faster retrieval.
D. To authenticate users before processing requests.

Solution

  1. Step 1: Understand the role of TimeoutInterceptor

    The TimeoutInterceptor is designed to limit how long a request can take before it is stopped.
  2. Step 2: Compare options with the interceptor's purpose

    Only To stop requests that take too long and prevent hanging. describes stopping long requests to avoid hanging, which matches the interceptor's goal.
  3. Final Answer:

    To stop requests that take too long and prevent hanging. -> Option A
  4. Quick Check:

    TimeoutInterceptor stops long requests = D [OK]
Hint: TimeoutInterceptor stops slow requests to keep app responsive [OK]
Common Mistakes:
  • Confusing timeout with logging or caching
  • Thinking it handles authentication
  • Assuming it speeds up all requests
2.

Which of the following is the correct way to apply a timeout of 5 seconds using RxJS timeout operator inside a NestJS interceptor?

return next.handle().pipe( ... )
easy
A. return next.handle().pipe(timeout(500));
B. return next.handle().pipe(timeout(5));
C. return next.handle().pipe(timeout(5000));
D. return next.handle().pipe(timeout(50));

Solution

  1. Step 1: Understand RxJS timeout parameter

    The timeout operator expects time in milliseconds, so 5 seconds is 5000 ms.
  2. Step 2: Match the correct timeout value

    Only return next.handle().pipe(timeout(5000)); uses 5000 which equals 5 seconds; others use incorrect values.
  3. Final Answer:

    return next.handle().pipe(timeout(5000)); -> Option C
  4. Quick Check:

    Timeout in ms for 5 seconds = 5000 [OK]
Hint: Timeout value is always in milliseconds in RxJS [OK]
Common Mistakes:
  • Using seconds instead of milliseconds
  • Using too small timeout values
  • Forgetting to import timeout operator
3.

Given this TimeoutInterceptor code snippet, what will be the output if the request handler takes 7 seconds to respond?

intercept(context, next) {
  return next.handle().pipe(
    timeout(5000),
    catchError(err => throwError(() => new RequestTimeoutException()))
  );
}
medium
A. The request completes successfully after 7 seconds.
B. The request throws a RequestTimeoutException after 5 seconds.
C. The request throws a generic error immediately.
D. The request never completes or errors.

Solution

  1. Step 1: Analyze timeout duration and handler delay

    The timeout is set to 5000 ms (5 seconds), but the handler takes 7 seconds, which is longer.
  2. Step 2: Understand error handling on timeout

    When timeout triggers, catchError throws a RequestTimeoutException, so the request errors after 5 seconds.
  3. Final Answer:

    The request throws a RequestTimeoutException after 5 seconds. -> Option B
  4. Quick Check:

    Handler > timeout triggers RequestTimeoutException = A [OK]
Hint: Timeout triggers error if handler exceeds set milliseconds [OK]
Common Mistakes:
  • Assuming request completes despite timeout
  • Confusing generic error with RequestTimeoutException
  • Ignoring catchError usage
4.

Identify the error in this TimeoutInterceptor implementation:

intercept(context, next) {
  return next.handle().pipe(
    timeout(3000),
    catchError(err => {
      throw new RequestTimeoutException();
    })
  );
}
medium
A. Using throw inside catchError instead of returning an observable error.
B. Timeout value should be in seconds, not milliseconds.
C. Missing import for RequestTimeoutException.
D. The interceptor must return a Promise, not an Observable.

Solution

  1. Step 1: Check error handling inside catchError

    Inside catchError, throwing an error directly breaks the observable chain; it should return an observable error using throwError.
  2. Step 2: Validate other options

    Timeout is correctly in milliseconds, imports are assumed correct, and interceptors return Observables, so only Using throw inside catchError instead of returning an observable error. is the error.
  3. Final Answer:

    Using throw inside catchError instead of returning an observable error. -> Option A
  4. Quick Check:

    Use throwError() inside catchError, not throw [OK]
Hint: Inside catchError, always return throwError() observable [OK]
Common Mistakes:
  • Throwing error directly inside catchError
  • Confusing milliseconds with seconds
  • Assuming interceptors return Promises
5.

You want to create a TimeoutInterceptor that applies a 3-second timeout globally but allows a specific route to override it with a 10-second timeout. Which approach correctly implements this behavior?

hard
A. Set timeout to 10 seconds globally and manually check route inside interceptor to reduce to 3 seconds if needed.
B. Apply two TimeoutInterceptors globally, one with 3 seconds and one with 10 seconds; the last one wins.
C. Create two separate interceptors and apply the 10-second one only on the specific route without global interceptor.
D. Use a global TimeoutInterceptor with 3 seconds and a custom decorator to set metadata for 10 seconds, then read metadata inside the interceptor to override timeout.

Solution

  1. Step 1: Understand global and route-specific timeout needs

    Global interceptor applies 3 seconds by default; specific routes can override by metadata.
  2. Step 2: Implement override using custom decorator and metadata

    Custom decorator sets timeout metadata on route; interceptor reads it and uses that value if present.
  3. Step 3: Evaluate other options

    Applying multiple global interceptors causes conflicts; setting longer timeout globally and reducing for most routes reverses the logic; creating separate interceptors without a global one loses timeout protection on other routes.
  4. Final Answer:

    Use a global TimeoutInterceptor with 3 seconds and a custom decorator to set metadata for 10 seconds, then read metadata inside the interceptor to override timeout. -> Option D
  5. Quick Check:

    Use metadata + decorator to override global timeout [OK]
Hint: Use custom decorator + metadata to override global interceptor timeout [OK]
Common Mistakes:
  • Applying multiple global interceptors causing conflicts
  • Hardcoding timeout values without metadata
  • Not reading route metadata inside interceptor
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard