GuardRateLeaderboard / docs /data-loading-cache_en.md
Anton Malykhin
fix: stabilize benchmark leaders, model benchmark sorting, and HF bucket reads
644ba85
|
Raw
History Blame Contribute Delete
15.4 kB

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-revalidate window 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:

  1. The page loader calls the corresponding Ranking, Details, or Tools state function.
  2. The state function calls fetchBucketRankingSnapshot({ refreshManifest: true }).
  3. refreshManifest: true bypasses the regular manifest TTL and reads the current small manifest.json from Hugging Face.
  4. If the returned snapshot_id matches the in-memory ranking snapshot, catalog and leaderboard are reused without another payload download.
  5. If snapshot_id changed, catalog and leaderboard are downloaded in parallel, their hashes and schemas are validated, and the ranking snapshot is replaced.
  6. Route-specific data is reused or rebuilt for the same new snapshot_id.
  7. 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: true always checks the manifest but reuses payloads when snapshot_id is unchanged;
  • forceRefresh: true also 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 stale and the UI can show a warning;
  • if no usable cache exists, the route returns an unavailable state 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:

  1. Generate all payload files.
  2. Use immutable or snapshot-specific file paths where practical.
  3. Calculate and write the SHA-256 hashes.
  4. Upload every payload file and verify it is readable.
  5. Create a manifest with a new unique snapshot_id, correct paths, hashes, counts, and schema version.
  6. Upload latest/manifest.json last.

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