Power Apps – Canvas – Onstart How to avoid ruining your application
Table of Contents
- 1. Introduction
- 2. The OnStart Trap
- 3. Principles That Keep OnStart Healthy
- 4. Suggested Structure
- 5. Practical Tips
- 6. Final Checklist
- 7. Conclusion
- 8. References
1. Introduction
OnStart runs once when the app loads. It is tempting to treat it like a main() function, but that is where performance and maintainability regress. The goal is to keep OnStart as a thin orchestration layer and push real logic into the formula bar (named formulas, UDFs, tables, and styles).
Microsoft guidance for large canvas apps explicitly recommends using App.Formulas instead of App.OnStart and splitting long formulas into reusable parts. That direction is exactly what this article reinforces (see Build large and complex canvas apps).
2. The OnStart Trap
When OnStart becomes a dumping ground, apps slow down and become fragile. Avoid these patterns:
- Do not place core business logic in OnStart. Define UDFs and named formulas and call them from screens or controls.
- Do not load large datasets at startup. Load only what the first screen needs and defer the rest.
- Do not build long, monolithic formulas in OnStart. Split logic into named formulas and UDFs (see Build large and complex canvas apps).
- Do not call connectors inside loops. This multiplies network calls and kills load time.
- Do not mix unrelated responsibilities. Separate parameters, caching, user context, and UI defaults.
- Do not use OnStart as a hidden workflow engine. This breaks reusability and makes testing harder.
- Do not rely on screen state. Screen-specific setup belongs in Screen.OnVisible or screen-level UDFs.
3. Principles That Keep OnStart Healthy
Use these principles to keep OnStart small and safe:
-
Thin Orchestration Only
- OnStart should call setup steps, not implement them.
- Keep reusable logic in
App.Formulasand UDFs.
-
Deterministic and Idempotent
- Running OnStart twice should not corrupt state or create duplicates.
-
Fast First Screen
- Load only what is required for the first screen to render (see Overview of creating performant apps).
-
Separation of Concerns
- Keep environment/params, collections, user context, and theme settings in distinct blocks.
-
Concurrent Only For Independent Tasks
- Use Concurrent only when operations are truly independent (see Efficient calculations).
4. Suggested Structure
/*-----------------------------------------------OnStart-----------------------------------------------*/
// Flow response and parameters
With(
{ coFlow: 'SomeFlow'.Run() },
Set(vsFlowValue, coFlow.result)
);
// Deeplink routing (task focus)
If(
!IsBlank(Param("Source")),
Switch(
Param("SomeParameter"),
"TaskA",
/* setup for TaskA */,
"TaskB",
/* setup for TaskB */,
Blank()
)
);
// Global defaults and parameters
Concurrent(
Set(vsParamScreen, Param("Screen")),
Set(viParamItemId, Value(Param("ItemID")))
);
// Build month/period lists
ClearCollect(
colPeriodList,
/* data builder logic */
);
// Optional data enrichment (only if needed)
If(
RoundUp(Month(Now()) / 3, 0) = 1,
Collect(colPeriodList, /* additional rows */)
);
// Collections cache (first screen only)
ClearCollect(
colCache,
ShowColumns(SomeDataSource, /* required columns */)
);
/*-----------------------------------------------End OnStart-----------------------------------------------*/
5. Practical Tips
-
Use
App.Formulasto split logic and keep OnStart readable (see Build large and complex canvas apps). - Prefer named formulas for read-only values like constants, configuration, and lookups (see Get started with formulas in canvas apps).
-
Use explicit column selection like
ShowColumnswhen caching collections to reduce payload (see Efficient calculations). -
Prefer delegable query patterns such as server-side views and
StartsWith/Filterto avoid local loops (see Optimized query data patterns). - Cache only what is reused on multiple screens. If a collection is used on a single screen, load it there.
- Avoid Patch/SubmitForm in OnStart. Side effects at startup are hard to debug.
- Document the intent of each block with short comments.
6. Final Checklist
Before shipping, verify:
- OnStart runs fast and does not load unnecessary data.
- Logic is grouped into clear sections with comments.
- Business rules live in the formula bar (UDFs, named formulas).
- Screen-specific init is in Screen.OnVisible, not OnStart.
- Concurrent is used only for independent work.
- There are no hidden side effects or data writes on startup.
7. Conclusion
Keeping OnStart lean makes your app faster, easier to maintain, and easier to scale. Treat it as a launcher, not as the place where the app truly lives. The formula bar is where the app logic should grow.
8. References
Official Documentation
Performance and Optimization