How to exclude a route from caching in nest.js

Learn how to ignore a route from caching by overriding CacheInterceptor

image.png I love working with Nest.js, it's such an excellent framework for teams to build a scalable backend server. Recently, I've been working on caching all our routes. It worked well for a few days then I noticed I missed an endpoint that can not be cached, which was to generate a coupon code. Imagine two customers ending up with the same coupon code. I immediately started looking at how to ignore a certain route while using global caching in nest.js but to my surprise, there is no pre-built decorator or config to do that. But there are simple ways to achieve that.

Nest.js uses CacheInterceptor to intercept our HTTP request and decide whether to cache it or not. We can create our own custom interceptor that extends default CacheInterceptor and add some logic to ignore a route.

A suggested way can be found on StackOverflow but I did not want to hard code the route paths in my interceptor.

There's another way we can do it by combining our custom CacheInterceptor and a CustomDecorator.

First, we need to create a custom cache interceptor. Note that this is slightly different from the accepted StackOverflow answer.

my-cache.interceptor.ts

import { CacheInterceptor, ExecutionContext } from '@nestjs/common';

export class MyCacheInterceptor extends CacheInterceptor {
  protected isRequestCacheable(context: ExecutionContext): boolean {
    const http = context.switchToHttp();
    const request = http.getRequest();

    const ignoreCaching: boolean = this.reflector.get(
      'ignoreCaching',
      context.getHandler(),
    );

    return !ignoreCaching || request.method === 'GET';
  }
}

Here, we're overriding a method on default interceptor isRequestCacheable which tells nest.js whether to go ahead and cache it or ignore it. In this method, we are using nest.js Reflector to get the metadata value. If metadata ignoreCaching is set to true, we tell nest.js to ignore it otherwise cache it if the request method is GET. We're going to create a custom decorator to set this metadata value.

Let's create a no-cache.decorator.ts file somewhere -

import { SetMetadata } from '@nestjs/common';

export const NoCache = () => SetMetadata('ignoreCaching', true);

We're almost done. Now let's test it. Let's use this decorator in our controller


@Controller('coupon')
export class CouponController {
  constructor(private readonly couponService: CouponService) {}

  @Get('code')
  @NoCache()
  code() {
    return this.couponService.generateCode();
  }

}

and, that's all. Now any controller which is decorated with NoCache will be ignored from caching. Pretty Neat right?