Skip to main content

Caching

The client stores downloaded definitions in memory and also retains evaluation results. These are separate layers: evaluating a flag is normally a local operation, not an API call per check.

How Caching Works​

At initialization, the client downloads shared application/environment definitions. Later evaluations can use a retained decision or evaluate a loaded definition. Polling and optional live updates obtain new definitions; decision retention has its own TTL.

Configuration​

Cache TTL​

The default decision TTL is 60 seconds. Set cache_ttl(Duration::from_secs(...)) on the config or client builder. Do not treat TTL as an exact propagation-time guarantee, or assume that constructing a new EvalContext requests a fresh decision.

Maximum Cache Entries​

The default capacity setting is 10,000. Capacity handling attempts expired-entry cleanup and batch eviction; it is not an oldest-first or LRU contract.

Cache Keys​

Keep each operation's context owned by that operation. Supplying a context does not invalidate existing decisions. Choose refresh and retention behavior deliberately; context mapping describes the inputs used during evaluation.

Cache Invalidation​

Manual Invalidation​

Use these helpers with an initialized shared client:

use toggly::TogglyClient;

pub async fn refresh_definitions(client: &TogglyClient) -> toggly::Result<()> {
// Successful explicit refresh also clears retained decisions.
client.refresh().await
}

pub async fn clear_and_reload(client: &TogglyClient) -> toggly::Result<()> {
// This also removes in-memory definitions and signing-key state.
client.clear_cache().await;
client.refresh().await
}

Do not clear/reload on every incoming request. It discards shared definitions and adds avoidable network work. An application-owned refresh operation can be useful after an administrative configuration change.

Automatic Invalidation​

Periodic polling updates definitions. Do not equate the arrival of a new definition revision with an immediate change in every already-cached decision. client.refresh() is the explicit client operation that clears decisions after its definition refresh succeeds.

Memory Management​

The cache lives in process memory. There is no public client cache-statistics accessor or persisted evaluated-snapshot store. Do not access private client.cache or client.provider fields from application code.

Monitoring​

use toggly::TogglyClient;

pub async fn diagnostics(client: &TogglyClient) {
println!("Definition ETag: {:?}", client.etag().await);
println!("Last refresh error: {:?}", client.last_error().await);
println!("Loaded keys: {}", client.feature_keys().await.len());
}

An ETag identifies definition state; it is not a cache-hit ratio or a user's evaluated flag snapshot. last_error is the last definition-refresh error, not a record of every evaluation.

Best Practices​

Keep one client for the application's lifetime, prepare request context before evaluation, and avoid process-wide user mutation. Await close() after draining requests; close clears decisions and flushes enabled telemetry best-effort before signaling provider shutdown.

Signed Definitions and Live Updates​

Signed definitions and optional WebSocket updates use the same client lifecycle. Signing verifies definition authenticity; it does not add a disk snapshot API or an atomic export of evaluated flags. Configure these mechanisms through TogglyConfig.