Caching and Freshness
A cache remembers a successful result so the same request can avoid doing the work again. Pivot’s browser read cache uses the shared Query engine. Your backend may independently cache expensive SQL/OLAP results. These are two different places where work can be reused.
| Where | Who controls it | What a hit avoids |
|---|---|---|
| Browser Query cache | query on an HTTP store or createPivotQueryAdapter | A new request to your backend. |
| Application/backend cache | Your API/database infrastructure | Repeating the backend calculation after an HTTP request arrives. |
Reuse a recent response
Section titled “Reuse a recent response”Reuse a recent response
Compare actual simulated HTTP calls for reused, forced-fresh and uncached reads.
The example reads the same scope twice with a 60-second freshness window: one simulated HTTP call. Repeat cached reads adds no call while it remains fresh. Force fresh read adds one. Bypass Query twice adds two.
import { HttpPivotRemoteStore } from '@revolist/pivot';
const remoteStore = new HttpPivotRemoteStore({ baseUrl: '', query: { staleTime: 60_000 },});staleTime means “this response may be reused for this long.” The HTTP store and automatically managed custom adapters default to staleTime: 0, so a later read normally fetches again. gcTime controls how long an inactive entry stays in memory; it does not make it fresh. query: false disables Query caching and native automatic read policy.
Pivot refresh actions forward a fresh-read intent through PivotReadContext. For a direct store call, store.load(request, signal, { fresh: true }) explicitly fetches even under cached/static policies. store.invalidate() marks analytical reads stale; it does not flush your database server’s cache. Change configuration with a new provider/policy object, and dispose application-owned stores/wrappers after their consuming grids/controllers.
Share work while a request is running
Section titled “Share work while a request is running”Share a request, cancel one caller
Cancel one subscriber, retain its peer, and then request a fresh response.
Two callers asking for the same analytical window can share one pending backend request. Each caller owns its subscription. Cancelling one caller does not cancel its peer; the last cancelled subscriber aborts transport. This works with AbortSignals too.
The example starts two cancellable reads, cancels the first and displays the surviving response. It then makes another read with freshness zero, showing that sharing an in-flight request and reusing a completed response are different behaviors.
Promise-based Pivot reads release their observer when they settle. Polling options do not create an always-running refresh loop for an idle report. Use the Pivot/controller refresh lifecycle to acquire another result.
Know which requests are equivalent
Section titled “Know which requests are equivalent”Understand request identity
Compare object ordering, window changes, tenant scope and registry versions in real key generation.
A cache key is the address of a result. A different filter, axis window, field-registry version or authorized dataset must use a different address. Property ordering inside a plain object is irrelevant; array order can be meaningful.
The example compares real createPivotCacheKey results. requestId is for correlating a particular call; it is not the analytical identity used to share an equivalent read. Each caller receives its own response ID after validation.
Keep provider identity stable for the same authorized session. Share an explicit Query source only between readers of the same dataset/schema/tenant/authorization scope. Replace that scope when the identity changes. Never put credentials in cache-key labels. HTTP-store tenantId and datasetWatermark scope its client keys; they are not automatically added as routing/authentication fields to the request body or headers.
Understand backend cache status
Section titled “Understand backend cache status”Read backend cache metadata
Inspect the actual simulated backend response and its cacheStatus field.
“Server cache management remains separate” means your server owns its own optional result cache. For example, the browser can issue an HTTP request while the API returns a previously computed SQL result. Conversely, a browser Query hit may avoid HTTP entirely, so the server never sees that read.
response.meta.cacheStatus (hit, miss, warm or bypass) is reported by the backend. It does not prove a browser Query hit. This example reports bypass: the simulated backend computed the result rather than using a backend response cache.
Your API decides whether to cache results, for how long, and when data or permission changes make them invalid. Query configuration in the browser does not change those decisions. A datasetWatermark separates data versions in a key; the backend must supply or validate its authoritative data version and authorization scope.
Advanced integration
Section titled “Advanced integration”For native read options, shared scope setup and teardown, see Server Data Queries. For constructor options and wire fields see Remote API Reference. For trusted backend cache limits and security see Adapters and Security.
Query integration
Section titled “Query integration”The adapter wrapper explanation covers createPivotQueryAdapter. It is optional for custom read policy; ordinary adapters already use Query. No adapter wrapper is needed around a normal HttpPivotRemoteStore.