Docs / Build Workflow

Query Cache

Why cache matters

Every dashboard load triggers Malloy queries against BigQuery. Without cache, the same aggregations run on every page view — which means cost and latency scale with traffic, not with how often your data actually changes.

For most analytical workloads, data changes once a day or less. Adding a cache with a reasonable TTL makes dashboards fast for users and predictable in cost for you.

How it works: the sidecar file

Cache is configured per model using a sidecar file placed alongside the .malloy file. The sidecar has the same name as the model, with a .cache.yml suffix:

content/
  models/
    ec_revenue.malloy
    ec_revenue.cache.yml    ← cache config for ec_revenue.malloy
    ec_performance.malloy
    ec_performance.cache.yml

If no sidecar exists, queries run live on every request.

Working example

# content/models/ec_revenue.cache.yml

model: models/ec_revenue.malloy
defaults:
  cache:
    mode: auto
    ttl_seconds: 1800

Field by field:

  • model: path to the model this cache config applies to, relative to the workspace root.
  • defaults.cache.mode: set to auto. This is the only supported mode in the current version. It caches query results keyed by query name and parameter combination.
  • defaults.cache.ttl_seconds: how long cached results are valid. After this time, the next request triggers a fresh query and repopulates the cache. 1800 = 30 minutes.

Choosing a TTL

Match TTL to how often the underlying data actually changes:

  • Daily batch pipelines: ttl_seconds: 86400 (24 hours)
  • Hourly refreshes: ttl_seconds: 3600 (1 hour)
  • Near real-time: skip cache or use ttl_seconds: 300 (5 minutes)
  • Reports and document dashboards: ttl_seconds: 1800 (30 minutes) is a safe default

Setting a very short TTL on heavy queries does not make them fresher — it just makes them expensive. Match TTL to the actual data freshness SLA, not to how often users open the dashboard.

Cache and dashboard filters

Cache keys include the query parameters passed by dashboard filters. A user filtering by "2024" gets a cached result for that specific parameter combination. A user filtering by "2023" triggers a separate cache entry the first time, then hits cache on subsequent loads.

This means dashboards with many distinct filter combinations will have a larger cache warm-up cost. For document dashboards with a fixed default date, the cache is typically warm within one load.