Open-source project
arthurfiorette/axios-cache-interceptor avatar
arthurfiorette/axios-cache-interceptor

axios-cache-interceptor: putting a cache in front of an axios instance

📬 Small and efficient cache interceptor for axios. Etag, Cache-Control, TTL, HTTP headers and more!

817 stars67 forksTypeScriptMIT

At a glance

What is it?
axios-cache-interceptor is a TypeScript library that wraps an axios instance with HTTP-aware caching, so repeated calls to the same URL do not hit the network twice. The API surface is small, the package ships ESM and CJS builds, and the entry point you need is setupCache.
Who is it for?
Use axios-cache-interceptor when an axios client in your app or tests fires the same GET request more than once and you want the second call answered without touching the network. Do not reach for it if you need cache entries to survive a page reload, if you need to control revalidation server side, or if your application already depends on the browser HTTP cache semantics and the added layer only gets in the way.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 24, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem is repeated calls to the same URL

Most frontend codebases call the same endpoint more than once. A component mounts, fires a request, and a sibling component or a route guard fires the same request a moment later. Each of those calls is a real HTTP round trip, and each one can be made more or less at random by cache headers you did not write.

axios-cache-interceptor was created for exactly this situation. Its stated purpose is to help developers call axios multiple times without having to worry about overloading the network or implementing a simple and error-prone cache system. The description frames it as a cache interceptor for axios with ETag, Cache-Control, TTL and HTTP header handling, and the repository topics list etag, cachecontrol, ttl and http alongside axios and interceptor.

That makes the audience narrow and identifiable. It is for engineers who already use axios, mostly in a browser, and who want response reuse without writing an axios adapter and a cache map by hand. It is not a general HTTP client cache, and it is not aimed at teams that need durable, server side caching infrastructure.

The documentation lives at its own site, and the repository front page points there rather than trying to hold the whole reference inline. It also publishes a machine readable guide at a llms-full.txt path for assistants, which tells you the project treats its documentation as the real source of truth rather than the front page.

setupCache wraps the instance you already created

The whole integration is one function. You create an axios instance with Axios.create(), pass it to setupCache, and use the returned object as your client. The instance you pass in is still yours, so any interceptors, baseURL, timeout or adapter you configured before the wrapping stays in effect.

The front page gives this example, and it is worth reading closely because the two properties at the end are the API contract in miniature:

ts
import Axios from 'axios';
import { setupCache } from 'axios-cache-interceptor';

const instance = Axios.create();
const axios = setupCache(instance);

const req1 = axios.get('https://arthur.place/');
const req2 = axios.get('https://arthur.place/');

const [res1, res2] = await Promise.all([req1, req2]);

res1.cached; // false
res2.cached; // true

Two calls are started before either is awaited, and both are in flight at the same moment. The first response reports cached as false because it went out over the network. The second reports cached as true, so the library answered it without a second request. That is the behaviour the library exists to provide, and the cached flag on the response is how you tell the two cases apart in your own code.

Because the flag lives on the response object rather than in a separate result type, existing axios call sites keep their normal shape. You can read res.cached for a conditional render or a log line without restructuring the request layer.

HTTP metadata drives the reuse decision

The mechanism is not a blind key-value store with a timer on it. The package description names ETag, Cache-Control and TTL as first-class concerns, which means the library reads the HTTP semantics the server sends back and lets those decide whether a stored response can be reused, whether it must be revalidated, and when it should be discarded.

ETag is the interesting one for the case in the example above. If the server sends a validator with the response, a later request can carry it and the server can answer with a not-modified status instead of a full body. A cache layer that understands ETag turns that into an invisible saving, where the request still happens but the payload does not.

Cache-Control headers from the server carry the same kind of instruction, this time about freshness windows and about whether a response may be stored at all. TTL on the library side gives you a client side ceiling when the server does not express one. The three overlap on purpose: the server states what it can, the client applies a bound, and the library reconciles them.

The practical consequence for a reader is that cache behaviour in this library is not configurable through a single global switch. It follows from what the origin server sends, so an endpoint that returns no cache headers will behave differently from one that returns a long max-age. If you need predictable reuse, the server has to say something.

What the package manifest tells you before you install

The package manifest answers most of the packaging questions without guesswork. The published package name is axios-cache-interceptor, the type field is module, and the exports map lists the root entry with separate require and import conditions pointing at a CommonJS build and an ES module build, plus type declaration files for each.

The root export resolves through main for the CommonJS path, module for the ES module path, types for the declaration entry, and unpkg and jsdelivr for the browser bundle build. The dev subpath export is separate and points at its own dev builds, which is the entry the documentation site uses for live examples rather than something you should import in application code.

Two other fields matter for bundlers. The sideEffects field is false, which lets a bundler drop the module entirely when you import nothing from it. The repository also declares funding and an author, and points its bugs field at the GitHub issue tracker.

Reading package.json before installing is a habit worth keeping here. A library that offers a dev entry, two module formats and a prebuilt browser bundle is telling you it expects to run in more than one environment, and you can confirm your bundler picks the right condition from the exports map instead of discovering it later.

The toolchain that surrounds the source

