Skip to main content

Caching & Performance Optimization with Redis in NestJS

· 2 min read
JavaScript Dev

Overview​

When building a platform that relies on statistical analysis and deep comparisons, response time can quickly become a bottleneck. In this article, I’ll walk through how I integrated Redis with NestJS to reduce computation time and database load on performance-heavy endpoints.

I implemented caching on frequently accessed data like:

  • Party trends across elections
  • Leader performance history
  • Poll summaries
  • Government composition data

Why Redis?​

Redis was a natural fit for this use case because:

  • It’s fast (in-memory)
  • Supports key-based access
  • Handles TTL (time-to-live) logic elegantly
  • Integrates easily with Node.js

I use it both for static data (cached responses) and temporary session data (vote hashes, poll locks).


Integration with NestJS​

NestJS doesn’t come with Redis out of the box, but integrating it is straightforward:

@Module({
imports: [
CacheModule.registerAsync({
useFactory: async () => ({
store: redisStore,
host: 'localhost',
port: 6379,
}),
}),
],
})
export class AppModule {}

Use @CacheInterceptor or cacheManager manually in services:

@Injectable()
export class PartyService {
constructor(@Inject(CACHE_MANAGER) private cacheManager: Cache) {}

async getPartyTrends(id: number) {
const key = `party_trends_${id}`;
const cached = await this.cacheManager.get(key);
if (cached) return cached;

const trends = await this.queryTrends(id);
await this.cacheManager.set(key, trends, { ttl: 300 });
return trends;
}
}

When to Cache​

I typically cache data that meets at least one of the following:

  • Expensive to compute or join (multi-election trend analysis)
  • Stable for a given timeframe (e.g. 5 minutes to 1 hour)
  • Frequently requested (e.g. homepage charts, top leaders)

TTL and Invalidation Strategy​

  • Each cached object gets a TTL depending on volatility:

    • Poll results: 30 seconds
    • Leader summaries: 5 minutes
    • Election trend comparisons: 1 hour
  • For admin-triggered updates, I add manual cache busting logic:

await this.cacheManager.del(`party_trends_${partyId}`);

Metrics Before & After​

  • Party trend endpoint: from 1.2s → 90ms
  • Top winners summary: 800ms → 70ms
  • Poll result rendering: 300ms → 50ms

Redis made the site feel instantly more responsive and scalable.


Takeaways​

  • Don’t over-cache everything—start with high-impact queries
  • TTLs should reflect content volatility and UX needs
  • Redis + NestJS works cleanly and gives you full control

Next up, I’ll dive into multilingual integration and how I ensured the entire system—from schema to tooltips—could work in English and Nepali interchangeably.