Consider GET /products/42 served through a shared cache. This path can lower database load and latency for repeat reads, but it introduces a second copy whose freshness must be managed.
1. Route the request
An edge or load balancer chooses a service instance. The request carries the product identifier and relevant authorization context. If responses differ by user or permission, the cache key and cache policy must prevent one caller from receiving another caller's data.
2. Check the cache
The service builds a key from the resource identity and checks the cache. A hit returns a stored value subject to its expiry and invalidation rules. A cache miss continues to the database. Concurrent misses can cause a thundering herd unless the system coalesces requests or limits duplicate work.
3. Read and populate
The service queries the authoritative store, maps the row into an API representation, and may write that value into the cache with a time-to-live. The cache write can fail independently; the service must decide whether the response still succeeds and how that failure is observed.
4. Return under a stated freshness contract
The response leaves the service. Updates may invalidate the key, overwrite it, or allow it to expire. Each policy has a window in which a caller can observe older data. Document that window and test the race between an update and a cache fill.
Caching is a consistency decision as well as a speed decision. Measure hit rate and stale-read impact before adding layers.