Skip to main content

Cache Invalidation — One of the Two Hard Problems

Keeping cache in sync with source of truth — choose your strategy based on how stale data harms you.

When to use

  • TTL: staleness acceptable (product catalog, configs)
  • Event-driven: near-real-time required (inventory counts, pricing)
  • Versioned keys: static assets, CDN-cached content

Tradeoffs

  • TTL = stale window risk; event-driven = coupling to write path; versioned keys = storage growth
  • All strategies have failure modes — none is universally safe
// TTL: expire after fixed duration on write
redis.Set(ctx, "product:123", data, 60*time.Second)

// Event-driven: invalidate on write event
func OnProductUpdated(id string) {
redis.Del(ctx, "product:"+id)
}

// Versioned key: embed version, no invalidation needed
func VersionedKey(id, version string) string {
return fmt.Sprintf("product:%s:v%s", id, version)
}

Gotcha: Versioned keys are the most robust — never overwrite, never invalidate. Old versions are just ignored. Best for assets, configs, feature flags.