What Are Watchers in PowerApps?
In PowerApps, a “watcher” refers to an element that continuously observes changes in the app, such as:
- OnChange Events: Monitors changes in input fields.
- OnVisible and OnStart: Triggers when a screen is loaded or an app starts.
- Formulas Evaluating Frequently: Functions like
Filter()
,LookUp()
, orSort()
running too often. - Collections and Variables Changing Dynamically: Updating large datasets repeatedly can cause performance lags.
- Timers, Data Refreshes, and Real-time Triggers: When too many timers or
Refresh()
functions are active.
When the number of watchers grows excessively, PowerApps has to constantly track multiple events, leading to slower performance and app crashes.
Step-by-Step Guide to Optimizing Watchers in PowerApps
Step 1: Identify Performance Bottlenecks
- Enable Debugging Mode: Use Monitor Tool in PowerApps to track execution logs and see which functions are running excessively.
- Check Network Calls: Open Developer Tools (F12) in your browser, go to the Network tab, and check how many requests PowerApps is making.
- Use Performance Profiler: PowerApps offers a built-in performance profiler to analyze response times for different elements.
Step 2: Reduce Unnecessary Watchers
1. Avoid Too Many OnChange Events
Problem: When a TextInput, Dropdown, or ComboBox has an OnChange
event, PowerApps continuously monitors it.
Solution:
- Instead of triggering an action for every keystroke, use a button click to apply changes.
- Example: Instead of this:
TextInput1.OnChange = Set(varSearch, TextInput1.Text)
Use this approach:Button1.OnSelect = Set(varSearch, TextInput1.Text)
This ensures updates happen only when needed, not for every character typed.
2. Reduce Unnecessary Timer Controls
Problem: PowerApps timers continuously track time and execute actions, consuming resources.
Solution:
- Disable timers unless they are absolutely necessary.
- Example: If a timer is used to refresh data every 5 seconds, replace it with a manual refresh button.
3. Optimize LookUp and Filter Functions
Problem: Too many LookUp()
, Filter()
, or Search()
functions in a gallery or screen force PowerApps to constantly evaluate data.
Solution:
- Store filtered results in collections or variables to reduce repeated computations.
- Example: Instead of:
Gallery1.Items = Filter(Orders, Status = "Pending")
Use:ClearCollect(CollectedOrders, Filter(Orders, Status = "Pending")); Gallery1.Items = CollectedOrders
This ensures filtering only happens once, not every time the gallery refreshes.
Step 3: Optimize Data Sources and Queries
1. Reduce Data Calls Using Delegation
Problem: Fetching too much data slows down performance.
Solution:
- Use delegation-friendly queries that fetch data efficiently.
- Example: Instead of
Filter(MyList, Title = "ABC")
, use indexed columns in SharePoint or Dataverse. - Use delegable functions like
StartsWith()
instead ofSearch()
.
2. Avoid Repetitive Data Refresh Calls
Problem: Using Refresh()
frequently forces PowerApps to reload all data, leading to performance issues.
Solution:
- Refresh data only when necessary, such as after form submission.
- Example: Instead of refreshing the whole dataset:
Refresh(MyDataSource)
Refresh only the needed record: PowerAppsCopyEditLookUp(MyDataSource, ID = SelectedRecord.ID)
3. Reduce Items in Galleries and Data Tables
Problem: If a gallery loads 1000+ items, it significantly slows down PowerApps.
Solution:
- Use pagination (e.g., load only 50 records at a time).
- Use Lazy Loading by showing a limited number of records initially and loading more when needed.
Step 4: Optimize Variables and Collections
1. Reduce Excessive Variable Updates
Problem: Setting variables too frequently increases processing load.
Solution:
- Use
Set()
andUpdateContext()
only when required, not inside repetitive loops. - Example: Instead of
ForAll(MyCollection, Set(varTotal, varTotal + Value(ThisRecord.Amount)))
Use PowerAppsCopyEditSet(varTotal, Sum(MyCollection, Amount))
This prevents the app from tracking multiple variable updates.
2. Clear Unused Collections and Variables
Problem: PowerApps keeps unused collections in memory, affecting performance.
Solution:
- Use
ClearCollect()
instead ofCollect()
to avoid unnecessary accumulation. - Use
Clear()
to remove unused data from memory.
Example:
Clear(MyCollection);
ClearCollect(MyCollection, Filter(DataSource, Status = "Active"))
Step 5: Optimize Screen and Component Loading
1. Load Data Only When Needed
Problem: If all data loads at app startup, the app slows down.
Solution:
- Load only essential data on app launch (
OnStart
event). - Load additional data on demand when a user navigates to a screen.
Example: Instead of loading everything on App.OnStart
, load data only when needed:
Screen1.OnVisible = ClearCollect(ActiveUsers, Filter(Users, Status="Active"))
2. Use Components Instead of Duplicating Controls
Problem: Duplicating the same UI elements on multiple screens increases app complexity.
Solution:
- Use Reusable Components instead of creating multiple copies of the same control.
- This reduces watchers since PowerApps tracks one component instead of multiple controls.