Every cache freshness design answers one question: when does a cached entry stop being true? Push and pull answer it in opposite directions.
With pull-based TTLs, you store a value plus an expiry time and re-fetch when the entry ages out. Nothing in the pipeline needs to know your cache exists. The cost is that freshness is a function of the TTL alone: a record that changes ten times a minute under a five-minute TTL is wrong for most of its life.
With push invalidation, the source tells you when something changed. Either the producer sends an HTTP callback (a webhook), or you tap the database's own log (change data capture, CDC) and turn each row change into an event. Delivery lag, not the timer, becomes the freshness bound, and you can often measure it directly: event timestamp minus cache eviction timestamp.
The distinction matters because the failure modes are different. A TTL cache fails by being stale, quietly, for a known maximum duration. A push pipeline fails by missing an event, and then the entry is stale until something else evicts it, which may be never. Push needs a safety net; TTL needs a tuned number.
For prompt and response caches inside an LLM stack, the same split shows up: prefix caching on the provider side is exact-match and correctness-neutral, while a fuzzy semantic cache can hand you a wrong answer with a 200 status (KV vs Prefix vs Prompt vs Semantic Caching). Treat invalidation of business data with the same severity: fuzzy matching and stale data both fail silently.



