Skip to content

Angular 22+ · Zero dependencies · Signal-native · Tree-shakeable

SWR caching for Angular resource()

Stale-while-revalidate for resource(). Instant navigations, silent background refreshes.

Go back to a page you already visited and you get the spinner again. ziflux paints the cached value immediately and refreshes behind it, for as long as the entry is within expireTime.

If you know resource() and signals, most of this is already familiar. Three APIs, no runtime dependencies, 6.2 kB brotli enforced in CI.

npm install ngx-ziflux
order-list.store.ts
const todos = cachedResource({
  cache: this.#api.cache,
  cacheKey: params => ['todos', params.status],
  params: () => this.filters(),
  loader: ({ params }) => this.#api.getAll$(params),
})

What it feels like

Same app, same actions. One caches.

How caching works #

Two timers, three phases. invalidate() marks entries stale — it never deletes them.

FRESH

Return cached data

No network request

Data written to cache

STALE

Return cached + re-fetch

User sees data instantly, refresh in background

staleTime elapsed — data may be outdated

EVICTED

Fetch from server

Cache entry removed

expireTime elapsed — entry evicted

The docs add the loading-state table, cache keys and when to cache.

When ziflux is the wrong tool #

SWR caching is narrow on purpose. If your problem looks like one of these, reach for something else.

Cases where ziflux is the wrong tool, and what to use instead.
LimitWhy notUse instead
Real-time data (WebSocket / SSE)SWR assumes data ages on a wall clock. Push streams update on events, not on staleness.Subscribe to the stream directly. Cache the snapshot if you need offline display.
SSR transfer stateziflux is in-memory and does not serialize across the server/client boundary.Use Angular's TransferState for SSR hydration; layer ziflux on top after rehydration.
Persistence across browser reloadsThe cache lives in process memory and is gone on refresh.Persist explicitly with localStorage / IndexedDB; ziflux handles the in-memory layer above.
Volatile search-as-you-typeNew params on every keystroke means new cache keys. LRU thrashes; the cache becomes overhead.Debounce the input; cache only the stable result keys you actually want to revisit.
Angular before v22ziflux declares @angular/core ^22.0.0 as its peer range, so npm will refuse to install it on older majors. The code itself only needs resource(), which shipped earlier, but v22 is the supported floor.Stay on whatever cache pattern you have today; revisit when you upgrade.
Global state orchestrationziflux caches data; it does not coordinate workflows, side-effects, or cross-feature actions.NgRx, NgRx SignalStore, or a state machine. Pair it with ziflux for the data layer.

How ziflux compares #

You'll compare anyway, so here is the honest positioning.

TanStack Query (Angular)

Full data-fetching framework. Infinite queries, SSR hydration, persistence, cross-framework. Pick this if your data layer needs the whole toolbox. Its Angular adapter still ships as @tanstack/angular-query-experimental.

NgRx

Two things under one name: the classic Redux store (reducers, effects, selectors, time-travel) and @ngrx/signals SignalStore, which is signal-first. Pick either when caching is a side-effect of complex global state, not the goal. ziflux has no integration layer for it and does not need one: cachedResource() and DataCache only require an Angular injection context, so anything that provides one can host them.

ziflux

Caches resource(). That's the entire scope. Signal-native, no new mental model. Pick this when SWR on top of Angular's built-in primitives is all you need.

Mutation lifecycle (onMutate → mutationFn → onSuccess → invalidateKeys) is modeled on React Query: a proven shape with signal-native execution.

GitHub · MIT License · Zero dependencies

AI skills #

Give your AI coding agent deep ziflux expertise. Works with Claude Code, Cursor, Windsurf, and any skills.sh-compatible tool.

npx skills add https://github.com/neogenz/ziflux --skill ziflux-expert

Add it to one resource()

Caches resource(). Nothing else. Zero dependencies, 6.2 kB brotli, three APIs.

npm install ngx-ziflux
Read the docs