Power Apps Canvas App Performance Guide
A practical guide to diagnosing and fixing canvas app performance issues, covering delegation, data loading anti-patterns, the App Checker and Monitor tools, and a 10-point optimisation checklist your team can apply to any canvas app.
Why Canvas Apps Become Slow
Canvas app performance issues almost always share the same root causes: loading too much data from the wrong place at the wrong time. Understanding this principle makes 80% of performance diagnostics straightforward.
The key distinction: some operations happen on the server (fast), others happen in the browser (slow). Your goal as an app builder is to push as much computation as possible to the server side and keep the browser-side processing minimal.
The 5 Most Common Performance Anti-Patterns
Anti-Pattern 1: Non-Delegable Functions on Large Data Sources
Delegation means that a formula is sent to the data source to execute server-side. Non-delegable formulas pull all records into the browser and filter locally.
The most common non-delegable operations:
- Search() on most data sources (including SharePoint)
- Filter() with string functions: StartsWith() is delegable for many sources; Mid(), Len(), Lower() are not
- Sort() on calculated columns
- Any formula using CountRows() on an unfiltered collection
Fix: Use only delegable functions in your Filter and Sort formulas. Check the blue delegation warning triangle, if it appears on your formula, you are hitting the delegation limit.
Anti-Pattern 2: OnStart Overload
OnStart runs every time the app launches. Loading data collections, calling APIs, and computing variables in OnStart forces users to wait before seeing anything.
Fix:
- Move data loading to OnVisible of the first screen, data loads in parallel with the screen rendering
- Use Concurrent() to load multiple data sources simultaneously
- Load only the data you need on the first screen. Defer other data loading to OnVisible of subsequent screens
Anti-Pattern 3: Too Many Visible Controls
Every visible control on a screen is rendered by the browser, regardless of whether it's in view. Apps with 100+ visible controls per screen degrade rapidly.
Fix:
- Use a single-screen architecture with visibility control rather than many screens with navigation
- Set controls to Visible = false when not needed rather than positioning them off-screen
- Use galleries rather than individual controls for repeated patterns
Anti-Pattern 4: Nested Galleries
A gallery inside a gallery creates an exponential rendering problem. A parent gallery with 50 rows, each containing a child gallery with 10 rows, requires 500 controls to render simultaneously.
Fix:
- Flatten nested data into a single collection using AddColumns() and ForAll() during data load
- Use LookUp() inside gallery items rather than a nested gallery where the relationship is one-to-one
- For genuinely hierarchical data, consider a drill-down navigation pattern
Anti-Pattern 5: Unindexed Column Lookups
Filtering large SharePoint lists or Dataverse tables on non-indexed columns causes full table scans.
Fix:
- Index the columns you filter on most frequently
- For SharePoint: columns used in Filter formulas should have the Indexed property enabled
- For Dataverse: create column indexes in the Power Apps maker portal
Delegation myth: Many developers use ClearCollect() to load data into a local collection, thinking this solves the delegation problem. It does not. It just hides it. ClearCollect() is itself subject to the delegation limit. If your data source has 50,000 records and the delegation limit is 2,000, ClearCollect() will only load the first 2,000 records. The data is silently truncated.
Understanding Delegation Limits
The delegation limit is the maximum number of records Power Apps will retrieve from a data source when a formula cannot be fully delegated. The default is 500 records; you can increase it to 2,000 in Settings → App Settings → Advanced Settings → Data row limit for non-delegable queries.
2,000 is the maximum. You cannot increase it beyond this.
What this means in practice: any app that needs to work with more than 2,000 records must use only delegable operations for filtering and sorting.
Delegable functions by data source:
| Function | SharePoint | Dataverse | SQL Server |
|---|---|---|---|
| Filter (equals) | Yes | Yes | Yes |
| StartsWith | Yes | Yes | Yes |
| Search | No | Yes | Yes |
| Contains | No | Yes | Yes |
| CountRows | No | Yes | Yes |
| Sum/Average | No | Yes | Yes |
Where delegation is not available for your data source, migrate to Dataverse for the affected tables.
App Checker, Your First Diagnostic Tool
App Checker runs automatically in the Power Apps maker studio and flags errors, warnings, and performance recommendations.
To access: Click the tick icon in the left toolbar of the maker studio.
Key performance warnings to address immediately:
- Delegation warnings, your formula is not delegable
- Non-responsive layout, controls are positioned using absolute coordinates rather than responsive containers
- Unused variables, global variables that are set but never read
- Missing accessible names, required for accessibility compliance
Resolve all App Checker errors before publishing.
Monitor Tool, Deep Performance Diagnostics
The Monitor tool provides a real-time trace of every operation your app performs while it runs.
To access: In the maker studio, click Advanced Tools and then Monitor and then Play published app.
Key signals to look for in Monitor traces:
- High-latency data operations, rows showing response times over 500ms. These are your bottleneck.
- Repeated identical queries, the same data request firing multiple times per second
- Large payload sizes, responses over 1MB suggest you are retrieving too many columns or rows
- Error responses, 429 (throttled), 404 (not found), or 5xx errors from your data sources
Filter the Monitor trace to Network events to focus on data operations. Sort by Duration to identify the slowest calls.
Power Apps Performance Optimisation Checklist
| # | Check | Action |
|---|---|---|
| 1 | No delegation warnings in App Checker | Fix non-delegable formulas or migrate to Dataverse |
| 2 | OnStart is minimal | Move data loading to OnVisible |
| 3 | Concurrent() used for parallel loads | Wrap simultaneous ClearCollect calls in Concurrent() |
| 4 | No nested galleries | Flatten data or use drill-down navigation |
| 5 | Controls use Visible=false not off-screen | Review all controls positioned outside visible area |
| 6 | Indexed columns used for filtering | Add indexes to frequently-filtered columns |
| 7 | Only required columns retrieved | Use ShowColumns() to limit retrieved fields |
| 8 | App Checker shows zero errors | Resolve all errors before publishing |
| 9 | Monitor trace reviewed for slow queries | Address all operations over 500ms |
| 10 | App tested on a mobile device | Performance on mobile is the minimum acceptable standard |
Work With Us
Ready to Put This Into Practice?
Book a free consultation with our Microsoft-certified Power Platform team and get expert guidance tailored to your organisation.
