Optimising Power Apps to improve user experience

Speed is crucial in ensuring good user experience in our Power Apps. Waiting for Power Apps and screens to load can be frustrating for users.  This article discusses strategies for making our PowerApps more efficient, and faster to load.

Use Collections to Cache data

Avoid duplicate network requests to external data sources by using Collections to cache data that can be referenced throughout our PowerApp. Keep in mind Collections can’t hold more than 2000 records and PowerApps sets to a maximum of 500 by default.

Load data sources when you need them

Avoid grouping calls to external data sources in the OnAppLoad screen. It is better to reference data sources in the OnLoad function of the screen that will be using that data. This will minimise the time the user has to wait before interacting with the app.

Use the Concurrent function to speed up formulae evaluation

The Concurrent function in PowerApps can be used to simultaneously evaluate formulae. This can be used to load multiple data sources at once, providing they don’t have any dependencies. This method avoids users waiting for the sum of all request times, as is the case with sequential formulae. See below for a comparison between sequential and concurrent formulae evaluation in PowerApps.

Sequential

In the example below 4 Collections are defined sequentially. Each makes a call to an external SQL database.

ClearCollect( Product, '[SalesDB].[Product]' );
ClearCollect( Customer, '[SalesDB].[Customer]' );
ClearCollect( SalesOrderDetail, '[SalesDB].[SalesOrderDetail]' ); 
ClearCollect( SalesOrderHeader, '[SalesDB].[SalesOrderHeader]' )

We can observe the increased time to execute sequential formulae in the network activity graph below.

Concurrent

In the example below the same Collections are defined, but this time they are enclosed within the Concurrent function. This allows the data to be retrieved simultaneously, resulting in less time to load the data.

Concurrent( 
    ClearCollect( Product, '[SalesLT].[Product]' ), 
    ClearCollect( Customer, '[SalesLT].[Customer]' ),
    ClearCollect( SalesOrderDetail, '[SalesLT].[SalesOrderDetail]' ),
    ClearCollect( SalesOrderHeader, '[SalesLT].[SalesOrderHeader]' )
)

The graph below illustrates the reduced time taken to execute the formulae when the same collections are wrapped in the Concurrent function.

 

Reference PowerApps global variable to reduce network calls

It is a common to use the Office365Users object in PowerApps to extract user profile information. We can optimize our PowerApps by defining this as a global variable in the OnLoad property of our first screen. We can then reference the UserProfile variable to avoid duplicate network calls each time we need to access user information.

Set global variable

Set(UserProfile, Office365Users.MyProfileV2() );

Reference global variable

Set(
    CurrentUserBlurb,
    "<b>" & UserProfile.displayName & "</b><br>" & 
    Text(Now(),"[$-en-US]dd/mm/yyyy")
);

This alone wouldn’t gain a significant performance improvement, however if we were making multiple calls to the Office365Users object in our PowerApp, the benefit would become more apparent. It is good practice to keep network calls to a minimum and consider this when developing PowerApps.

PowerApps settings for optimisation

There are a number features in PowerApps that can be used for improving performance.

Delayed Load

Delayed Load prevents all PowerApps screens from being loaded simultaneously when the app starts. Ensure this is turned on to significantly improve PowerApp load time. This function will not work if screens have dependencies between themselves, e.g. referencing a value contained in a label on different screen.

 

Explicit Column Selection

Loads a subset of only those columns in the data source that are referenced in the PowerApp. For example if Address Line 3 isn’t referenced anywhere in the PowerApp this column will not be fetched from the data source.