Canvas Apps Performance Tips

February 14, 2025Power PlatformDevelopment

We've got about 15 Canvas apps in production at this point - everything from warehouse check-in screens to sales order entry to driver delivery confirmation. Performance has become an issue on some of them. Here's what we've learned about making Canvas apps actually fast.

Canvas Apps Performance Tips

The Delegation Problem

Canvas apps have a concept called delegation that trips up everyone eventually. When you write a formula that filters or sorts data, Power Apps tries to send that work to the data source (Dataverse, SharePoint, SQL). But not every function is delegable. When delegation fails, Power Apps pulls the data locally and processes it client-side, limited to 500 or 2000 rows depending on settings.

This means your app works great in development with 50 test records, then falls over in production with 50,000 real records.

The fix: know which functions delegate and which don't. Filter() delegates. Search() doesn't (usually). StartsWith() delegates to some sources but not others. Check the little warning icons in the formula bar - they're telling you when delegation isn't happening.

Collection Strategies

For lookup tables that don't change often - product categories, warehouse locations, customer types - load them into collections at app start. Once they're in memory, lookups are instant instead of round-tripping to the data source.

But don't go crazy. Loading 100,000 records into a collection at startup makes your app take 30 seconds to open. Balance between reducing data calls and not bloating initial load.

Our pattern: Static lookup tables (under 1000 records) go into collections at OnStart. Transactional data gets queried on-demand with proper delegation. User-specific data (like "my recent orders") gets loaded when needed and cached for the session.

Concurrent() Is Your Friend

If you're making multiple data calls that don't depend on each other, use Concurrent() to run them in parallel instead of sequentially. Loading user profile AND recent orders AND notifications? That's three data calls. Sequential: 1.5 seconds. Concurrent: 0.6 seconds. Users notice.

Gallery Optimization

Galleries with complex templates kill performance. Every item in a visible gallery has to render all its controls. If your gallery item has 15 controls with conditional formatting and multiple lookups, and you're showing 10 items, that's 150 evaluations every time the gallery renders.

Simplify gallery items. Move complex logic to variables that get calculated once. Use icons instead of images where possible. Consider lazy loading for galleries that could have many items.

The OnVisible Trap

Putting lots of logic in OnVisible seems intuitive - "when the user sees this screen, load its data." But OnVisible runs every time the screen becomes visible, including when navigating back from another screen. If you're reloading data unnecessarily, you're wasting time and API calls.

Better pattern: Use a context variable to track if data has already been loaded. Only fetch if the variable is false or if the user explicitly refreshes.

Measure Before Optimizing

Use Monitor (in the app checker) to see actual timing. Don't guess what's slow - measure it. We had an app where everyone assumed the gallery was the bottleneck, but Monitor showed the real problem was a complex Set() formula in OnStart that was recalculating every time a dependent value changed.

Power Apps isn't going to match native app performance, but with proper architecture, it's plenty fast for business applications. The key is understanding the platform's constraints and designing within them instead of fighting against them.

Planning an ERP modernization?

6 SAP-to-Dynamics conversions with zero business disruption. Let's discuss your project.

ERP Services Book a Call

If you’re a PE-backed operator or family-owned business working through similar technology and operations decisions, I’m always open to a conversation.

Schedule a CIO Strategy Conversation