The repository layout shows a project maintained with a modern TypeScript setup. The build script runs tsdown, and there are separate tsconfig.json and tsconfig.build.json files, so type checking and emit are configured independently. Formatting and linting are handled by biome, with distinct scripts for format, lint, lint-ci and a fix mode that applies unsafe fixes.

The test script runs the test suite under c8 and produces both an lcov report and a text report, which is why the project page links a Codecov badge. Documentation is a VitePress site built with vitepress build docs, and the dev script serves it on port 1227. A separate benchmark script exists as well, pointing at a benchmark directory and driving it with pnpm.

Release housekeeping is present too. The repository contains a CHANGELOG.md, an .auto-changelog directory, a pnpm-lock.yaml and pnpm-workspace.yaml, and an .npmignore alongside .gitignore, plus an examples directory with separate node and react projects and a runkit.js file.

The presence of runnable examples in node and react is the most useful of those for an evaluating engineer, because the library behaves differently depending on whether it runs in a browser or on the server, and the examples show both shapes.

Where this library is the wrong tool

The cache here lives in the memory of the running JavaScript process. Nothing in the front page describes writing entries to disk, to IndexedDB or to any store that outlives the process, so a page reload or a server restart starts with an empty cache. If your requirement is a cache that survives a navigation, this library does not describe that behaviour and you would need a storage layer of your own.

The library is also a client-side convenience, not a caching proxy. It does not sit between your users and an origin server, it does not share entries between users, and it does not give you a shared cache for a fleet of backend processes. Teams that need those things should look at an HTTP caching layer or a CDN rather than at an axios wrapper, and the useful framing is that this library reduces redundant calls inside one process while a shared cache reduces them across processes.

There is also a documentation boundary worth naming. The front page itself is mostly badges, a license section, one code example and a thank you to contributors. It does not document the available options for TTL, invalidation or storage, and it does not show an installation command. The details live on the linked documentation site. That is a legitimate choice for a project with a docs site, but it means you cannot evaluate the cache semantics from the repository front page alone, and the option names you will actually use are not visible there either.

Maintenance pace and the MIT boundary

The repository is not archived, and the last push was on 2026-10-19, four days before this review. Releases are frequent and recent: v1.13.0 was published on 2026-10-14, with v1.12.3 on 2026-08-04 and v1.12.2 on 2026-08-03. The current package version in the manifest is 1.13.0, matching the newest tag, so the published artifact and the release history line up.

Two tags close together in August followed by a gap before October suggests the project ships when there is something to ship rather than on a fixed calendar, and a fast-moving axios ecosystem means upgrade decisions come with the axios version you are on.

The licence is MIT, which permits use, modification and redistribution with the notice retained. There is no separate licence for the examples directory or the documentation, and no contributor licensing file is listed at the top level beyond the LICENSE itself and the standard contributor graph links. Practically, that means you can wrap the library inside a proprietary product, but you must keep the copyright and licence notice in copies and distributions.

The cost of adoption is low in licence terms and low in code volume. The cost sits in the dependency itself: one more package to keep in step with axios, and a caching layer whose decisions are visible to your application through the cached flag.

Editorial conclusion

Use axios-cache-interceptor when an axios client in your app or tests fires the same GET request more than once and you want the second call answered without touching the network. Do not reach for it if you need cache entries to survive a page reload, if you need to control revalidation server side, or if your application already depends on the browser HTTP cache semantics and the added layer only gets in the way. Before adopting it, check the documented options for TTL and cache invalidation on the documentation site, and confirm that the package version you install matches the axios version you use, since the library is distributed as a thin wrapper over an instance you create.

Frequently asked questions

How do I add caching to an axios instance with axios-cache-interceptor?

Create the instance with Axios.create(), pass it to setupCache from axios-cache-interceptor, and use the returned client. The front page example shows two parallel get calls to the same URL where the second response reports cached as true while the first reports false.

Does axios-cache-interceptor support both ES modules and CommonJS?

Yes. The package manifest sets type to module and its exports map provides separate require and import conditions pointing at a CommonJS build and an ES module build, each with its own type declarations, plus a browser bundle for unpkg and jsdelivr.

How does axios-cache-interceptor decide whether to reuse a response?

The package description names ETag, Cache-Control and TTL as core features, and the repository topics list etag, cachecontrol and ttl. The library therefore reads HTTP caching metadata from the server and applies client side lifetime rules rather than reusing every response unconditionally.

Where can I find the full option list for axios-cache-interceptor?

The front page points to the documentation site at https://axios-cache-interceptor.js.org rather than listing options inline, and it also exposes a machine readable guide at the llms-full.txt path on that site. The project page itself only shows a single usage example.

Does axios-cache-interceptor persist cached responses between page reloads?

The front page does not describe any persistent storage, so entries are held in the running process only. The repository lists examples for node and react and a runkit.js file, and the behaviour of each environment differs, so check the relevant example before relying on reuse across a reload.

Official sources

  1. arthurfiorette/axios-cache-interceptor on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/arthurfiorette-axios-cache-interceptor.svg)](https://hysenlabs.com/projects/arthurfiorette-axios-cache-interceptor)

Was this useful?