Web Applications

Reducing API Costs in Next.js Applications

A Next.js app grows, traffic climbs, and suddenly the API bill, or the database one, is the fastest-growing line item. The usual cause of those costs isn’t traffic itself; it’s the same data being fetched far more often than it changes.

Illustration of a web application dashboard, Reducing API Costs in Next.js Applications
Next.js API costs grow faster than traffic when data is fetched more often than it changes.

Where Next.js API costs come from

Before changing any code, it helps to know which habit is behind the bill. In my experience it is almost always one of these:

  • Per-request fetches of slow-changing data. Product lists, settings and content pulled fresh on every page view.
  • Fetching from the browser. Every visitor calls the API separately, so nothing is shared between users.
  • Duplicate and sequential calls. Several components ask for the same thing, one after another.
  • Over-fetching. Full records come back when the page shows three fields.
  • Polling. A dashboard that refreshes every few seconds in every open tab, whether anyone is looking or not.
  • Bots. Crawlers count as traffic too, and every uncached page they hit is a fresh set of API calls.

Cache by how often data updates

If every page load hits an external API or database for data that updates hourly, you’re paying for thousands of identical requests. Next.js gives you layers: cache fetch responses, use Incremental Static Regeneration to rebuild pages on a schedule instead of per request, and cache expensive queries. Data that changes hourly should be fetched hourly, not on every visit.

In recent versions of Next.js, fetch is not cached by default, so caching is something you opt into. The Next.js caching documentation covers the model for your version. The patterns I use most are these:

  • With Cache Components enabled, put the 'use cache' directive at the top of a data function and give it a lifetime with cacheLife('hours') or a profile that matches the data.
  • On the previous caching model, set a revalidation time on the request, for example fetch(url, { next: { revalidate: 3600 } }).
  • When data changes on a known event, such as an editor publishing a post, revalidate by tag or path at that moment instead of using a short timer.
  • For database and SDK calls that do not use fetch, wrap the query in a cached function so it follows the same rules.
Infographic summarising “Reducing API Costs in Next.js Applications”: Where Next.js API costs come from; Cache by how often data updates; Kill waterfalls and duplicate calls; How to find what is costing you
The article at a glance.

Kill waterfalls and duplicate calls

Components that each fetch the same thing, or fetch sequentially when they could run in parallel, multiply requests. Fetch shared data once, higher up, and pass it down.

When two requests do not depend on each other, start them together with Promise.all instead of awaiting one before the next. When several server components need the same record in one render, wrap the loader in React’s cache so the call runs once per request.

Move work to the server, too. Fetching from the client means each user’s browser hits your API directly, and you can’t cache across users. Server Components and server-side fetching let you fetch once and reuse the result. And request only what you need: pulling full objects when you use three fields wastes bandwidth and, on metered APIs, money.

Deciding what runs where is its own skill, and server components vs client components gives a simple rule for it. If a client request fires twice in development, check Strict Mode before blaming your code; why your React app re-renders twice on every click explains why.

Polling and bots need their own fixes. For a dashboard, poll less often, pause polling when the tab is hidden using document.visibilityState, and only refetch when something has changed. For crawlers, make sure public pages are served from cache. A bot reading a hundred pages should cost you a hundred cache hits, not a hundred rounds of API calls.

Session checks are another hidden cost. If every request validates the session against an external auth service, a busy app pays for that on every page. Read the session from the cookie for quick routing decisions, and keep the full check close to the data. I cover that split in handling auth redirects in Next.js without the flicker.

How to find what is costing you

  1. Open your provider’s usage dashboard and sort endpoints by request count, not by cost alone.
  2. Log outgoing requests on the server with the route that made them, for one day.
  3. Compare requests to page views. If one page view triggers ten identical calls, you have found your leak.
  4. Check your host’s cache headers on the pages you expect to be cached, to confirm they really are.

Mistakes to avoid

  • Caching user-specific data under a shared key. One customer can end up seeing another’s details.
  • Setting revalidation to a second or two, which is barely different from no cache.
  • Disabling caching everywhere to fix one stale page, instead of revalidating that page when its data changes.

Most cost blowups come down to one habit: treating data that rarely changes as if it changes every request. Cache by how often data actually updates and the bill usually drops sharply. If yours keeps climbing and you want a second pair of eyes, this kind of audit is part of my web application development work.

Questions people ask

Does Next.js cache fetch requests by default?

Not in recent versions. Since Next.js 15, fetch requests are not cached by default, so you choose what to cache. You can set a revalidation time on the request or, with Cache Components enabled, use the use cache directive with a cache lifetime. Check the docs for the version you run, because the model has changed between releases.

What is the fastest way to reduce API costs in a Next.js app?

Find the endpoint with the most requests and ask how often its data really changes. If it changes hourly but is fetched on every page view, caching it for an hour on the server usually gives the biggest drop. Then remove duplicate calls and stop fetching fields the page never shows.

Is it safe to cache API responses in Next.js?

It is safe for data that is the same for every visitor, such as products, prices or published content. It is not safe to cache personal data under a shared key, because one user could see another user's details. Keep user-specific data either uncached or cached per user.

Should I fetch data on the client or the server in Next.js?

Fetch on the server by default. Server-side fetching lets you cache one result and reuse it for every visitor, keeps API keys out of the browser, and sends ready HTML. Fetch on the client only for data that depends on live interaction, such as search-as-you-type or a user's own changing state.

Comments

Leave a comment

0 / 3000
Comments are moderated. Links are not clickable and your email is never published. See the privacy policy.
keep reading

Related articles

Usually replies within a day
let’s talk

Tell me what you want to build

A website, an app, some automation, or something you’re still figuring out. Tell me the problem and I’ll give you a straight answer on what it takes. No pressure, no sales team.