What it does
Two capacity-only levers for concurrency. Query caching keeps the results of a report's landing-page queries in the capacity's cache so the model doesn't recompute them for the next user. Scale-out puts read-only replicas of a semantic model alongside the read-write primary, so query load spreads across nodes instead of queuing on one.
Key facts
- Query caching is available on Premium and Power BI Embedded, for Import models only. It doesn't apply to DirectQuery or to live connections against Azure Analysis Services or SQL Server Analysis Services.
- Only the initial page a user lands on is cached. Interacting with the report generates queries that aren't cached.
- Cached results are per user and per model context and always respect security rules, so RLS isn't bypassed. Personal bookmarks and persistent filters are respected too, and dashboard tiles powered by the same queries benefit once the query is cached.
- Three settings on the semantic model: Capacity default (which is off), Off, and On. Switching from On to Off discards the saved results immediately.
- The query cache refreshes when the model refreshes, which means a burst of queries against the model at refresh time. A lot of cached models on a loaded capacity can degrade performance during that window.
- Refreshes driven through the XMLA endpoint or the enhanced refresh REST API do not refresh the query cache. Only service-driven scheduled or on-demand refreshes do.
ClientCacheRefreshPolicyis an XMLA server property that overrides scheduled cache refresh for a whole workspace. 0 discourages background cache refreshes, -1 (the default) allows them.- Scale-out needs the workspace on capacity — PPU, P SKUs, A SKUs or Fabric F SKUs — and the large semantic model storage format enabled. Disabling that storage format disables scale-out and loses all sync information.
- Scale-out is on by default at tenant level but off for every model. Enabling it per model is a REST API operation, not a UI toggle.
- Replica count is decided by CU consumption, and all replicas combined can't exceed what a single model is allowed to consume on that SKU. Microsoft's own guidance: an F64 typically won't scale beyond one read-only replica, while F256 and F1024+ are more likely to add a second.
- If the capacity is loaded enough that adding a replica would cause throttling, no new replica is created.
- Manual and scheduled refreshes always sync to the replicas. REST API and XMLA refreshes need a manual sync when
autoSyncReadOnlyReplicasis false. - Power BI Desktop and live connection reports go to a read-only replica by default. XMLA clients and service refreshes go to the read-write primary. Append
?readonlyor?readwriteto steer.
When to use / skip
Query caching is worth switching on for a small number of heavily read, infrequently refreshed models where everyone lands on the same page. That's a narrow profile, and the default being off is a reasonable default — turning it on across a capacity trades a spike at every refresh for a saving at every open. Scale-out is for one specific problem: many concurrent users queuing behind a single model at a peak. If the complaint is "the report is slow" rather than "the report is slow at 9am when everyone opens it", scale-out is the wrong tool and the model is the right place to look.
Configuration decisions
- Whether query caching is on per model or left at the capacity default, and whether the capacity default is deliberate or inherited.
- Whether
ClientCacheRefreshPolicyis used to stop background cache refresh at workspace level on a busy capacity. - Whether scale-out is enabled per model, which means someone owns the REST API call and the PowerShell to go with it.
- Whether automatic replica sync stays on. Leaving it on is far simpler; turning it off is only worth it if you're controlling sync from a pipeline.
- Whether the SKU is big enough for scale-out to do anything — on F64 it will typically add one replica and stop.
Gotchas
- Scale-out with automatic sync disabled blocks a list of model changes: adding or deleting roles, changing role memberships, modifying or deleting data sources used by DirectQuery or Dual tables, and changes to OLS or dynamic RLS expressions. You have to disable scale-out, wait, make the change, and re-enable.
- XMLA and REST refreshes leave both the query cache and, with auto-sync off, the replicas stale. Teams who moved refresh to XMLA for good reasons often don't realise they've quietly broken both.
- Deleting a scale-out model and recreating one with the same name needs a five-minute gap for the replicas to clear.
- SQL Server Profiler doesn't work against a
?readonlyconnection string, and some DMVs return read-write information even when you asked for read-only. Diagnostics get confusing fast. - Live connection reports always land on the read-only replica even if the connection string says
?readwrite— except from Desktop, where they don't. That inconsistency is documented and still surprising. - Turning query caching off doesn't just stop future caching, it throws away what's there, so the next few report opens are slower than the steady state.
Consultant notes
- Set expectations honestly on scale-out. It addresses concurrency, not query speed, and on smaller SKUs it may add a single replica and no more. Clients hear "scale-out" and expect something dramatic.
- Both of these are late-stage tuning. If the model still has auto date/time on and a GUID column in the fact table, do that first — it's cheaper and helps more.
- If the client has moved to XMLA or REST-driven refresh, check the cache and sync implications as part of that change. It's the most common way these two features quietly stop working.
- Neither feature is self-documenting. Whoever inherits the tenant won't know scale-out is on unless you write it down, because it isn't visible in the UI.
Revisit if scale-out gains a UI, or after any change to how replica counts are allocated across SKUs.