The Three Things That Break Every Power Platform Migration (and How to Catch Them)
Every Power Platform migration I’ve been asked to rescue started the same way: someone exported a list of apps from the admin centre, and that list became the plan. Tenant-to-tenant after an acquisition, moving out of the default environment, or adding proper ALM under apps that were built straight in production. The scenario changes, but the list is never what actually needs to move.
Three problems come up on almost every estate. None of them is exotic, and all of them stay invisible until someone opens the app on the other side, usually the week after go-live and usually in front of users. Here they are, and how to catch them before cutover.
Problem 1: the apps and flows aren’t in a solution
Most of what makers build never starts life in a solution. They open the maker portal, build the app, and it lives directly in the environment, very often the default environment. That’s fine until the day it has to move.
A solution is the unit of transport in the Power Platform. It’s what you export and import, and it carries the environment-specific bindings. You can export a canvas app on its own as an .msapp file, but you only get the screens. You don’t get the flows it calls, the connection references, the environment variables or the dependency metadata the target needs. In other words, you get the screens but not the application.
So the real first task isn’t “move the apps”. It’s “work out what has to travel together, and build the solutions”. There’s a subtle trap here too: if you move an app but leave its sibling components behind in another solution, it arrives with references that point at nothing.
Problem 2: connections instead of connection references
A connection reference sits between a flow and the credentials it runs with. The flow points to the reference, the reference points to a connection, and on import you simply rebind the reference in the target environment.
Flows built before connection references existed, or built outside solutions since, bind directly to a connection. That causes two problems:
- Manual rework. Every one of those flows has to be opened in the target and re-pointed by hand. With a few hundred flows, that’s a project in its own right, and it lands on cutover weekend.
- Hidden identity changes. A connection is an identity. After import, a directly bound flow often runs as whoever imported it. It works fine, quietly running every night as the consultant who migrated it, until their account is disabled and a production process stops for no obvious reason.
The fix is to convert flows to use connection references while you package them, not after they land. The hard part is finding which flows need it, because that information lives inside each flow definition, not in any admin list.
Problem 3: hardcoded URLs inside apps
This is the quietest problem, and the one that bites after sign-off. Somewhere in the app there’s a button like this:
Launch("https://contoso.sharepoint.com/sites/Operations/Shared%20Documents")
Or a Patch() against a list referenced by its full URL, or an embedded Power BI report in the old tenant’s workspace. After migration, all of these keep working, because the old tenant usually still exists for months during an acquisition. Users carry on saving documents and reading reports in the old tenant, and nobody notices until a fortnight of real work is on the wrong side of the migration.
Admin APIs can’t find this. They tell you which connectors and data sources an app uses, but nothing about a string a maker typed into a formula. The only place it exists is the app’s source.
Why the project plan never catches these
The admin centre gives you apps, flows, owners, environments and modified dates. It won’t tell you that app A calls flow B, that flow B runs on a personal connection belonging to someone in finance, that neither is in a solution, and that the app’s main button opens a library in the tenant you’re leaving.
You can find all of it manually: export each app, unpack it, read the formulas, cross-reference flows and connections, and repeat a few hundred times. I’ve done it that way. It takes weeks, and it’s out of date by the first cutover.
The order that works
- Assess the whole tenant before agreeing the migration list. The list is an input to the plan, not the plan.
- Expand the list to its real dependencies: the flows each app calls, the connections and connectors, custom connectors (which must be rebuilt in the target first) and solution siblings.
- Search app sources for the source tenant’s hostname and anything else hardcoded, and fix those references before export, while you still have a working environment to test in.
- Convert flows to connection references while packaging them.
- Export who each app is shared with, so re-sharing is a checklist rather than a helpdesk queue on day one. Use it as a chance to fix apps shared with the entire organisation.
- Match objects by ID and environment, never by display name. Two environments often contain apps with the same name.
- Move in waves and track status, because a migration runs for weeks and everyone will ask which apps are where.
None of this removes the work. It removes the surprises, and the surprises are what wreck the schedule.
Tooling that helps
For the assessment, I use LogiSam’s Power Insights. It maps app → connector → connection → account, searches inside app packages for hardcoded strings such as the old tenant’s hostname, and exports sharing lists, which are exactly the gaps the admin APIs leave. Whatever tool you use, make sure it can see inside apps and flows, not just list them.
For ALM basics (solutions, pipelines, environment variables), see Power Platform ALM and Power Automate tips and the Power Platform governance guide.
FAQ
Can I migrate canvas apps without solutions?
You can export and import individual apps, but the flows, connection references and environment variables won’t come with them. For anything business-critical, package it in a solution first.
What is a connection reference?
A solution component that sits between a flow or app and a connection. When you import into a new environment, you map the reference to a connection there, without editing each flow.
How do I find hardcoded URLs in Power Apps?
Unpack the app source (for example with the Power Platform CLI) and search for hostnames, or use an assessment tool that reads app packages. Admin APIs alone won’t show them.

