v147 · pwa · in developer trial
PWA origin migration
A mechanism for developers to seamlessly migrate an installed Progressive Web App from one origin to a new, same-site origin — preserving user trust, permissions, and the installed app icon — without requiring the user to manually uninstall and reinstall.
chrome://flags/#enable-experimental-web-platform-features to test locally. Enterprise-managed installs (WebAppInstallForceList) will not be offered a migration.
at a glance
| Status in Chrome 147 | In developer trial (behind a flag) |
|---|---|
| Flag | chrome://flags/#enable-experimental-web-platform-features |
| Constraint | New and old origins must be same-site (same eTLD+1). Cross-site migration is not supported. |
| Enterprise | Migration is blocked when the app is force-installed via WebAppInstallForceList. A banner informs the user. |
| Standards position | Firefox: No signal · Safari: No signal |
| Spec | WICG manifest-incubations PR #136 |
| Chromium bug | issues.chromium.org/396504527 |
| Demo / sample | googlechrome.github.io/samples/pwa-migration |
| ChromeStatus | 5123349239955456 — PWA origin migration |
why it exists
A PWA's identity is bound to its web origin. When a developer needs to move to a new domain — due to rebranding, domain restructuring, or technical re-architecture — there is currently no upgrade path. The installed app on the user's device simply stops working or points to the wrong place, and the user has to manually uninstall and reinstall. This destroys any stored permissions, shortcuts, and the perceived continuity of the app. PWA origin migration introduces a first-party handshake: the old origin declares where it is moving, the new origin confirms the migration is intentional, and Chrome offers the user a seamless upgrade rather than a replacement.
Source: chromestatus summary field, May 2026.how the migration works
Migration requires cooperation from both the old origin and the new origin. Neither can unilaterally redirect an installed PWA to a different origin.
| Step 1: Old origin declares migration | The old origin's web app manifest includes a new migration_target field pointing to the new origin's manifest URL. |
|---|---|
| Step 2: New origin confirms | The new origin's manifest includes a migration_source field referencing the old origin. This two-way declaration prevents hijacking. |
| Step 3: Chrome offers migration | When Chrome detects the paired declaration, it shows the user a migration prompt explaining the change. The user can accept or decline. |
| Step 4: On acceptance | The installed app's identity is updated to the new origin. Permissions, shortcuts, and the icon are preserved where possible. |
| Enterprise block | If the app was force-installed by an enterprise policy (WebAppInstallForceList), no migration prompt is shown. Instead, a banner informs the user that migration is unavailable. |
manifest fields
migration_target | In the old origin's manifest. Value: URL of the new origin's manifest. Signals that the app is moving to a new origin. |
|---|---|
migration_source | In the new origin's manifest. Value: URL of the old origin's manifest. Confirms the migration is intentional and authorized. |
Specification divergence, both sides reported rather than resolved (fetched 2026-10-06): this page names the
manifest members migration_target and migration_source, while the merged WICG
manifest-incubations change that adds spec language for PWA origin migration (PR #136, merged 2026-03-11)
defines migrate_to (an object with id and install_url) and
migrate_from (a list of ids or objects) — the names this page uses do not appear in that
change at all. That change also requires the old origin to serve
/.well-known/web-app-origin-association with allow_migration: true, which this page's
hijack-prevention account does not mention, and it illustrates a same-site migration as
old.example.com to new.example.com, whereas this page's examples call
app.example.com and app.newexample.com same-site even though those are different
registrable domains.
example
Old origin manifest (app.example.com)
{
"name": "My App",
"start_url": "https://app.example.com/",
"migration_target": "https://app.newexample.com/manifest.json"
}
New origin manifest (app.newexample.com)
{
"name": "My App",
"start_url": "https://app.newexample.com/",
"migration_source": "https://app.example.com/manifest.json"
}
Constraint check: same-site for migration_target
// Valid: both origins share the same eTLD+1 (example.com)
// app.example.com → app.newexample.com — VALID
// app.example.com → totally-different.com — BLOCKED (cross-site)
Source: WICG manifest-incubations PR #136 and chromestatus summary, May 2026.
browser support
| Browser | Support |
|---|---|
| Chrome 147 | In developer trial (behind flag) |
| Edge 147 | Tracking Chromium |
| Firefox | No signal |
| Safari | No signal |
Status divergence, both sides reported rather than resolved (fetched 2026-10-06): ChromeStatus feature
5123349239955456 records this feature's developer-trial stage at desktop 147 and its active ship
stage at desktop 150 with status “Proposed”, while this page records the Chrome 147 developer trial and
does not carry the 150 ship stage. The flag this page names
(chrome://flags/#enable-experimental-web-platform-features) also differs from the flag the linked
Chrome sample gives (chrome://flags/#web-app-migration-api), and the record lists no Edge position
at all, so the page's “Edge 147” row is not confirmed by it.
see also
- chromestatus — PWA origin migration (5123349239955456)
- WICG manifest-incubations PR #136 — spec incubation
- Sample: PWA origin migration
- Chromium bug — issue 396504527
- Chrome Enterprise: WebAppInstallForceList — explains the enterprise block
- chrome-platform-showcase: PWA origin migration demos (when built)