3 min read

Nest.js | Memoization vs Cache

Memoization and caching are related but distinct concepts. Memoization is a technique where a function stores the results of previous…
Nest.js | Memoization vs Cache

Memoization and caching are related but distinct concepts. Memoization is a technique where a function stores the results of previous invocations and returns the cached result when the same input is provided again. This can greatly improve the performance of a function by avoiding redundant computation.

Caching, on the other hand, is a broader concept that involves storing data in a temporary storage area (such as memory or disk) in order to speed up future access to that data. Caching can be used in various parts of an application, such as database queries, API calls, or even at the level of individual functions like memoization.

In Nest.js, caching can be implemented using the caching modules such as @nestjs/common or @nestjs/microservices and it can be used to cache HTTP responses, database results, or other data. This can be useful to improve the performance of your application and reduce the load on your data sources.

Here’s an example of how you could use the @nestjs/common caching module to cache the results of an HTTP endpoint in a Nest.js controller:

import { Controller, Get, UseInterceptors } from '@nestjs/common';
import { CachingInterceptor } from '@nestjs/common/interceptors/caching.interceptor';

@Controller('users')
@UseInterceptors(CachingInterceptor)
export class UserController {
    @Get()
    @CacheInterceptor({
        ttl: 30, // time to live in seconds
        max: 100, // maximum number of items in cache
    })
    async findAll(): Promise<User[]> {
        // This will be cached for 30 seconds
        return this.userService.findAll();
    }
}

In this example, the findAll method is decorated with the @CacheInterceptor decorator provided by the @nestjs/common caching module. This will cache the result of the method for 30 seconds and will store a maximum of 100 items in cache.

You can also use caching in other parts of your application, such as in a service layer to cache results from a database or in a pipe to cache results from an external API.

It’s also possible to use third-party caching libraries such as ioredis, memcached or redis in Nest.js with the help of a module such as @nestjs/bull or @nestjs/microservices.

import { Injectable } from '@nestjs/common';
import { ClientOpts, createClient } from 'redis';

@Injectable()
export class MyService {
    private redis = createClient({ host: 'localhost', port: 6379 });

    async getData(key: string): Promise<string> {
        return new Promise((resolve, reject) => {
            this.redis.get(key, (err, data) => {
                if (err) {
                    reject(err);
                } else {
                    resolve(data);
                }
            });
        });
    }

    async setData(key: string, value: string): Promise<void> {
        return new Promise((resolve, reject) => {
            this.redis.set(key, value, 'EX', 60, (err) => {
                if (err) {
                    reject(err);
                } else {
                    resolve();
                }
            });
        });
    }
}

It’s important to note that caching can also make your code less predictable and harder to debug, so it should be used with caution and only when it is appropriate for the specific use case.


Memoization can be implemented in Nest.js by decorating a function with a decorator that checks for a cached result before executing the function. There are libraries that provide this functionality, such as fast-memoize or memoizee.

Here’s an example of how you could use the fast-memoize library to implement memoization in a Nest.js service:

import { Injectable } from '@nestjs/common';
import memoize from 'fast-memoize';

@Injectable()
export class MyService {
    // This function will be decorated with the memoize decorator
    @memoize()
    expensiveFunction(input: string): string {
        // Do some expensive computation here
        return expensiveComputation(input);
    }
}

In this example, the expensiveFunction method is decorated with the memoize decorator provided by the fast-memoize library. Now, whenever the expensiveFunction is called with the same input, it will return the cached result instead of executing the expensive computation again.

You can also pass options to the memoize decorator to customize its behavior, for example to set a maximum size for the cache or to specify a custom equality function.

import { Injectable } from '@nestjs/common';
import memoize from 'fast-memoize';

@Injectable()
export class MyService {
    @memoize({
        maxSize: 10,
        isEqual: (a, b) => a.id === b.id
    })
    expensiveFunction(input: MyInputType): string {
        // Do some expensive computation here
        return expensiveComputation(input);
    }
}

It’s important to note that memoization can make your code less predictable and harder to debug, so it should be used with caution and only when it is appropriate for the specific use case.

In summary, memoization is a specific implementation of caching that is applied to function calls, whereas caching can be used in a variety of contexts to improve performance by storing data in a temporary storage area.