I used to think caching was a pretty simple performance trick: store something closer to the user, serve it faster, reduce the load on the backend, and everyone wins. Then I started digging into CloudFront cache keys and realized caching can become a data-isolation problem if one small decision is wrong. Imagine an application with a GET /profile endpoint where User A sends Cookie: session=userA and gets a response like “Hello Alice, your orders: 12, your balance: ₹42,000.” CloudFront can cache that response so future requests don't always have to reach the origin. Sounds great, right? Until another user requests the same URL and the cache doesn't distinguish the thing that actually makes the response personal.
Now User B sends GET /profile with Cookie: session=userB, and the origin would normally return completely different information such as “Hello Bob, your orders: 4, your balance: ₹8,000.” But if the cache key only considers /profile and ignores the user-specific part of the request, CloudFront can see the request as equivalent to the object it already has. In that situation, User B could receive the response cached for User A. Nothing has crashed, the EC2 instance can be healthy, the database can be healthy, and CloudFront can even be behaving exactly according to its configuration. The actual problem is the caching strategy. That's when caching stops being only a performance optimization and becomes a correctness and security concern.
Now compare that with a public product catalogue. A request like GET /products?id=101 might return the same product information for every user: iPhone 17, ₹79,999, In Stock. That's a fantastic candidate for caching because thousands of users can safely reuse the same response. We want something like one cache object serving many requests, not a separate cache entry for every visitor. But this is where another subtle problem appears: if every request contains an analytics cookie such as analytics_id=83A91, analytics_id=72B42, or analytics_id=91K17, and those values don't change the product response, putting them into the cache key can create thousands or even millions of unnecessary cache variants. The application may still be correct, but cache reuse gets worse, cache efficiency drops, and more requests may end up going back to the origin.
That leads to one of the most useful CloudFront distinctions I've learned: Cache Policy and Origin Request Policy are not answering the same question. Cache Policy is essentially asking, “What makes this request a different cached object?” while Origin Request Policy is asking, “What information does the origin need to receive?” For example, an analytics cookie might need to reach the origin for logging or processing, while still not needing to create a unique cache entry for every user. The important part is to understand which request values actually change the response and which ones are simply metadata. A good cache design therefore doesn't blindly include every cookie, header, or query string just because it is available; it deliberately chooses only the dimensions that matter.
The production lesson for me is that a high cache-hit ratio is not automatically a good outcome. A cache that is extremely fast but returns the wrong user's data is a disaster, not an optimization. The real question isn't “How much can I cache?” but “What can I safely reuse, what makes the response different, and how do I make CloudFront understand that difference?” This also changes how I think about CDN architecture: cache design affects performance, origin load, freshness, correctness, and potentially security at the same time. Static assets such as versioned JavaScript, CSS, images, and public product data are usually much easier to cache aggressively, while personalized responses need a much more careful strategy. Caching is not just about speed — it's about knowing exactly when two requests are allowed to share the same answer.
Top comments (0)