The fastest way to turn Power Platform from an asset into a liability is to let everyone build whatever they like in the default environment, edit it live, and call that "agile." Low-code doesn't exempt you from application lifecycle management — it makes ALM more important, because the people building are often not developers. Here's the governance and ALM model that keeps a tenant healthy.
Environments: your first governance lever
An environment is an isolated container for apps, flows, connections, and (optionally) a Dataverse database. Treat environments as your dev/test/prod boundary:
- Default environment — every tenant has one, everyone can create in it, and it can't be deleted. Great for personal productivity; wrong for anything business-critical.
- Developer / Sandbox — non-production, used for building and testing. Sandboxes can be reset and copied.
- Production — backed by Dataverse, governed access, the home of released solutions.
Solutions: the unit of deployment
A solution is the package that carries your apps, flows, tables, and choices between environments. This is the heart of Power Platform ALM, and the managed/unmanaged distinction is the part everyone gets wrong at first:
| Unmanaged | Managed | |
|---|---|---|
| Where it belongs | Dev only | Test & Prod |
| Editable in place | Yes | No (locked) |
| Clean uninstall | No | Yes — removes its components |
| Think of it as | Source code | The compiled build |
You author in an unmanaged solution in Dev, export it as managed, and import that managed build into Test and Prod. Never develop directly in downstream environments.
Dev
Unmanaged · author here
Test
Managed · validate
Prod
Managed · release
The golden path: author unmanaged in Dev, export managed, import to Test then Prod.
Publishers and prefixes
Every solution belongs to a publisher, which stamps a customization prefix (e.g. contoso_) onto the schema names of everything you create — contoso_contract, contoso_status. Set a meaningful publisher up front; the default crxxx_ prefix is ugly and permanent once components are created under it.
Environment variables & connection references
The reason "it works in Dev but breaks in Prod" is almost always hard-coded, environment-specific values. Two solution components fix this:
- Environment variables — parameterise values that differ per environment (a site URL, an API endpoint, a config flag). Set the value per environment at import time instead of editing the app.
- Connection references — abstract which connection a flow uses, so the same managed flow binds to the right SharePoint/SQL connection in each environment without being edited.
// In Dev — define, don't hard-code:
Environment variable "ContractsSiteUrl" = https://contoso.sharepoint.com/sites/dev
// At Prod import — supply the prod value:
Environment variable "ContractsSiteUrl" = https://contoso.sharepoint.com/sites/contracts
Automating promotion
Two supported ways to move solutions, depending on maturity:
- Power Platform Pipelines — a low-code, in-product deployment pipeline. Define Dev → Test → Prod stages once and makers promote with a button (and optional approvals), no DevOps knowledge required.
- Azure DevOps / GitHub with the Power Platform Build Tools — full CI/CD: export the unmanaged solution, commit it to source control (unpacked into files), build the managed artifact, and deploy with gated releases.
# Power Platform CLI — the building blocks behind a pipeline
pac solution export --name ContractMgmt --managed false --path ./src
pac solution unpack --zipfile ./src/ContractMgmt.zip --folder ./src/ContractMgmt
# ...commit ./src to Git, then in the pipeline:
pac solution pack --folder ./src/ContractMgmt --zipfile ./out/ContractMgmt_managed.zip --packagetype Managed
pac solution import --path ./out/ContractMgmt_managed.zip --environment {prod-url}
Guardrails: DLP and managed environments
Governance isn't only about promotion — it's about what makers can do:
- Data Loss Prevention (DLP) policies — classify connectors as Business, Non-business, or Blocked. Connectors in different groups can't be used together in one app/flow, stopping (say) corporate SharePoint data from flowing to a personal Twitter connector.
- Managed Environments — a premium governance layer adding maker controls, sharing limits, usage insights, and weekly digests across your production environments.
- CoE Starter Kit — Microsoft's free Center of Excellence toolkit that inventories every app, flow, and maker in the tenant so you can actually see what's been built.
The takeaway
Power Platform ALM is the same discipline you'd apply to any software: isolate environments, package work in solutions, author unmanaged in Dev and ship managed to Prod, parameterise the environment-specific bits, and automate promotion. Layer on DLP, Managed Environments, and the CoE kit for guardrails and visibility. None of it requires heavy code — but all of it requires the engineering mindset that "it works on my screen" is the beginning of the job, not the end.