KB-007: Vercel ISR — Incremental Static Regeneration Explained
| Field | Detail |
|---|---|
| Document ID | KB-007 |
| Version | 1.0 |
| Date | March 2026 |
| Author | Gemi (Gemini — Atlantis AI) |
| Reviewed By | Shane Hardin |
| Applies To | Atlantis Next.js projects — IceBreakrz, Lexicon, future SaaS pages |
| Difficulty | Intermediate |
| Est. Time | 10 minutes |
| Related Docs | KB-005 — Environment Variables, KB-006 — Edge vs Serverless |
1. Overview
Incremental Static Regeneration (ISR) is a Vercel and Next.js feature that gives you the best of both worlds: the blazing speed of a static site combined with the ability to update content dynamically — without triggering a full rebuild or redeployment.
For Atlantis, ISR is most relevant for: - IceBreakrz — content cards (jokes, riddles, quotes) that update periodically but don't need real-time refresh - Lexicon — Word of the Day content from MongoDB Atlas - Future SaaS marketing pages — pricing, feature lists, contractor testimonials that change occasionally
2. The Problem ISR Solves
Vercel supports three rendering strategies, each with tradeoffs:
| Strategy | Speed | Fresh Data | Rebuild Required |
|---|---|---|---|
| Static Site Generation (SSG) | ⚡ Fastest | ❌ Stale until rebuild | ✅ Yes — on every content change |
| Server-Side Rendering (SSR) | ⚠️ Slower | ✅ Always fresh | ❌ No — fetches on every request |
| ISR | ⚡ Fast (serves cached) | ✅ Refreshes in background | ❌ No — auto-regenerates |
Without ISR, if you update a price or fix a typo on a static page, you have to manually trigger a full Vercel rebuild and redeploy. ISR eliminates this entirely.
3. How ISR Works — The Stale-While-Revalidate Pattern
ISR uses a caching strategy called stale-while-revalidate:
Step 1 — First User Request:
User visits atlantisits.co/pricing
↓
Vercel builds and caches the page (static HTML)
↓
User gets the page instantly ⚡
Step 2 — Subsequent Requests (within revalidation window):
Next user visits the same page
↓
Vercel serves the CACHED version instantly ⚡ (stale but fast)
↓
In the BACKGROUND, Vercel checks for new data and rebuilds just that page
Step 3 — After Revalidation Completes:
The NEXT user after that gets the fresh rebuilt version ⚡
↓
Old cache is replaced — no downtime, no full rebuild
💡 TIP: The key insight is that ISR never makes a user wait for a rebuild. The page is always served from cache. The rebuild happens silently in the background and the next visitor gets the fresh version.
4. Implementation
ISR is configured with a single revalidate option in your Next.js page:
Next.js App Router (modern — recommended)
// app/pricing/page.js
export const revalidate = 3600; // Revalidate every 1 hour (in seconds)
export default async function PricingPage() {
// This fetch is cached and revalidated per the revalidate value above
const pricing = await fetch('https://api.atlantisits.co/pricing', {
next: { revalidate: 3600 }
}).then(res => res.json());
return (
<main>
<h1>Atlantis ITS Pricing</h1>
{pricing.map(tier => <PricingCard key={tier.id} {...tier} />)}
</main>
);
}
Next.js Pages Router (legacy pattern — IceBreakrz)
// pages/content.js
export async function getStaticProps() {
const content = await fetch('https://api.atlantisits.co/content').then(r => r.json());
return {
props: { content },
revalidate: 1800, // Rebuild this page every 30 minutes if requested
};
}
5. Choosing a Revalidation Interval
| Content Type | Recommended Interval | Atlantis Example |
|---|---|---|
| Real-time data (live scores, stock prices) | Don't use ISR — use SSR | n/a |
| Frequently updated content | 60–300 seconds (1–5 min) | Lead count dashboard widgets |
| Periodically updated content | 1800–3600 seconds (30–60 min) | IceBreakrz content cards, Lexicon Word of the Day |
| Rarely changed content | 86400 seconds (24 hours) | Pricing pages, feature lists |
| Near-static content | 604800 seconds (1 week) | Team pages, legal docs |
⚠️ NOTE: Setting
revalidate: 0disables caching entirely and makes the page behave like SSR (fetches fresh on every request). This defeats the purpose of ISR and should be avoided unless real-time data is genuinely required.
6. On-Demand Revalidation (Manual Trigger)
For cases where you need to update a page immediately — like when a contractor updates their profile or a new Word of the Day is added — Next.js supports on-demand revalidation via an API route:
// pages/api/revalidate.js
export default async function handler(req, res) {
// Protect the endpoint with a secret
if (req.query.secret !== process.env.REVALIDATION_SECRET) {
return res.status(401).json({ message: 'Invalid token' });
}
try {
// Revalidate a specific page path
await res.revalidate('/word-of-the-day');
return res.json({ revalidated: true });
} catch (err) {
return res.status(500).send('Error revalidating');
}
}
Then trigger it from n8n or any webhook:
GET https://lexicon.atlantisits.co/api/revalidate?secret=YOUR_SECRET&path=/word-of-the-day
💡 TIP: This is a powerful pattern for Atlantis — when Shane adds a new Word of the Day to MongoDB Atlas, an n8n workflow can automatically call the revalidation endpoint and push the fresh content live in seconds, with no manual deploy needed.
7. ISR vs. The Alternatives — Decision Guide
Is your data real-time (live prices, scores, status)?
→ YES: Use SSR (Server-Side Rendering) or Edge Functions with streaming
→ NO: Continue ↓
Does the page need to show the absolute latest data on EVERY request?
→ YES: Use SSR
→ NO: Continue ↓
Does the content change on a predictable schedule (hourly, daily)?
→ YES: Use ISR with an appropriate revalidate interval
→ NO: Continue ↓
Does the content almost never change?
→ YES: Use pure SSG (Static Site Generation) — no revalidate needed
8. Troubleshooting
| Error / Symptom | Cause | Fix |
|---|---|---|
| Page not updating after content change | Revalidation interval hasn't elapsed | Wait for interval or use on-demand revalidation |
| ISR not triggering revalidation | No user request hit the page after the interval | ISR only revalidates when the page is requested — not on a timer |
revalidate ignored in development |
ISR is disabled in next dev — always fetches fresh |
Test ISR behavior in production or with next build && next start |
| On-demand revalidation returning 401 | Wrong or missing secret in query param | Confirm REVALIDATION_SECRET env var is set in Vercel |
| Page always shows stale data | revalidate value too high |
Reduce the interval for more frequent refreshes |
revalidate: 0 making site slow |
Treating ISR like SSR — fetches on every request | Remove revalidate: 0 and set an appropriate interval, or switch to SSR intentionally |
9. Quick Reference
| Item | Value |
|---|---|
| What ISR does | Serves cached static pages, rebuilds in background after interval |
| Key config option | revalidate: N (seconds) in getStaticProps or export const revalidate |
| Revalidate every 30 min | revalidate: 1800 |
| Revalidate every hour | revalidate: 3600 |
| Revalidate every day | revalidate: 86400 |
| Disable ISR (use SSR) | revalidate: 0 or remove option entirely with getServerSideProps |
| On-demand trigger | res.revalidate('/path') in an API route |
| n8n integration | Trigger revalidation via GET webhook from n8n workflow |
| Best for Atlantis | IceBreakrz content, Lexicon Word of the Day, SaaS pricing pages |
| Not suitable for | Live lead counts, real-time dashboards, AI streaming |
| Related doc | Edge vs Serverless → KB-006 |
Document prepared by Gemi (Gemini — Atlantis AI Automations)
atlantisits.info | KB-007 | v1.0 | March 2026