How to Speed Up Your Next js App with Caching
Source: Dev.to
What is Caching?
Caching basically means remembering data that you already fetched or calculated, so you don’t have to do the same thing again.
- Instead of calling an API or hitting a database every time a user visits your page, your app can store that data temporarily and reuse it until it needs to be updated.
- Think of it like your brain remembering your home address. You don’t have to look it up every time you fill out a form. The same concept applies to your app.
Where Can Caching Happen?
In React and Next.js, caching can happen at different levels:
| Layer | What you can cache |
|---|---|
| Client side | API responses, computed values, component output |
| Server side | Data fetched during SSR/SSG, route‑level data |
| Network / CDN | Whole pages, static assets, edge‑cached API routes |
Each layer gives you an opportunity to make your app faster if you use it wisely.
Why Cache?
- Makes pages load faster for users.
- Reduces server costs and API usage.
- Makes your app feel smoother and more responsive.
- Improves SEO and Core Web Vitals by cutting down page‑load time.
Next.js Caching Features
1. fetch() with Built‑in Caching Controls
// Example: cache for 1 hour
const data = await fetch('https://api.example.com/posts', {
next: { revalidate: 3600 } // seconds
});
revalidatetells Next.js to re‑fetch the data after the given number of seconds.- Perfect for data that doesn’t change frequently (blog posts, product lists, static content).
If you always need fresh data:
const data = await fetch('/api/always-fresh', {
cache: 'no-store' // never cache
});
2. Cache Components ('use cache' Directive)
// Sidebar component – cached
async function Sidebar() {
'use cache';
const categories = await fetch('/api/categories');
return (
<>
{/* Sidebar content here */}
</>
);
}
- Use
'use cache'inside a server component to cache only that part of the UI. - Great for sidebars, navigation, or any UI that rarely changes.
3. Route / Page Segment Caching (SSG & ISR)
// pages/blog/[slug].tsx
export const revalidate = 3600; // 1 hour
- Next.js will pre‑render the page at build time and re‑validate it in the background after the specified interval.
- Ideal for blog articles, product pages, etc.—you get static speed with dynamic freshness.
React‑Side Caching Techniques
1. Memoization (useMemo & useCallback)
import { useMemo } from 'react';
const sortedList = useMemo(() => {
return data.sort((a, b) => a.name.localeCompare(b.name));
}, [data]); // recompute only when `data` changes
- Prevents expensive calculations (like sorting) from running on every render.
2. Data‑Fetching Libraries with Built‑in Caching
SWR Example
import useSWR from 'swr';
const fetcher = (url: string) => fetch(url).then(res => res.json());
export default function Profile() {
const { data, error } = useSWR('/api/user', fetcher, {
refreshInterval: 60000 // revalidate every minute
});
if (error) return <div>Error loading</div>;
if (!data) return <div>Loading...</div>;
return <div>Hello {data.name}</div>;
}
- SWR caches the response, returns it instantly on subsequent renders, and revalidates in the background.
- React Query works the same way—pick whichever fits your style.
My Simple Caching Checklist
- Identify data that doesn’t change often.
- Keep user‑specific or time‑sensitive data dynamic.
- Cache only where it improves performance.
- Set a revalidation time or expiry for every cached entry.
- Test & monitor the results (e.g., Lighthouse, server logs).
Caching is not about caching everything. It’s about caching the right things.
Common Caching Mistakes
| Mistake | Why it hurts |
|---|---|
| Over‑caching – never setting expiry | Serves stale data |
| Caching user data globally | Mixes up sessions, leaks private info |
| Forgetting invalidation | Updates never appear |
| Debugging confusion – assuming data is fresh when it’s cached | Wastes time tracking down “missing” updates |
The golden rule: balance speed and freshness.
A Real‑World Balance (My Example)
- Sidebar categories & featured posts – cached with
'use cache'. - Post list – fetched with
fetch(..., { next: { revalidate: 600 } })(re‑validate every 10 minutes). - User‑specific sections (comments, notifications) – always dynamic (no caching).
This gives a fast site without compromising accuracy.
TL;DR
- Caching = remembering data so you don’t redo work.
- Use Next.js’s
fetchoptions, Cache Components, and ISR for server‑side caching. - Use React’s
useMemo,useCallback, and libraries like SWR or React Query for client‑side caching. - Cache what’s static, keep what’s dynamic fresh, and always set a revalidation strategy.
Caching is one of the easiest ways to make your app feel instant.
Happy coding! 🚀
Make Your React or Next.js App Feel Lightning Fast
You don’t have to rebuild your whole system to see the impact — just start small. Cache the parts that don’t change often, test, and then expand from there.
With Next.js evolving rapidly, features like route caching, fetch‑level caching, and cache components make performance optimization much simpler than before.
If you use caching smartly, your app will not only load faster but also handle more users with less effort.
Thanks for reading. If you want to see more content like this, check out my other blogs where I share practical insights on React, Next.js, and web performance.