Bird
Raised Fist0
NestJSframework~15 mins

Custom cache keys in NestJS - Deep Dive

Choose your learning style10 modes available
Overview - Custom cache keys
What is it?
Custom cache keys in NestJS let you control how cached data is identified and stored. Instead of using default keys, you create your own unique keys to save and retrieve cached results. This helps make caching smarter and more precise for your app's needs. It is especially useful when you want to cache complex or dynamic data.
Why it matters
Without custom cache keys, caching might store data under generic or unpredictable keys, causing wrong data to be served or cache misses. This can slow down your app or cause bugs. Custom keys ensure the cache stores exactly what you want and retrieves it correctly, improving performance and reliability. It makes your app feel faster and more responsive to users.
Where it fits
Before learning custom cache keys, you should understand basic caching concepts and how NestJS caching works with default keys. After mastering custom keys, you can explore advanced caching strategies like cache invalidation, distributed caching, and integrating with external cache stores like Redis.
Mental Model
Core Idea
Custom cache keys are unique labels you create to store and find cached data exactly where you want it.
Think of it like...
Imagine a library where books are stored by default only by title, but you want to find books by author and year too. Custom cache keys are like adding special labels on books so you can find them faster and more accurately.
┌───────────────┐
│ Request Data  │
└──────┬────────┘
       │
       ▼
┌─────────────────────┐
│ Custom Cache Key     │
│ (unique identifier)  │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ Cache Store         │
│ (stores data by key)│
└─────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding Basic Caching
🤔
Concept: Learn what caching is and how it speeds up apps by storing data temporarily.
Caching saves results of expensive operations so next time the app can reuse them instead of recalculating. NestJS provides a CacheModule that stores data with default keys based on method names and arguments.
Result
You see faster responses because repeated requests use cached data instead of running full logic again.
Understanding caching basics is essential before customizing keys, as it shows why and when caching helps.
2
FoundationDefault Cache Keys in NestJS
🤔
Concept: Discover how NestJS creates default keys for cached data automatically.
By default, NestJS uses a combination of the method name and serialized arguments as the cache key. This works well for simple cases but can be limiting if you want more control.
Result
Cached data is stored and retrieved using these default keys without extra setup.
Knowing default behavior helps you see why custom keys are needed when defaults don't fit your data shape.
3
IntermediateCreating Custom Cache Keys Manually
🤔Before reading on: do you think you can use any string as a cache key, or must it follow a strict format? Commit to your answer.
Concept: Learn how to write your own cache key strings to identify cached data precisely.
You can create a function that takes method arguments and returns a string key. For example, combining user ID and query parameters into one string ensures cache entries are unique per user and query.
Result
Cache stores data under your custom keys, allowing precise retrieval and avoiding collisions.
Understanding how to build keys from input data unlocks flexible caching tailored to your app's logic.
4
IntermediateUsing Cache Key Factories in NestJS
🤔Before reading on: do you think NestJS supports automatic custom key generation, or must you always write manual key strings? Commit to your answer.
Concept: NestJS allows defining cache key factories that generate keys automatically based on method inputs.
You can create a cache key factory function and pass it to caching decorators like @CacheKey or use interceptors that call your factory. This centralizes key logic and reduces errors.
Result
Your app automatically generates consistent custom keys without repeating code in every method.
Using factories improves maintainability and reduces bugs by standardizing cache key creation.
5
IntermediateHandling Complex Arguments in Keys
🤔Before reading on: do you think complex objects can be used directly as cache keys, or must they be converted? Commit to your answer.
Concept: Learn how to convert complex method arguments like objects or arrays into stable string keys.
Since cache keys must be strings, you serialize objects using JSON.stringify or custom serializers. You must ensure consistent property order to avoid different keys for the same data.
Result
Cache keys reliably represent complex inputs, preventing cache misses due to key mismatches.
Knowing how to serialize complex data prevents subtle bugs where cache keys differ unexpectedly.
6
AdvancedIntegrating Custom Keys with Cache Interceptors
🤔Before reading on: do you think cache interceptors can modify cache keys dynamically, or are keys fixed at decorator time? Commit to your answer.
Concept: You can customize cache keys dynamically inside interceptors to handle advanced scenarios like user context or request headers.
By extending or creating custom cache interceptors, you override the key generation method to include extra data like authentication tokens or locale, making caching context-aware.
Result
Your cache keys adapt to runtime data, improving cache hit rates and correctness in multi-user or multi-tenant apps.
Understanding interceptor customization unlocks powerful, context-sensitive caching strategies.
7
ExpertAvoiding Cache Key Collisions and Security Risks
🤔Before reading on: do you think cache keys can leak sensitive data if not designed carefully? Commit to your answer.
Concept: Learn the risks of poorly designed keys causing collisions or exposing private info, and how to prevent them.
If keys are too generic, different data may overwrite each other causing wrong cache hits. If keys include sensitive info like passwords, they risk exposure in logs or cache stores. Use hashing or encoding to protect keys and ensure uniqueness.
Result
Your caching is safe, reliable, and does not cause data leaks or incorrect data serving.
Knowing security and collision risks helps you design robust cache keys fit for production.
Under the Hood
NestJS caching works by intercepting method calls and checking if a cached value exists for a given key. If yes, it returns cached data; if no, it runs the method and stores the result under that key. Custom cache keys change how the key is generated from method inputs, affecting cache lookup and storage. Internally, keys are strings used by the cache store (memory, Redis, etc.) to index data.
Why designed this way?
Default keys are simple to implement and cover many cases, but apps often need more control for complex or multi-tenant data. Custom keys let developers tailor caching to their domain logic. This design balances ease of use with flexibility, allowing simple defaults and advanced customization without changing core caching behavior.
┌───────────────┐
│ Method Call   │
└──────┬────────┘
       │
       ▼
┌─────────────────────────────┐
│ Cache Key Generator         │
│ (default or custom function)│
└─────────────┬───────────────┘
              │
              ▼
┌─────────────────────────────┐
│ Cache Store Lookup          │
│ (memory, Redis, etc.)       │
└───────┬─────────────┬───────┘
        │             │
   Hit  │             │ Miss
        │             ▼
        │      ┌─────────────┐
        │      │ Execute     │
        │      │ Method      │
        │      └─────┬───────┘
        │            │
        │            ▼
        │      ┌─────────────┐
        │      │ Store Result│
        │      │ in Cache    │
        │      └─────────────┘
        ▼
┌───────────────┐
│ Return Result │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do you think default cache keys always prevent collisions? Commit yes or no.
Common Belief:Default cache keys in NestJS are always unique and safe for all use cases.
Tap to reveal reality
Reality:Default keys can collide if method arguments serialize to the same string or if methods have similar signatures, causing wrong cache hits.
Why it matters:Relying on defaults can cause your app to serve wrong cached data, leading to bugs and confusing behavior.
Quick: Can you use objects directly as cache keys without conversion? Commit yes or no.
Common Belief:You can use any data type, including objects, directly as cache keys.
Tap to reveal reality
Reality:Cache keys must be strings; objects must be serialized consistently to avoid cache misses.
Why it matters:Using objects without serialization causes cache misses and wasted computation.
Quick: Do you think including sensitive info in cache keys is safe? Commit yes or no.
Common Belief:Including user passwords or tokens in cache keys is fine because cache is internal.
Tap to reveal reality
Reality:Sensitive data in keys can leak through logs or cache inspection, risking security breaches.
Why it matters:Exposing secrets in keys can lead to data leaks and compromise user privacy.
Quick: Do you think custom cache keys always improve performance? Commit yes or no.
Common Belief:Custom cache keys always make caching faster and better.
Tap to reveal reality
Reality:Poorly designed keys can cause overhead, collisions, or cache misses, hurting performance.
Why it matters:Blindly using custom keys without design can degrade app speed and reliability.
Expert Zone
1
Custom cache keys should be stable and deterministic; even small changes in input must produce the same key format to avoid cache misses.
2
Hashing long or sensitive parts of keys balances uniqueness and security, preventing key length issues and data leaks.
3
Cache key design often requires coordination with cache invalidation strategies to ensure stale data is not served.
When NOT to use
Avoid custom cache keys when your caching needs are simple and default keys suffice, as extra complexity can introduce bugs. For distributed caches with complex data, consider using dedicated cache libraries or external tools like Redis with built-in key management.
Production Patterns
In production, teams often centralize cache key generation in utility functions or services to ensure consistency. They combine user context, request parameters, and versioning info in keys to handle multi-tenant apps and API changes. Custom interceptors are used to inject dynamic data like locale or auth tokens into keys.
Connections
Hash Functions
Custom cache keys often use hashing to create fixed-length, secure keys from variable input data.
Understanding hash functions helps you design cache keys that are unique, compact, and protect sensitive info.
Database Indexing
Cache keys act like database indexes, enabling fast lookup of stored data based on query parameters.
Knowing how indexes work in databases helps you appreciate the importance of well-designed cache keys for quick data retrieval.
Human Memory Techniques
Both cache keys and mnemonic devices rely on creating unique, memorable labels to quickly find information.
Recognizing this similarity shows how organizing data with meaningful keys improves recall and efficiency across fields.
Common Pitfalls
#1Using method arguments directly as cache keys without serialization.
Wrong approach:@Cacheable() async getData(params: object) { // cache key defaults to object reference }
Correct approach:@Cacheable({ key: (args) => JSON.stringify(args[0]) }) async getData(params: object) { // serialized key string }
Root cause:Cache keys must be strings; objects need serialization to create stable keys.
#2Including sensitive user data like passwords in cache keys.
Wrong approach:const key = `user-${user.password}-data`; cache.set(key, data);
Correct approach:const key = `user-${user.id}-data`; cache.set(key, data);
Root cause:Misunderstanding security risks of exposing sensitive info in cache keys.
#3Creating cache keys that change order of object properties causing cache misses.
Wrong approach:const key = JSON.stringify(params); // params properties unordered
Correct approach:const key = JSON.stringify(sortObjectKeys(params)); // stable property order
Root cause:JSON.stringify on unordered objects produces different strings for same data.
Key Takeaways
Custom cache keys let you control how cached data is stored and retrieved, improving app speed and correctness.
Cache keys must be strings and stable; complex inputs need consistent serialization or hashing.
Poorly designed keys can cause collisions, cache misses, or security leaks, so design carefully.
NestJS supports custom keys via manual strings, factories, and interceptors for flexible caching.
Understanding cache key design is essential for building reliable, secure, and efficient caching in real apps.

Practice

(1/5)
1. What is the main purpose of using @CacheKey() in a NestJS service?
easy
A. To set the time duration for cache expiration
B. To clear all cached data automatically
C. To define a custom name for the cached data key
D. To disable caching for a method

Solution

  1. Step 1: Understand the role of @CacheKey()

    This decorator is used to specify a custom key name for the cached data instead of using a default or generated key.
  2. Step 2: Differentiate from other cache decorators

    @CacheTTL() sets cache duration, clearing cache is manual or by other methods, and disabling cache is not done by @CacheKey().
  3. Final Answer:

    To define a custom name for the cached data key -> Option C
  4. Quick Check:

    Custom cache key = @CacheKey() [OK]
Hint: Remember: CacheKey sets the cache name, TTL sets time [OK]
Common Mistakes:
  • Confusing @CacheKey() with @CacheTTL()
  • Thinking @CacheKey() clears cache
  • Assuming @CacheKey() disables caching
2. Which of the following is the correct way to apply a custom cache key to a method in NestJS?
easy
A. @CacheKey = 'myKey'\nasync getData() { return data; }
B. @CacheTTL(300)\nasync getData() { return data; }
C. cacheKey('myKey')\nasync getData() { return data; }
D. @CacheKey('myKey')\nasync getData() { return data; }

Solution

  1. Step 1: Identify correct decorator syntax

    In NestJS, decorators are applied with @DecoratorName(parameters) syntax above the method.
  2. Step 2: Check each option

    @CacheKey('myKey')\nasync getData() { return data; } uses @CacheKey('myKey') correctly. @CacheTTL(300)\nasync getData() { return data; } uses @CacheTTL which sets time, not key. @CacheKey = 'myKey'\nasync getData() { return data; } uses invalid assignment syntax. cacheKey('myKey')\nasync getData() { return data; } uses a non-existent function.
  3. Final Answer:

    @CacheKey('myKey')\nasync getData() { return data; } -> Option D
  4. Quick Check:

    Decorator syntax = @CacheKey('key') [OK]
Hint: Decorators start with @ and parentheses for parameters [OK]
Common Mistakes:
  • Using assignment instead of decorator syntax
  • Mixing @CacheKey with @CacheTTL
  • Calling cacheKey as a function instead of decorator
3. Given this NestJS method with caching:
@CacheKey('userList')
@CacheTTL(60)
async getUsers() {
  return ['Alice', 'Bob'];
}

What will be the cache key and TTL for the cached data?
medium
A. Key: 'getUsers', TTL: default (no TTL set)
B. Key: 'userList', TTL: 60 seconds
C. Key: 'userList', TTL: default (no TTL set)
D. Key: 'getUsers', TTL: 60 seconds

Solution

  1. Step 1: Identify the cache key from @CacheKey()

    The decorator @CacheKey('userList') sets the cache key explicitly to 'userList'.
  2. Step 2: Identify the TTL from @CacheTTL()

    The decorator @CacheTTL(60) sets the cache time to 60 seconds.
  3. Final Answer:

    Key: 'userList', TTL: 60 seconds -> Option B
  4. Quick Check:

    Custom key + TTL = 'userList' & 60s [OK]
Hint: @CacheKey sets key, @CacheTTL sets time in seconds [OK]
Common Mistakes:
  • Assuming method name is cache key when @CacheKey is used
  • Ignoring @CacheTTL and thinking no TTL is set
  • Confusing TTL units (seconds vs milliseconds)
4. You wrote this code:
@CacheKey('dataKey')
@CacheTTL('300')
async fetchData() {
  return 'info';
}

Why does the cache TTL not work as expected?
medium
A. Because TTL value should be a number, not a string
B. Because @CacheKey must come after @CacheTTL
C. Because async methods cannot use caching decorators
D. Because the cache key 'dataKey' is invalid

Solution

  1. Step 1: Check the @CacheTTL parameter type

    The TTL decorator expects a number (seconds), but '300' is a string, which causes it to fail.
  2. Step 2: Verify other decorator rules

    Decorator order does not affect TTL, async methods support caching, and 'dataKey' is a valid string key.
  3. Final Answer:

    Because TTL value should be a number, not a string -> Option A
  4. Quick Check:

    TTL must be number, not string [OK]
Hint: TTL needs number type, not quoted string [OK]
Common Mistakes:
  • Passing TTL as string instead of number
  • Thinking decorator order matters here
  • Assuming async disables caching
5. You want to cache user data with a dynamic key based on user ID. Which approach correctly creates a custom cache key in NestJS for method getUserById(id: string)?
hard
A. Use @CacheKey(() => `user_${id}`) above the method
B. Manually generate the key inside the method and use @CacheKey() without parameters
C. Use @CacheKey('user_' + id) directly above the method
D. Use @CacheKey() and pass the key as a method argument

Solution

  1. Step 1: Understand dynamic cache keys in NestJS

    To create a dynamic cache key, you can pass a function to @CacheKey() that returns the key string using method parameters.
  2. Step 2: Evaluate each option

    Use @CacheKey(() => `user_${id}`) above the method correctly uses a function returning a template string with id. Manually generate the key inside the method and use @CacheKey() without parameters is invalid because @CacheKey() needs the key at decoration time. Use @CacheKey('user_' + id) directly above the method tries to concatenate directly but id is not available at decoration time. Use @CacheKey() and pass the key as a method argument is invalid as @CacheKey() does not accept method arguments.
  3. Final Answer:

    Use @CacheKey(() => `user_${id}`) above the method -> Option A
  4. Quick Check:

    Dynamic key = function in @CacheKey() [OK]
Hint: Use function in @CacheKey() for dynamic keys [OK]
Common Mistakes:
  • Trying to use method parameters directly in decorator string
  • Assuming @CacheKey() accepts method arguments
  • Generating key inside method but not linking to cache
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