🍕 Data Fetching: Revalidation Strategies in Next.js
The Pizza Shop Story 🍕
Imagine you own a pizza shop with a menu board outside. The board shows today’s specials.
The problem? The menu gets stale. Yesterday’s special is still there!
Revalidation is like having a helper who updates your menu board at the right time. Fresh data for your customers!
🏠 What is Revalidation?
Think of your website like a refrigerator with food.
- Fresh food = Fresh data (just fetched)
- Stale food = Old data (needs refresh)
- Revalidation = Checking if food is still good, or getting new food
Next.js gives you 5 magic tools to keep your data fresh:
graph TD A["🍕 Revalidation Tools"] --> B["revalidatePath"] A --> C["revalidateTag"] A --> D["updateTag"] A --> E["refresh"] A --> F["Time-based"] B --> B1["Update one page"] C --> C1["Update by label"] D --> D1["Instant update"] E --> E1["Refresh current view"] F --> F1["Auto-update on timer"]
1️⃣ revalidatePath Function
The Story
You have a bakery. Someone buys the last chocolate cake.
The display case still shows “Chocolate Cake Available!” ❌
revalidatePath is like yelling to your helper: “Hey! Update the display for aisle 3!”
What It Does
Tells Next.js: “This specific page needs fresh data NOW!”
Simple Example
// Someone bought the last cake
// Update the cakes page!
import { revalidatePath } from 'next/cache';
async function buyCake() {
// Remove cake from database
await db.cakes.delete('chocolate');
// Tell Next.js: refresh /cakes page
revalidatePath('/cakes');
}
When to Use It
| Situation | Example |
|---|---|
| User adds something | New blog post → refresh /blog |
| User deletes something | Delete comment → refresh /posts/123 |
| User updates something | Edit profile → refresh /profile |
Pro Tip 💡
You can refresh a layout that affects many pages:
// This refreshes ALL pages under /shop
revalidatePath('/shop', 'layout');
2️⃣ revalidateTag Function
The Story
Your pizza shop has three menu boards:
- Outside board
- Counter board
- Drive-thru board
All show the same pizza prices. When prices change, you update ALL THREE.
Instead of running to each board, you put a sticker on all pizza prices: "pizza-prices"
Now you just say: “Update everything with the pizza-prices sticker!”
What It Does
Updates all data marked with a specific tag (label).
Simple Example
Step 1: Mark your data with a tag
// When fetching pizza data
const pizzas = await fetch(
'https://api.shop.com/pizzas',
{ next: { tags: ['pizza-prices'] } }
);
Step 2: Refresh all data with that tag
import { revalidateTag } from 'next/cache';
async function updatePrices() {
// Change prices in database
await db.pizzas.updatePrices(newPrices);
// Refresh ALL cached data tagged
// with 'pizza-prices'
revalidateTag('pizza-prices');
}
Real World Use
graph TD A["🏷️ Tag: user-posts"] --> B["Home Page"] A --> C["Profile Page"] A --> D["Dashboard"] E["User creates post"] --> F["revalidateTag"] F --> G["All 3 pages updated!"]
3️⃣ updateTag Function
The Story
Imagine a scoreboard at a basketball game.
The score changes. You don’t want to wait for it to update. You want it instant!
updateTag is like having a super-fast assistant who changes the score the moment it happens.
What It Does
Provides immediate cache updates without waiting.
Simple Example
import { unstable_update } from 'next/cache';
async function scorePoint(team) {
// Update score in database
const newScore = await db.score.add(team, 1);
// Instantly update cached score data
unstable_update(
['game-score'],
newScore
);
}
Key Difference from revalidateTag
| revalidateTag | updateTag |
|---|---|
| Marks as stale | Updates immediately |
| Next request gets fresh data | Current data is replaced |
| Like “refresh needed” | Like “here’s the new data” |
4️⃣ refresh Function (useRouter)
The Story
You’re looking at a photo album on your phone.
Your friend just uploaded new photos to the shared album.
You pull down to refresh and see the new photos!
refresh() is that pull-to-refresh for your Next.js page.
What It Does
Re-fetches data for the current page you’re looking at.
Simple Example
'use client';
import { useRouter } from 'next/navigation';
function PhotoGallery() {
const router = useRouter();
const handleRefresh = () => {
// Refresh this page's data
router.refresh();
};
return (
<button onClick={handleRefresh}>
🔄 Load New Photos
</button>
);
}
When to Use It
| ✅ Good For | ❌ Not For |
|---|---|
| User clicks “refresh” | Automatic updates |
| After user action | Background syncing |
| Showing latest data | Updating other pages |
5️⃣ Time-based Revalidation
The Story
Your weather app shows the temperature.
Weather changes slowly. Checking every second is wasteful.
So you set a rule: “Check for new weather every 60 seconds.”
This is time-based revalidation. Like a kitchen timer! ⏰
What It Does
Automatically refreshes cached data after a set time.
Simple Example
// Refresh weather data every 60 seconds
const weather = await fetch(
'https://api.weather.com/today',
{ next: { revalidate: 60 } }
);
Understanding the Timeline
graph LR A["First Request"] --> B["Cache Created"] B --> C["60 seconds pass"] C --> D["Next Request"] D --> E["Fresh Data Fetched"] E --> F["New Cache Created"]
Choosing the Right Time
| Data Type | Revalidate Time | Example |
|---|---|---|
| Stock prices | 10 seconds | revalidate: 10 |
| News headlines | 5 minutes | revalidate: 300 |
| Blog posts | 1 hour | revalidate: 3600 |
| About page | 1 day | revalidate: 86400 |
Pro Tips 💡
Setting revalidate: 0 means “always fetch fresh data”
// Never cache - always fresh
const data = await fetch(url, {
next: { revalidate: 0 }
});
🎯 Choosing the Right Strategy
Quick Decision Guide
graph TD A{When should data update?} --> B{After user action?} B -->|Yes| C{One page or many?} C -->|One page| D["revalidatePath"] C -->|Many pages| E["revalidateTag"] B -->|No| F{On a schedule?} F -->|Yes| G["Time-based"] F -->|No| H{User clicks refresh?} H -->|Yes| I["router.refresh"]
Summary Table
| Strategy | When to Use | Speed |
|---|---|---|
revalidatePath |
Update one page after action | Fast |
revalidateTag |
Update many pages at once | Fast |
updateTag |
Instant data replacement | Fastest |
refresh() |
User-triggered refresh | Fast |
| Time-based | Automatic periodic updates | Automatic |
🌟 Key Takeaways
- revalidatePath = “Update THIS page”
- revalidateTag = “Update ALL pages with this label”
- updateTag = “Replace cached data RIGHT NOW”
- refresh = “User clicks refresh button”
- Time-based = “Auto-update every X seconds”
Think of revalidation like keeping your room clean:
- Sometimes you clean one corner (revalidatePath)
- Sometimes you clean all toys at once (revalidateTag)
- Sometimes you set a weekly cleaning day (Time-based)
- Sometimes you refresh when guests arrive (refresh)
Keep your data fresh, and your users happy! 🎉
