Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Refresh and Stale Reads

TTL says when a value expires. Refresh options say what the cache may do around expiry.

Use refresh behavior only when stale fallback is acceptable for the product path. It should be visible in code review.

    let cache = HydraCache::local().build();

    cache
        .put(
            "profile:42",
            Profile {
                id: 42,
                display_name: "Ada".to_owned(),
            },
            CacheOptions::new().ttl(Duration::from_millis(10)),
        )
        .await?;

    tokio::time::sleep(Duration::from_millis(20)).await;

    let value = cache
        .get_or_load_with_refresh(
            "profile:42",
            CacheOptions::new().ttl(Duration::from_secs(60)),
            RefreshOptions::new().stale_while_revalidate(Duration::from_secs(5)),
            || async {
                Ok::<_, LoadError>(Profile {
                    id: 42,
                    display_name: "Grace".to_owned(),
                })
            },
        )
        .await?;

    assert_eq!(value.display_name, "Ada");

stale_while_revalidate lets the cache return a recently expired value while a background refresh runs. Once the stale window expires, callers return to foreground loading.

Related choices:

  • refresh_ahead refreshes a value before expiry while still serving the fresh cached value;
  • stale_while_revalidate serves an expired value inside a bounded window and refreshes in the background;
  • stale_on_loader_error can return an expired value when the refresh loader fails.

Use diagnostics to confirm which path is happening in practice.