Power Apps Performance Optimization Guidelines
Power Apps Performance Optimization Guidelines Table of Contents Load Multiple Datasets Concurrently Write Formulas That Use Delegation Cache Data In Collect...
- Published
- Reading time
- 7 min read
Before you start
Is this guide for you?
- Best entry point
- Power Apps
- Time investment
- 7 min read
Imported reference from Matthew Devaney's blog for learning purposes. Original: https://www.matthewdevaney.com/power-apps-performance-optimization-guidelines/. Author: Matthew Devaney.
Power Apps Performance Optimization Guidelines Table of Contents Load Multiple Datasets Concurrently Write Formulas That Use Delegation Cache Data In Collections And Variables Limit The Size Of Collections
“Batch Patch” Multiple Changes To A Datasource Table At Once
Reduce Code In The App’s OnStart Property
Minimize Number Of Controls On A Single Screen
Enable DelayOutput For Text Input Controls
Do Not Reference Controls On Other Screens “>Eliminate The N+1 Problem Load Multiple Datasets Concurrently
Making connector calls sequentially is slow because the current connector call must be completed before the next one starts. The Concurrent function allows Power Apps to load data faster by simultaneously processing multiple connector calls at once. Only use the Concurrent function to retrieve data stored in cloud. There is no advantage to using concurrent when working with data already on the device (i.e. variables and collections). // Sequential code execution (slower)
Set ( gblUserProfile, Office365Users.GetUserProfileV2(User().Email) ); ClearCollect( colActiveProjects, Filter( Projects, ProjectStatus.Value= "Active" ) ) // Simultaneous code execution (faster) Concurrent( // Thread #1
Set ( gblUserProfile, Office365Users.GetUserProfileV2(User().Email) ), // Thread #2
ClearCollect( colActiveProjects, Filter( Projects, ProjectStatus.Value= "Active" ) ) ) Code language: JavaScript ( javascript ) Write Formulas That Use Delegation
Always write formulas that can be delegated to the cloud datasource . Delegation is when data operations such as filter, lookup and search are performed in the cloud (i.e. SharePoint, Dataverse) instead of on the user’s device. Data operations can be performed faster in the cloud because there are more computing resources than a laptop or mobile phone. Also, less data will be transmitted to the user’s device because it has already been filtered by the datasource.
Refer to the official Power Apps documentation to determine which Power Fx functions can be delegated. The supported functions are different for SharePoint , Dataverse & SQL . A warning will appear in the app checker when a function cannot be delegated.
Dataverse views are not subject to delegation rules. Use Dataverse views to write filter criteria that cannot be delegated using Power Apps formulas. Filter( 'Device Orders' ,
'Device Orders (Views)' . 'Active Device Orders' ) Code language: JavaScript ( javascript ) Cache Data In Collections And Variables
Store frequently used data in collections and variables . Data stored in memory can be accessed very quickly. A cloud datasrouce must receive a connector call, perform a query and send a response back to the device before data can be displayed on-screen.
// Store the currency exchange rates table in memory for quicker access ClearCollect( colCurrencyExchangeRates, 'Currency Exchange Rates' , ) Code language: JavaScript ( javascript ) Limit The Size Of Collections
Limit the size of collections to the least number of rows and columns that required by the app. Mobile devices have tight restrictions on memory usage. Collections are stored in the device’s memory. If too much memory is in use the mobile operating system will kill the Power Apps process and the app will crash.
Use the ShowColumns function to select only specific columns and drop the rest from the collection. Enable explict column selection to fetch only table columns used in the app when connecting to Dataverse.
// Selecting only desired columns from the accounts table
ClearCollect( colAccounts ShowColumns( Accounts, "name" , "city" , "state" , "zipcode" ) ) Code language: JavaScript ( javascript )
“Batch Patch” Multiple Changes To A Datasource Table At Once
Quickly update multiple records in the same datasource table by using the “batch patch” technique . “Batch patch” enables record updates to be made simultaneously. The traditional ForAll + Patch method is slower because it makes the updates sequentially. // Collection of records to update
ClearCollect( colUpdateEmployees, Table( { ID : 2 , FullName : "Alice Henderson" , Active : true }, { ID : 4 , FullName : "David Wright" , Active : false }, { ID : 5 , FullName : "Mary Allen" , Active : false } ) ); // Update records one-by-one (slower)
ForAll( colUpdateEmployees, Patch( Employees, LookUp(Employees, ID=colUpdateEmployees[@ID]), {
FullName : colUpdateEmployees[@FullName],
Active : colUpdateEmployees[@Active] } ) );
// Bulk update multiple records at once (faster)
Patch( Employees, ShowColumns( colUpdateEmployees, "ID" , "FullName" , "Active" ) ); Code language: JavaScript ( javascript )
Reduce Code In The App’s OnStart Property
The more code that is in the app’s OnStart property , the longer an app will take to start. Improve app startup time by initializing global variables in the OnVisible property of the app’s first screen. If possible, further defer setting variables until the screen they are needed.
Time to first screen metrics can be found in the app’s Analytics page. Go to the maker portal, click on the three dots beside the app, select Analytics (preview), then choose Performance.
Minimize Number Of Controls On A Single Screen
Every control added to a screen increases memory usage when the screen loads. Try to achieve a screen design with the fewest controls possible. A screen with fewer controls on it is faster to render and consumes less memory. For screens with too many controls, consider dividing their functionality across multiple screens.
Use a gallery to display repetitive controls . Each control in a gallery only counts as 1 control no matter how many times it is shown.
Enable DelayOutput For Text Input Controls
The Text property of a text input is updated after each keystroke. Set the DelayOutput property of the input to true to wait until after the user stops typing. This is useful when building a search bar connected to a gallery. With DelayOutput enabled the app will only make one request to the datasource when typing stops, as opposed to each keystroke.
Do Not Reference Controls On Other Screens
When writing formulas, only reference controls on the current screen. Do not reference controls on other screens. It will force Power Apps to keep that other screen in memory even though it is not being displayed on the device. Use a global variable to store the values found on other screens and refer to the variable instead. Eliminate The N+1 Problem
The N+1 problem is caused when an app must make N+1 connector calls, where N is the number of items. For example, let’s say we want to display a list of business Contacts in a gallery. The Items property requires 1 connector call to get Contacts from the datasource. // ITEMS property of a gallery Contacts Code language: JavaScript ( javascript )
Each Contact has a related Account (i.e. an organization). To display the Account Name we insert a label into the gallery with this code in the text property. As a result one additional connector call must be made for each row in the gallery. If there are 100 rows in the gallery, there will be 101 total connector calls total (1 gallery +100 rows).
// TEXT property of the account name label
LookUp(Accounts, ID=ThisItem.AccountID, 'Account Name' ) Code language: JavaScript ( javascript )
The solution to the N+1 problem for Dataverse is quite simple. Dataverse automatically fetches the required data in related tables during the connector call for Contacts.
// TEXT property of the account name label ThisItem.Account. 'Account Name' Code language: JavaScript ( javascript )
SharePoint lists are not a relational database and cannot return all related data in one connector call. We cannot eliminate N+1 but we can reduce the number of connector calls to SharePoint. Collect all data in the Accounts and Contacts prior to opening the gallery screen. Then add a new column called “Account Name” to the Contacts table by joining it with the Accounts table. Display the resulting collection in the items property of the gallery.
// Download all contacts and accounts prior to entering the gallery screen
ClearCollect(colAccounts, Accounts); ClearCollect(colContacts, Contacts); // Join tables to get account name
ClearCollect( colGalleryData, AddColumns( colContacts,
"AccountName" , LookUp(colAccounts, ID=ThisItem.AccountID, 'Account Name' ) ) ); // new ITEMS property of the gallery colGalleryData Code language: JavaScript ( javascript ) Did You Enjoy This Article? 😺
Subscribe to get new Copilot Studio articles sent to your inbox each week for FREE Enter your email address Sign Me Up Questions?
If you have any questions about Power Apps Performance Optimization Guidelines please leave a message in the comments section below. You can post using your email address and are not required to create an account to join the discussion.
Tagged
Power Apps
Have a Microsoft 365 topic idea?
Share article suggestions, community session ideas, corrections, or real-world scenarios for future nextM365 learning notes.
Keep learning Microsoft 365
Explore more practical guides for SharePoint, Power Platform, Copilot Studio, migration, automation, governance, and security.
Continue learning
Related tutorials
Related questions
Related comparisons
Next action