15 questions found
What is multi-tier caching (combining an in-memory L1 cache with a distributed L2 cache), and what problem does it solve?
Advanced
Multi-tier caching layers a fast, small in-memory (L1) cache on each application instance in front of a larger, shared distributed (L2) cache like Redis -- a read first checks L1 (fastest), falling back to L2 on a miss, and finally to the actual data source, giving both the raw speed of in-memory access for hot data and the consistency/capacity of a shared cache.
const l1Cache = new Map();
async function getData(key) {
if (l1Cache.has(key)) return l1Cache.get(key);
const l2Value = await redis.get(key);
if (l2Value) { l1Cache.set(key, JSON.parse(l2Value)); return JSON.parse(l2Value); }
const fresh = await db.fetch(key);
l1Cache.set(key, fresh);
await redis.set(key, JSON.stringify(fresh), { EX: 300 });
return fresh;
}
Real-world example
A high-traffic API serving the same handful of extremely popular product pages adds a small in-memory L1 cache in front of its existing Redis cache, cutting typical response latency further for those hot items.
Common follow-ups: How do you keep L1 caches on different instances from serving inconsistent stale data relative to each other after an invalidation?;What's an appropriate L1 cache size given it exists on every application instance?
Caching with Redis;Performance Optimization & Profiling
What is the risk of caching sensitive or user-specific data with a shared cache key, and how do you avoid it?
Intermediate
If a cache key doesn't incorporate the identity of the requesting user (or tenant, or permission context), one user's request could be served another user's cached, personalized data -- a serious privacy bug. The fix is ensuring cache keys always include every dimension the response varies by (user ID, locale, permission level), the same principle behind the HTTP 'Vary' header.
// Bug: cache key doesn't include the user
const cacheKey = 'dashboard-data';
// Fixed: cache key scoped to the specific user
const cacheKey = `dashboard-data:${userId}`;
Real-world example
A security audit discovers a dashboard-caching layer used a single shared cache key regardless of the logged-in user, meaning the first user to load the dashboard after expiration had their personalized data served to every subsequent user until the entry expired.
Common follow-ups: What other dimensions besides user ID commonly need to be included in a cache key (locale, currency, permission role)?;How does the HTTP 'Vary' header address this same class of problem for CDN and browser caching?
Security;HTTP & HTTPS Modules
How would you implement a write-behind (write-back) caching strategy, and what durability risk does it introduce?
Advanced
Write-behind caching writes changes to the cache immediately and defers the actual write to the durable database to a later batched operation, improving write throughput significantly, but introducing a durability risk: if the process crashes before the deferred write happens, that data is permanently lost, so this pattern is only appropriate when losing a small, recent window of writes is genuinely acceptable.
const writeBuffer = new Map();
function recordPageView(pageId) {
writeBuffer.set(pageId, (writeBuffer.get(pageId) || 0) + 1);
}
setInterval(async () => {
for (const [pageId, count] of writeBuffer) {
await db.pageViews.increment(pageId, count);
}
writeBuffer.clear();
}, 30000);
Real-world example
An analytics system tracking page-view counts buffers increments in memory and flushes them to the database every 30 seconds, accepting a small window of possible data loss on crash since exact real-time counts aren't business-critical.
Common follow-ups: What data would be completely inappropriate to cache using a write-behind strategy given this durability risk?;How would you reduce the durability risk without giving up the throughput benefit entirely, such as more frequent flushing?
Databases & ORMs (MongoDB/Mongoose
SQL/Sequelize);Performance Optimization & Profiling
What is negative caching, and why might you deliberately cache the fact that a lookup returned 'not found'?
Intermediate
Negative caching stores the result of a lookup that found nothing, preventing repeated identical lookups for something known not to exist from hitting the database every time -- without it, requests probing for non-existent resources could generate significant unnecessary load on the underlying data source.
async function getUser(id) {
const cached = await redis.get(`user:${id}`);
if (cached === 'NOT_FOUND') return null;
if (cached) return JSON.parse(cached);
const user = await db.users.findById(id);
if (!user) { await redis.set(`user:${id}`, 'NOT_FOUND', { EX: 60 }); return null; }
await redis.set(`user:${id}`, JSON.stringify(user), { EX: 3600 });
return user;
}
Real-world example
A public API repeatedly queried for invalid or deleted user IDs by a misconfigured integration adds negative caching with a short TTL, absorbing the repeated invalid lookups without hitting the database each time.
Common follow-ups: Why does a negative cache entry typically need a much shorter TTL than a positive cache entry?;Could negative caching be exploited or cause a functional bug if a resource is created shortly after being negatively cached?
Security;Databases & ORMs (MongoDB/Mongoose
SQL/Sequelize)
What is the difference between res.set('Cache-Control', 'no-cache') and 'no-store' in an Express response?
Beginner
'no-cache' allows a cache to store the response, but requires it to revalidate with the origin server before reusing the cached copy on every subsequent request. 'no-store' is much stricter: it forbids storing the response at all, anywhere, appropriate for genuinely sensitive responses that must never be cached in any form.
// Allows caching but forces revalidation every time
res.set('Cache-Control', 'no-cache');
// Forbids storing this response anywhere at all
res.set('Cache-Control', 'no-store');
Real-world example
A banking API sets Cache-Control: no-store on every endpoint returning account balance data, ensuring browsers, proxies, or any intermediate cache never retain a copy of that sensitive information.
Common follow-ups: How does a client know when a 'no-cache' response is safe to reuse versus needing to refetch it entirely?;Why would an application choose 'no-cache' over 'no-store' when it still wants some caching-related benefit?
Security;HTTP & HTTPS Modules