It started with a support ticket: “Users are seeing old prices.” We had implemented SSR caching. The cache was working. But something was wrong. Let me tell you what happened.
The Setup
We used Next.js with Sircloa (or in production, the typical approach looks like this):
export async function getServerSideProps({ res }) {
res.setHeader('Cache-Control', 'public, max-age=3600');
const data = await fetchProduct();
return { props: { data } };
}
The Bug
After 10 minutes, users started seeing wrong prices. Here’s what went wrong:
1. User A visits at 10:00 - cache miss, fetches fresh data
2. Admin updates price at 10:05
3. User B visits at 10:06 - still gets cached data (10:00)
4. User B sees old price. Support tickets incoming.
The Fix
We needed cache invalidation. There are two approaches:
1. Time-Based (Simpler)
export async function getServerSideProps({ res, req }) {
// Shorter cache for frequently changing data
res.setHeader('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');
}
2. On-Demand Invalidation (Better)
Use a tag-based system with on-demand revalidation:
// Fetch with tags
await fetch('/api/products/1', { next: { tags: ['product-1'] } });
// Revalidate when data changes
await fetch('/api/revalidate?tag=product-1');
What I Learned
Cache invalidation is harder than caching itself. If your data changes frequently, don’t cache user-specific or time-sensitive data. It’s not worth the complexity.