The cache is empty. 30 goroutines call Remember for user:42 at the same moment, each with the same loader function.
130 callers ask for one key
2Every caller misses
3Only one runs the loader
4The value is stored
5All 30 share one result
6Later calls are cache hits
←→ step · space play
All steps as text
30 callers ask for one key. The cache is empty. 30 goroutines call Remember for user:42 at the same moment, each with the same loader function.
Every caller misses. Get finds nothing, so each caller sees a miss (ErrNotFound). Without protection, all 30 would now run the loader and hit the database.
Only one runs the loader. The miss goes into a single-flight loader. One goroutine runs your function; the other 29 block and wait for its answer.
The value is stored. The loader returns. Remember wraps the value in a small envelope and stores it with Set, using the hard TTL plus jitter.
All 30 share one result. The 29 waiting goroutines get the same value. The loader ran exactly once for 30 callers.
Later calls are cache hits. A caller that arrives while the entry is still fresh gets the cached value straight away. The loader is not called.
The README describes it in one line: 30 goroutines that all miss user:42 at once run the loader exactly once; the other 29 block and share the result.
Add WithJitter so a batch of keys written together do not all expire in the same instant, and WithRefreshAhead so a hot key is refreshed in the background before it expires. The freshness explainer shows those windows.