Utilizing Keyv for Caching in NestJS: A Step-by-Step Guide
Table of Contents
Caching is an essential technique to enhance the performance of your application by storing frequently used data temporarily so that it can be quickly retrieved later. In this blog post, we'll explore how to use Keyv, a simple yet powerful key-value store for Node.js, to implement caching in a NestJS application. We will cover the basics of setting up Keyv with NestJS and demonstrate some examples of how to cache data effectively.
1. Setting Up the Project
First, let's create a new NestJS project using the Nest CLI:
$ npm i -g @nestjs/cli
$ nest new nestjs-keyv-cache
$ cd nestjs-keyv-cache
2. Installing Keyv and its Dependencies
To begin, install Keyv and a storage adapter of your choice. In this example, we'll use SQLite:
$ npm install cacheable @keyv/redis --save
3. Integrating Keyv with NestJS
Create a new module named 'CacheModule' to manage the Keyv integration:
$ nest generate module cache
Then, update the cache.module.ts file to import and configure Keyv:
import { Module } from '@nestjs/common';
import { Cacheable } from 'cacheable';
import KeyvRedis from '@keyv/redis';
@Module({
providers: [
{
provide: 'CACHE_INSTANCE',
useFactory: () => {
const secondary = new KeyvRedis('redis://user:pass@localhost:6379');
return new Cacheable({ secondary, ttl: '4h' });
},
},
],
exports: ['CACHE_INSTANCE'],
})
export class CacheModule {}
Don't forget to import the CacheModule in app.module.ts:
import { Module } from '@nestjs/common';
import { CacheModule } from './cache/cache.module';
@Module({
imports: [CacheModule],
})
export class AppModule {}
4. Creating a Caching Service with Keyv
Now, create a service to manage caching using Keyv:
$ nest generate service cache
Update the cache.service.ts file with caching methods:
import { Inject, Injectable } from '@nestjs/common';
@Injectable()
export class CacheService {
constructor(@Inject('CACHE_INSTANCE') private readonly cache: Cacheable) {}
async get(key: string): Promise {
return await this.cache.get(key);
}
async set(key: string, value: T, ttl?: number | string): Promise<void> {
await this.cache.set(key, value, ttl);
}
async delete(key: string): Promise<void> {
await this.cache.delete(key);
}
}
5. Implementing Caching in a Sample Controller
Create a sample controller to demonstrate caching usage:
$ nest generate controller sample
Update the sample.controller.ts file to use the caching service:
import { Controller, Get } from '@nestjs/common';
import { CacheService } from '../cache/cache.service';
@Controller('sample')
export class SampleController {
constructor(private readonly cacheService: CacheService) {}
@Get()
async getData() {
const cacheKey = 'sample-data';
let data = await this.cacheService.get(cacheKey);
if (!data) {
// Simulate fetching data from an external API
data = 'Sample data from external API';
await this.cacheService.set(cacheKey, data, '1m'); // Cache for 1 minute
}
return {
data,
source: data === 'Sample data from external API' ? 'API' : 'Cache',
};
}
}
This SampleController demonstrates how to use the CacheService to cache and retrieve data. When a request is made to the /sample endpoint, the getData() method first checks if the data is available in the cache. If the data is not cached, it simulates fetching data from an external API, caches the data for 1 minute, and then returns the data along with its source (either "API" or "Cache").