Spaces:
Running
Data loading and caching
This document describes the current implementation of data loading and caching in the HiveTrace Guardrail Leaderboard frontend.
The implementation has three goals:
- keep the private Hugging Face token on the SvelteKit server;
- avoid downloading and adapting unchanged bucket payloads;
- make repeated client-side navigation fast while providing a predictable data freshness window.
Architecture
Browser
-> SvelteKit page or __data.json request
-> Hugging Face Space Node process
-> private Hugging Face bucket
-> latest/manifest.json
-> payload files referenced by the manifest
The browser never reads the private bucket directly. All bucket requests are made by the
SvelteKit server with the server-only HF_TOKEN environment variable.
Data source
The bucket is configured with these runtime variables:
HF_TOKEN=<private read token>
HF_BUCKET_ID=hivetrace/leaderboard_frontend_v2
HF_BUCKET_PREFIX=latest
HF_BUCKET_REQUEST_TIMEOUT_MS=60000
HF_BUCKET_REQUEST_RETRIES=2
HF_BUCKET_ENDPOINT=https://huggingface.co
HF_BUCKET_ENDPOINT, HF_BUCKET_REQUEST_TIMEOUT_MS, and HF_BUCKET_REQUEST_RETRIES are optional.
The values above are their defaults.
HF_BUCKET_CACHE_TTL_MS still controls the regular in-memory manifest cache and the direct
Tools snapshot helper. The main Ranking, Details, and Visualizations page-data flow explicitly
refreshes the manifest after the browser cache misses, so this variable does not add another
freshness delay to normal client-side page transitions.
Manifest as the version pointer
latest/manifest.json is the single version pointer used by the frontend. Its important fields
are:
snapshot_id: the identity of the published dataset;files: paths to all payload files;hashes: SHA-256 hashes of the payload files;schema_version: the bucket contract version;- model, group, and dataset counts used for validation.
The frontend decides whether payload data changed by comparing snapshot_id. A new publish
must always use a new, unique snapshot_id.
Changing payload files or hashes without changing snapshot_id is not supported. In that case,
the frontend considers the snapshot unchanged and can continue using the old in-memory payload
until the Space process restarts.
Routes and payloads
| Route | Server loader | Bucket data |
|---|---|---|
/ |
getHfBucketRankingState() |
catalog, leaderboard, and details matrix |
/details |
getHfBucketDetailsState() |
catalog, leaderboard, and details matrix |
/tools |
getHfBucketToolsState() |
catalog, leaderboard, drilldown index, radar, scatter, heatmap, grouped bars, Pareto, performance, and robustness |
/methodology |
no bucket page loader | no bucket payload |
Ranking also uses the details matrix because the partial model status is derived from
metrics_evaluated_samples < sample_count.
The root +layout.server.ts reads the manifest separately to expose public bucket status such
as snapshot date and model count. That status uses the regular manifest cache. It is metadata
for the layout and does not control page-data freshness.
Client-side navigation
SvelteKit intercepts internal menu links and requests route data through endpoints such as:
/__data.json
/details/__data.json
/tools/__data.json
Localized variants are recognized as well, for example /ru/details/__data.json.
The response optimization in src/hooks.server.ts applies only to these three page-data
routes. It does not apply to Methodology, static assets, errors, or arbitrary API responses.
Browser cache
Successful page-data responses use:
Cache-Control: private, max-age=300
This means:
- each browser can reuse a route response for five minutes;
- the response is not a public CDN or shared-proxy cache entry;
- no
stale-while-revalidatewindow is used; - after five minutes, the next navigation must contact the SvelteKit server before rendering that route.
The cache is per response URL, including SvelteKit query parameters. Ranking, Details, and Visualizations therefore have independent browser cache entries.
An already rendered page does not update itself. Fresh data is applied on a later navigation or full page reload.
Gzip compression
The same hook compresses a page-data response when all conditions are true:
- the response is successful and has a body;
- its declared size is at least 1,024 bytes;
- the client accepts
gzip.
The compressed response contains:
Content-Encoding: gzip
Vary: Accept-Encoding
Content-Length is removed because the compressed body is streamed. Clients without gzip
support receive the original body with the same five-minute private cache policy.
Approximate measured sizes for the current dataset are:
| Route data | Uncompressed | Gzip |
|---|---|---|
| Ranking | 171 KB | 58 KB |
| Details | 643 KB | 158 KB |
| Visualizations | 709 KB | 122 KB |
These sizes depend on the bucket contents and will change as models and datasets are added.
Server request flow
When the browser does not have a fresh page-data response, the server follows this flow:
- The page loader calls the corresponding Ranking, Details, or Tools state function.
- The state function calls
fetchBucketRankingSnapshot({ refreshManifest: true }). refreshManifest: truebypasses the regular manifest TTL and reads the current smallmanifest.jsonfrom Hugging Face.- If the returned
snapshot_idmatches the in-memory ranking snapshot, catalog and leaderboard are reused without another payload download. - If
snapshot_idchanged, catalog and leaderboard are downloaded in parallel, their hashes and schemas are validated, and the ranking snapshot is replaced. - Route-specific data is reused or rebuilt for the same new
snapshot_id. - SvelteKit serializes the adapted route data, and the server hook applies the private cache header and gzip compression.
The important distinction between the snapshot options is:
refreshManifest: truealways checks the manifest but reuses payloads whensnapshot_idis unchanged;forceRefresh: truealso bypasses payload reuse and rebuilds the ranking snapshot.
Normal page transitions use refreshManifest, not forceRefresh.
In-memory caches
All server caches are module-level memory in the running Node process. They are private to a single Space replica and are cleared when the container restarts, sleeps, or is redeployed.
Manifest cache
src/lib/server/hf-bucket/cache.ts stores:
- the parsed manifest;
- the time it was fetched;
- its expiration time;
- one shared in-flight manifest request.
Regular callers use HF_BUCKET_CACHE_TTL_MS, with a five-minute default. Page-data refreshes use
the forced manifest path described above. Concurrent forced checks join the same in-flight
request when they overlap.
Ranking snapshot
The ranking snapshot contains the manifest, catalog, and leaderboard. It is cached by
snapshot_id.
Concurrent downloads of the same snapshot share one promise. In-flight requests are also keyed
by snapshot_id, so a request for a newly published snapshot does not accidentally reuse a
download for an older snapshot.
Details snapshot
The details snapshot adds details_matrix to the ranking snapshot and is cached by
snapshot_id.
This cache is shared by Ranking and Details. Ranking needs the matrix for partial detection, so
opening Details after Ranking does not download and validate details_matrix a second time.
Concurrent requests for the same details snapshot also share one promise.
Adapted Ranking and Details datasets
The UI-ready Ranking and Details objects are cached by snapshot_id. When the manifest is
unchanged, the server returns the already adapted object. A new snapshot is parsed, validated,
and adapted once per Node process.
Visualizations snapshot and adapted Tools dataset
For a new snapshot, the visualization files are downloaded in parallel. The raw visualization
snapshot and the adapted Tools dataset are cached separately by snapshot_id.
The direct getHfBucketToolsSnapshot() helper retains its TTL-based fast path. The /tools
page uses the state path, which refreshes the manifest after a browser cache miss.
Validation
Payload reuse is allowed only after the manifest version check. New payloads go through:
- JSON parsing;
- schema parsing;
- SHA-256 verification when a hash is present;
- manifest count checks;
- model, group, and dataset reference checks;
- matrix completeness and duplicate-pair checks;
- visualization reference checks.
A validation error is handled in the same way as another refresh failure.
Data freshness guarantee
Assume a valid new snapshot is published at time T and the bucket remains reachable.
Route response is already in the browser cache
The old route response can be used until its individual five-minute max-age expires. The first
navigation to that route after expiration reads the fresh manifest. If snapshot_id changed,
the same navigation waits for and receives the new payload.
Therefore, the expected guarantee is:
No later than the first navigation after the route's five-minute browser cache expires, the user receives the new snapshot.
There is no additional stale response window.
Route response is not in the browser cache
The navigation immediately contacts the server and checks the manifest. If the server already has the new payload, it reuses it. Otherwise, the navigation waits while the new snapshot is downloaded and adapted.
Full page reload
The five-minute policy targets SvelteKit __data.json navigation responses. A normal full HTML
request is not covered by this page-data cache and runs the server page loader again.
Exceptions
The five-minute expectation does not apply when:
- Hugging Face or the network is unavailable;
- the new payload fails parsing, hash checks, or validation;
- the publisher reused the old
snapshot_id; - the manifest was published before all referenced files became readable.
Failure behavior
The cache is also a resilience mechanism:
- if a refresh fails and a usable route dataset exists, the server returns cached data;
- if a new manifest is readable but a new payload is invalid or unavailable, the route state is
returned as
staleand the UI can show a warning; - if no usable cache exists, the route returns an
unavailablestate with an empty fallback dataset; - simultaneous requests share in-flight work to avoid duplicate bucket downloads.
One implementation detail is worth noting: when a forced manifest read fails but an older
manifest is cached, the manifest layer can return that stale manifest. The existing route data
can then continue to be served. The current route state does not always propagate this specific
manifest fallback as a visible stale warning.
Publishing a new snapshot
The producer must publish atomically from the frontend's point of view:
- Generate all payload files.
- Use immutable or snapshot-specific file paths where practical.
- Calculate and write the SHA-256 hashes.
- Upload every payload file and verify it is readable.
- Create a manifest with a new unique
snapshot_id, correct paths, hashes, counts, and schema version. - Upload
latest/manifest.jsonlast.
Publishing the manifest last prevents the frontend from seeing a new version that references files which are not available yet.
Cold starts and replicas
After a Space restart or cold start, no in-memory snapshot exists. The first request must read the manifest and all payloads required by that route. Later requests reuse the prepared data.
If the Space runs multiple replicas, each replica has its own memory cache and warms independently. The browser cache remains local to each user.
Operational checks
To inspect the page-data response headers, use an authenticated request to the Space:
curl -sS \
-H "Authorization: Bearer $HF_TOKEN" \
-H "Accept-Encoding: gzip" \
-D - \
-o /dev/null \
"https://<space-domain>/details/__data.json"
Expected headers include:
Cache-Control: private, max-age=300
Content-Encoding: gzip
Vary: Accept-Encoding
curl does not reproduce the browser's navigation cache unless an explicit curl cache is used.
Repeated curl requests therefore reach the server and can trigger repeated manifest checks.
When verifying a publish, check all of the following:
- the manifest has a new
snapshot_id; - every referenced file exists;
- hashes match the published contents;
- the Space logs contain no bucket validation errors;
- the first route navigation after browser cache expiration shows the new snapshot.
Implementation map
| Responsibility | File |
|---|---|
| HTTP bucket client and server-only token | src/lib/server/hf-bucket/client.ts |
| Regular manifest cache and in-flight request | src/lib/server/hf-bucket/cache.ts |
| Ranking snapshot download and validation | src/lib/server/hf-bucket/ranking-snapshot.ts |
| Shared details snapshot | src/lib/server/hf-bucket/details-snapshot.ts |
| Visualization snapshot download | src/lib/server/hf-bucket/tools-snapshot.ts |
| Adapted Ranking cache | src/lib/server/hf-bucket/ranking-cache.ts |
| Adapted Details cache | src/lib/server/hf-bucket/details-cache.ts |
| Raw and adapted Tools caches | src/lib/server/hf-bucket/tools-cache.ts |
| Browser cache headers and gzip | src/hooks.server.ts |
| Root public bucket status | src/routes/+layout.server.ts |
| Route orchestration | src/routes/+page.server.ts, src/routes/details/+page.server.ts, src/routes/tools/+page.server.ts |