Skip to content

Nr 07 Caching Strategies

DodaTech 5 min read

title: "Next.js vs Remix — Caching Strategies Compared" description: "Compare caching approaches in Next.js and Remix: Next.js Data Cache, Full Route Cache, ISR vs Remix CDN caching, and HTTP cache headers." weight: 17 date: 2026-06-28 lastmod: 2026-06-28 tags: [frameworks, react]

Caching strategies differ fundamentally between Next.js and Remix. Next.js provides multiple built-in caching layers. Remix relies on HTTP caching and CDN configuration.

What You'll Learn

You will understand the caching mechanisms in each framework, how to configure cache behavior, and strategies for balancing freshness and performance.

Why It Matters

Proper caching reduces server load, improves response times, and lowers hosting costs. Each framework requires a different caching mindset.

Real-World Use

DodaTech's Next.js marketing site uses ISR for blog posts with hourly revalidation. The Remix admin dashboard uses CDN caching with short TTLs for API responses.

flowchart LR
    subgraph Next[Next.js Caching]
        A1[Data Cache] --> B1[fetch results]
        A2[Full Route Cache] --> B2[Rendered HTML]
        A3[Router Cache] --> B3[Client-side]
        A4[ISR] --> B4[Time-based revalidation]
    end
    subgraph Remix[Remix Caching]
        C1[HTTP Headers] --> D1[Cache-Control]
        C2[CDN Layer] --> D2[Edge caching]
        C3[Browser Cache] --> D3[Standard HTTP]
    end
    style Next fill:#121212,color:#fff
    style Remix fill:#1a1a2e,color:#fff

Next.js Caching Layers

Next.js provides three built-in caching layers plus ISR.

// Data Cache — caches fetch results
async function PostsPage() {
  const posts = await fetch('https://api.example.com/posts', {
    cache: 'force-cache'  // Cache indefinitely
  });
  return <PostList posts={await posts.json()} />;
}

// Time-based revalidation
async function SemiDynamicPage() {
  const data = await fetch('https://api.example.com/data', {
    next: { revalidate: 300 }  // 5 minutes
  });
  return <Page data={await data.json()} />;
}

// On-demand revalidation via tag
async function updatePost(formData) {
  'use server';
  await db.posts.update(formData);
  revalidateTag('posts');  // Invalidate all 'posts' tagged data
  return { success: true };
}

Expected output: The Data Cache stores fetch results. force-cache serves cached data indefinitely. revalidate: 300 refreshes every 5 minutes. revalidateTag invalidates specific cache entries.

Next.js Incremental Static Regeneration (ISR)

ISR combines static generation with on-demand revalidation.

export default async function BlogPost({ params }) {
  const post = await fetch(`https://api.example.com/posts/${params.id}`, {
    next: { revalidate: 3600 }  // Revalidate every hour
  });
  return <Article post={await post.json()} />;
}

// Or use generateStaticParams for static paths
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json());
  return posts.map(post => ({ id: post.id.toString() }));
}

Expected output: Pages are pre-rendered at build time. On request, the cached HTML is served. After 3600 seconds, the page revalidates and updates in the background.

Remix Caching Approach

Remix does not have built-in caching layers. It relies on standard HTTP caching.

// Remix route with cache headers
export async function loader({ request }) {
  const posts = await db.posts.findAll();

  // Set cache headers on the response
  const data = { posts };
  const headers = new Headers();
  headers.set('Cache-Control', 'public, s-maxage=60, stale-while-revalidate=300');

  return new Response(JSON.stringify(data), { headers });
}

// Or use the headers export
export function headers() {
  return {
    'Cache-Control': 'public, max-age=0, s-maxage=60, stale-while-revalidate=300',
  };
}

Expected output: The CDN caches the response for 60 seconds. After 60 seconds, the CDN serves stale content while revalidating in the background (stale-while-revalidate).

Cache Invalidation

Next.js invalidates cache through revalidatePath, revalidateTag, or time-based revalidation.

Remix invalidates cache through CDN configuration, webhook-triggered purges, or short TTLs.

When to Use Each Approach

Next.js caching is ideal for content sites, blogs, documentation, and marketing pages where content changes infrequently.

Remix caching is ideal for data-driven applications, dashboards, and APIs where data freshness is important and CDN caching at the HTTP level is sufficient.

Common Mistakes

  1. Over-caching dynamic data in Next.js: Using force-cache for user-specific data serves stale data. Use no-store or revalidate for dynamic content.

  2. Not setting Cache-Control headers in Remix: Without cache headers, Remix responses are not cached at the CDN level, increasing server load.

  3. Forgetting to revalidate after mutations in Next.js: Without revalidatePath or revalidateTag, the page shows stale data after updates.

  4. Using ISR for user-specific pages: ISR is for shared, public content. User dashboards should use server rendering or client-side data fetching.

  5. Not understanding stale-while-revalidate: This pattern serves stale content while re-fetching in the background. It improves perceived performance but requires careful TTL configuration.

Practice Questions

  1. What caching layers does Next.js provide?

Data Cache (fetch results), Full Route Cache (rendered HTML), and Router Cache (client-side navigation cache).

  1. How does Remix handle caching?

Through standard HTTP Cache-Control headers and CDN configuration. There is no built-in framework caching layer.

  1. What is stale-while-revalidate?

A caching strategy that serves stale content while re-fetching updated content in the background. Defined via Cache-Control header.

  1. When would you use Next.js ISR vs Remix server rendering?

ISR for content that changes hourly/daily but does not need real-time freshness. Remix server rendering for data that must be fresh on every request.

  1. How do you invalidate Next.js cache programmatically?

Using revalidatePath (page-level) or revalidateTag (data-level) from Server Actions or route handlers.

Challenge

Set up caching for a blog with three tiers: static pages (archive, about), semi-dynamic (recent posts, revalidate 60s), and dynamic (post details, revalidate on tag when post is updated).

Frequently Asked Questions

Can I use ISR with Remix?

No. Remix does not support ISR. Use CDN caching with Cache-Control headers as an alternative.

Does Next.js cache database queries?

Database queries are not cached by default. Use memoization within a request or implement a cache layer around your database calls.

How long does the Next.js Full Route Cache persist?

Static pages persist until the next build. Dynamic pages with revalidate persist until the revalidation period expires.

Can I set cache headers in Next.js Server Components?

Not directly. Use Route Handlers or middleware to set cache headers. Server Components use the Data Cache internally.

What is the CDN caching strategy for Remix?

Set long Cache-Control on static assets and short s-maxage on dynamic pages. Use stale-while-revalidate for content that can tolerate slightly stale data.

Mini Project

Build a product catalog where the product list uses ISR with hourly revalidation in Next.js, and the same catalog uses CDN caching with 5-minute TTL in Remix. Compare the load behavior.

What's Next

Continue to Error Handling in both frameworks for building resilient applications.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro