Skip to content

Cache Invalidation

The Problem

When source data changes (e.g., user updates their profile), the cache still holds the old data. Cache invalidation removes stale entries to keep cache consistent with the database.

"There are only two hard things in Computer Science: cache invalidation and naming things." — Phil Karlton

How It Works

1. Database changes → User updates profile
2. Application notifies cache → Invalidate "user:123"
3. Cache removes stale entry
4. Next read → Cache miss → Fetch from DB → Update cache

InvalidationManager

The InvalidationManager provides event-driven invalidation:

typescript
import { InvalidationManager } from "distributed-cache";

const invalidator = new InvalidationManager();

// Set TTL for a key (auto-expire after 60 seconds)
invalidator.setTTL("user:123", 60000);

// Check if key is still valid
const isValid = invalidator.checkTTL("user:123"); // true or false

// Manually invalidate a key
invalidator.invalidate("user:123");

Event-Driven Invalidation

Subscribe to invalidation events:

typescript
import { InvalidationManager } from "distributed-cache";

const invalidator = new InvalidationManager();

// Subscribe to events
invalidator.subscribe((event) => {
  console.log(`Cache invalidated: ${event.type} - ${event.key}`);
  // Types: KEY_UPDATED, KEY_DELETED, KEY_EXPIRED
});

// When database changes
invalidator.onDatabaseChange({
  type: "KEY_DELETED",
  key: "user:123",
  timestamp: Date.now(),
});

Wildcard Invalidation

Invalidate multiple keys at once:

typescript
// Invalidate all user sessions
node.delete("session:user:1001");
node.delete("session:user:1002");
node.delete("session:user:1003");

// Or use pattern matching
const keys = node.getKeys();
keys
  .filter((k) => k.startsWith("session:"))
  .forEach((k) => node.delete(k));

Integration with CacheNode

typescript
import { CacheNode } from "distributed-cache";

const node = new CacheNode("node-1", {
  maxSize: 10000,
  onEvicted: (key) => {
    // Called when entry is evicted (LRU/LFU/FIFO)
    console.log(`Entry evicted: ${key}`);
  },
});

// Store with TTL
node.set("user:123", userData, 60000); // expires in 60s

// Manual invalidation
node.delete("user:123");

// Clear all entries
node.clear();

Best Practices

PracticeWhy
Set TTL for all entriesPrevents stale data from lingering
Use event-driven invalidationReal-time consistency with database
Invalidate on write-throughUpdate cache when DB changes
Batch invalidationReduce network overhead
Monitor hit rateLow hit rate = too much invalidation

Released under the MIT License.