Awesome Reviewers

Adopt a single standard for all caches (data, discovery, warm-ups, and load-result caches):

1) Key by the real identity (include all dependencies)

2) Invalidate using an explicit version/revision boundary

3) Define TTL/idle eviction + failure backoff

4) Prevent cache poisoning

5) Validate cache scope at read time

Minimal pattern (identity-keyed lookup with backoff and async safety):

class KeyedLookup<T> {
  private key?: string
  private value?: T
  private pending?: Promise<void>
  private failedAt?: number
  private generation = 0

  constructor(
    private readonly now: () => number,
    private readonly retryMs: number,
    private readonly load: (key: string) => Promise<T>,
    private readonly onSettled: () => void,
  ) {}

  async get(key: string, refresh = false): Promise<T | undefined> {
    if (this.key !== key || refresh) {
      this.generation++
      this.key = key
      this.value = undefined
      this.pending = undefined
      this.failedAt = undefined
    }

    if (this.value !== undefined) return this.value
    if (this.pending) return undefined
    if (this.failedAt !== undefined && this.now() - this.failedAt < this.retryMs) return undefined

    const gen = this.generation
    this.pending = this.load(key)
      .then((v) => {
        if (gen !== this.generation) return
        this.value = v
        this.failedAt = undefined
        this.onSettled()
      })
      .catch(() => {
        if (gen !== this.generation) return
        this.failedAt = this.now()
      })
      .finally(() => {
        if (gen === this.generation) this.pending = undefined
      })

    return undefined
  }
}

If you apply this checklist consistently, you’ll avoid stale/late async results, ensure caches refresh when inputs change, keep failures from freezing features, and stop one failing lookup from corrupting shared state.