Boost Your Canvas App Speed: Essential Performance Techniques
Accelerate data loading, minimize network calls, and handle large datasets smoothly in Power Apps.
A slow canvas app erodes user trust. When users must wait for data to appear or screens hang after every action, they quickly lose confidence in the solution. The good news is that a handful of deliberate design choices can dramatically improve response times—whether you are building for SharePoint, Dataverse, or SQL Server. This article presents five core performance techniques that apply to nearly any canvas app scenario.
To make these techniques concrete, imagine a sales‑pipeline app that relies on two SharePoint lists:
- Opportunities: contains 5,000+ rows with fields such as
Title,Stage,CloseDate, andAmount. - Activities: stores tasks and meetings linked to each opportunity by a lookup field.
Sales reps open the app, see their active opportunities, and want to update stages without delay. Without optimization, that simple workflow can become sluggish. Let's apply performance best practices step by step.
1. Let the Server Do the Work with Delegation
Delegation is the single most important performance concept in Power Apps. A delegable query sends the filter logic to the data source, so only the relevant records travel over the network. A non‑delegable query pulls every row to your app and filters locally—disastrous for large datasets.
Make your default gallery filter delegable by using functions that the data source supports. For a SharePoint list, avoid in operators or conversions inside Filter; rely on direct column comparisons.
Filter(Opportunities, Stage = SelectedStage && CloseDate >= DatePicker1.SelectedDate)
Always check the delegation warning indicator (the yellow triangle) in the formula bar. If you must use a non‑delegable step, push that logic to a server‑side flow or reduce the data volume first with a delegable filter.
Even delegable queries have data source limits—typically 500–2000 rows returned per request. If you need the full dataset for aggregation, consider using Power Automate or a Dataverse view.
2. Use App.Formulas Instead of OnStart Where Possible
Before reaching for Concurrent, consider App.Formulas (named formulas). Formulas defined in App.Formulas are evaluated just-in-time — Power Apps calculates each one only when it is first needed, rather than blocking the whole app at startup. This can cut load times dramatically for apps that previously had large OnStart scripts.
// In App.Formulas (preferred for static/infrequently-changed data) ActiveOpportunities = Filter(Opportunities, Stage = "Proposal"); RecentActivities = Filter(Activities, Modified >= Today() - 7);
Named formulas are also immutable, which prevents accidental overwrites and makes the app easier to reason about. Use Set/UpdateContext only for values that genuinely change at runtime.
Use App.OnStart (with Concurrent) for work that must run exactly once at startup with side effects — for example, logging a session, or loading data that a StartScreen expression depends on. For everything else, App.Formulas is the better choice.
3. Load Data Sources in Parallel with Concurrent()
When you do need imperative data loads in OnStart or a screen's OnVisible, use Concurrent() to fire them in parallel. By default, multiple formulas chained with ; run sequentially — each must finish before the next starts.
Concurrent( ClearCollect(colOpportunities, Filter(Opportunities, Stage = "Proposal")), ClearCollect(colRecentActivities, Filter(Activities, Modified >= Today() - 7)) )
The total wait time becomes roughly equal to the slowest query instead of the sum of all queries. Use Concurrent() whenever you call multiple independent data sources or run multiple long-running operations that have no dependencies on each other.
Formulas inside Concurrent must not depend on each other. Power Apps flags cross-dependencies with a build error. Also, firing many concurrent calls against the same connector can trigger throttling (HTTP 429 errors) — space out calls or stagger them if you notice rate-limit failures.
4. Cache Static Reference Data Once
Lookup tables (products, regions, user roles) rarely change. Loading them on every screen visit wastes time. Load them once into a collection at startup and reuse that collection throughout the app.
If(CountRows(colProducts) = 0, Collect(colProducts, ShowColumns(Products, "ID", "Name", "ListPrice")) )
Pull only the columns you actually need using ShowColumns(); this reduces memory and speeds up retrieval.
5. Cap Collection Size—Don't Fetch Everything
Even with delegation, loading thousands of records into a collection should be avoided unless absolutely required. Use FirstN or TopN (depending on your data source) to restrict the number of rows. Apply filtering early to keep collections lean.
ClearCollect(colRecentOpps,
FirstN(
Filter(Opportunities, Stage = "Proposal"),
200
)
)When you need to work with a larger set for offline scenarios, consider incremental loading and paging patterns rather than one massive collection.
6. Batch Updates with Power Automate (or Minimize Patch Calls)
Individual Patch calls inside loops are slow: each call is a separate network round trip. When you need to create or update many records, collect the changes and send them as a batch through a Power Automate flow.
One common pattern: let the user edit a gallery, store modifications in a collection, and then call a flow that processes the entire collection in a single HTTP payload.
Set(varUpdateBatch,
ForAll(colEdits,
{OpportunityID: ID, NewStage: ProposedStage}
)
);
PowerAutomate.Run("BatchStageUpdate", varUpdateBatch)Inside the flow, use an Apply to each on the incoming array and update each record. The flow runs server‑side and can use connections that are faster than individual client calls.
If you cannot use a flow, at least combine all field changes for a single record into one Patch call rather than multiple calls. Also, avoid writing to the same data source inside a ForAll that iterates over a large set—it escalates network traffic.
Common Pitfalls to Avoid
- Using
Filterwithinoperator on SharePoint: this is not delegable and will pull the entire table. Use a conceptual workaround (e.g., an OData filter via a flow). - Calling
ClearCollectinside a screen repeat onVisiblechange: this triggers unnecessary reloads. Instead, load onOnHiddenof the previous screen or use a global flag. - Storing full records in variables: load only the fields you need with
ShowColumnsorDropColumns. - Forgetting to remove explicit column selections: if you use
AddColumnson a large table, you may cause high processing time.
Performance Troubleshooting
When performance degrades, use the built-in Monitor tool (Preview) to track network calls and formula evaluations. Look for long‑running requests, repeated loads of the same data, or non‑delegable queries that return many records.
Also inspect the App Checker for delegation warnings. If you find a query that is not delegable and cannot be avoided, reduce the data volume first with a delegable outer filter, or move the data to Dataverse where delegation support is broader.
Final Recommendation
Performance is not an afterthought—it must be baked into your design from the first screen. Prefer App.Formulas over OnStart, delegate early, load in parallel, cache smartly, and batch writes. Applying these six techniques consistently will create an app that feels fast even as data volumes grow.
Start by auditing your current app's App.OnStart — move static lookups to App.Formulas, then check for delegation warnings. Replace the slowest queries one by one. Your users will notice the difference immediately.
References
- Original article: Power Apps Performance Optimization Guidelines by Matthew Devaney
- Microsoft Learn – Delegation in Power Apps
- Microsoft Learn – Concurrent function
- Microsoft Learn – App.Formulas (named formulas)
- Microsoft Learn – Build large and complex canvas apps
- Microsoft Learn – Code optimization guidelines
Learn how small coding practices—like using descriptive names, flattening conditions, and simplifying logic—can make your apps easier to update and less error-prone.
Move past the gallery and discover the hidden patterns for validation, navigation, and smart submission handling in your data entry forms.
PowerShell unlocks admin capabilities that the Power Platform admin center simply doesn’t offer—from recovering deleted apps to blocking trial licenses. Here’s how to wield them safely.