In Business Central 2026 release wave 2 (BC29), extensions published from Visual Studio Code are no longer uninstalled when a sandbox environment is updated or relocated. Microsoft noted the change in the BC Launch Event material rather than the release plan or the AL changelog, and Yun Zhu wrote it up on 8 October 2026: DEV extensions now behave like per-tenant extensions and stay installed after an update.
That sounds small. It isn't, if you've ever walked into a client UAT session and found the feature you demoed yesterday has vanished from the sandbox.
What the old behaviour actually was
Business Central sorts extensions into three scopes. Global apps come from Microsoft or the Marketplace. Per-tenant extensions (PTEs) are uploaded as .app files through the admin center or, historically, the Extension Management page. DEV extensions are the ones you publish straight out of Visual Studio Code, plus anything created with Designer in the client.
The scopes behave differently on upgrade, and the documentation is blunt about it. Upgrades preserve global apps in both environment types. The upgrade process never uninstalls PTEs from a production environment unless they're blocking the update during the enforced update period. But for DEV extensions, Microsoft's extension types and scope article states that when you upgrade or relocate a sandbox within the service, the process uninstalls them.
The data survives. That part has always been true, and it's repeated in the AL developer FAQ: the data of an app isn't removed, so you only have to republish and install the app to make it available. The code is what disappears, because the environment moves to a different service node running the new version.
There was a second-order effect that bit harder. The upgrade process also uninstalls any PTE that depends on a DEV extension. So a dependency chain that ended in a VS Code publish could take out apps nobody touched.
If you had partner telemetry switched on, the signal was there. The FAQ tells you to search for event ID LC0105, which carries a short description of why your environment was updated or relocated. Telemetry requires the applicationInsightsConnectionString property in your extension's app.json.
What BC29 changes
DEV extensions stay installed through a minor or major update. The practical consequence is that the sandbox a client logs into on Tuesday morning looks like the sandbox they signed off on Monday afternoon, even if Microsoft moved it overnight.
Be precise about the scope of the change, because the surrounding rules haven't moved. DEV extensions still only exist in sandbox environments. You still can't publish from VS Code into production and call it a deployment. And the warning in the sandbox environments documentation still stands: publishing an extension from VS Code with the same identifiers as an extension published to Marketplace is unsupported, and that app can be removed at any time. Identifiers here means the combination of appID and version, or name, publisher and version.
The Microsoft Learn pages describing the old removal behaviour hadn't been updated when Zhu published, and neither had the message VS Code shows you on publish. Treat the BCLE note as the statement of intent and verify on your own sandbox after BC29.1 lands.
The walkthrough: what your inner loop looks like now
The iteration loop doesn't change. You publish from VS Code, which under the covers is the al_publish tool in the AL Language extension. Its documentation lists four deployment modes. There's a full publish, an incremental RAD publish using delta compilation, a full dependency tree, and a skip build for an .app that a previous step already produced.
Through the AL MCP server, publishing an already-built app to a cloud sandbox looks like this, straight from Microsoft's example:
{
"appPath": "C:/build/output/MyExtension_1.0.0.0.app",
"environmentName": "sandbox",
"environmentType": "Sandbox",
"tenant": "contoso.onmicrosoft.com",
"skipBuild": true
}
Schema changes are governed by schemaUpdateMode, which defaults to Synchronize and also accepts ForceSync and Recreate. Cloud publishing authenticates interactively through MSAL with cached tokens; pass noCache: true when you need a fresh sign-in.
What changes is the decision you make around that loop. The old workaround, when a demo or a UAT window straddled an update, was to upload the app as a PTE instead. That gave you survival at the cost of a slower cycle, which Zhu calls out as the wrong trade when the code is changing frequently. With retained DEV extensions you keep the fast loop through the scheduled update and only promote to PTE when you actually mean to promote.
For promotion, use the admin center. The extension types article now says plainly that the recommended way to upload, install and manage PTEs is the Business Central admin center and its API, and that the in-product Extension Management upload flow and the Automation API extensionUpload endpoint are deprecated and planned for removal in 2027 release wave 1. The admin center PTE feature went generally available on 7 July 2026 and covers uploading packages, installing immediately or on a schedule, and viewing upcoming versions. The API accepts package uploads directly, and the new endpoints are exposed as tools through the admin center API MCP server.
So a sane pipeline in BC29 keeps VS Code publishes for the inner loop on a sandbox, sends anything you want governed through an admin center API upload, and stops reaching for the Extension Management page.
Where the limits still bite
It doesn't change your update obligations. Business Central ships two major updates a year, every April and October, and the update cycles documentation sets out the calendar around them. There's a preview period starting a month before GA, an update period of five calendar months from GA, a one-month grace period, then the enforced update period. During the enforced period, extensions that cause the update to fail might be automatically uninstalled so the update can succeed. Data belonging to those extensions isn't deleted.
Retained DEV extensions do nothing about compatibility. An app that doesn't compile against the new version is still a problem; it just now fails in a way you have to notice, where before it cleaned itself up by disappearing. Microsoft's own advice is to keep apps and PTEs ready to update at any time and to actively test compatibility.
It also doesn't make a DEV extension a deployment artefact. Sandboxes are where DEV extensions live. Production still takes PTEs and global apps, and the identity rules on id and version are unchanged.
One more thing to watch during the transition: anything in your process that quietly relied on the old cleanup. If you were counting on an update to wipe a half-finished Designer customisation off a shared sandbox, that no longer happens.
Getting BC data out for planning and forecasting
Extension lifecycle is one half of the ERP engineering problem. The other half is that finance and operations want the data somewhere they can model it, and that's a different pipeline.
If Databricks is where your analytics live, the managed Microsoft Dynamics 365 connector in Lakeflow Connect reads data through Azure Synapse Link, which exports Dynamics 365 data to Azure Data Lake Storage Gen2 as CSV or Parquet. It supports incremental ingestion, Unity Catalog governance, SCD type 2, and automated schema evolution for new and deleted columns; data type changes are not supported, and a pipeline tops out at 250 tables. Authentication is OAuth U2M only.
Pipelines are definable as code. From Microsoft's pipeline guide, a Declarative Automation Bundle resource file looks like this:
resources:
pipelines:
d365_ingestion:
name: 'd365_ingestion'
catalog: 'main'
schema: 'd365_data'
ingestion_definition:
connection_name: 'd365_connection'
objects:
- table:
source_schema: 'objects'
source_table: account
destination_catalog: 'main'
destination_schema: 'd365_data'
The workspace needs Unity Catalog and serverless compute enabled, and creating a connection needs CREATE CONNECTION on the metastore. The first run is a full refresh; subsequent runs ingest incrementally using the versionnumber cursor from Azure Synapse Link changelogs. Once the tables land in Unity Catalog, the forecasting and AI work sits on governed Delta tables instead of on extracts somebody mailed around. We write more about that pattern on our data integration page.
What I would tell a team moving to BC29
Test it before you change your process around it. BC29.1 was not out when Zhu wrote, and the Learn pages still described the old behaviour. Publish from VS Code to a sandbox, schedule the update in the admin center, and check whether the app is still installed afterwards. That's a half-hour test and it settles the question for your tenant.
Then do the cleanup this enables. Find the PTE uploads in your process that exist only to survive updates and move them back to VS Code publishes, so your iteration speed matches your iteration rate. Keep PTE promotion for the things that genuinely need governance, and move those uploads to the admin center API now, because the Extension Management upload path and the Automation API extensionUpload endpoint are going away in 2027 release wave 1.
And leave your compatibility testing alone. The update calendar hasn't moved, the enforced update period still uninstalls what blocks it, and an extension staying installed is not the same as an extension still working.
Frequently asked questions
Do DEV extensions still get removed when a Business Central sandbox updates?
Not in BC29. Microsoft stated in the 2026 release wave 2 launch event material that DEV extensions now behave like per-tenant extensions and remain installed after a minor or major environment update, which Yun Zhu documented on 8 October 2026. Before BC29, extensions published from Visual Studio Code or created with Designer were uninstalled when the sandbox was updated or relocated, although their data was retained.
What is the difference between a DEV extension and a PTE in Business Central?
A DEV extension is published from Visual Studio Code or created with Designer and exists only in sandbox environments, while a per-tenant extension is an .app package uploaded through the admin center and can run in production. Both are specific to your environment, but PTEs are the governed deployment artefact and DEV extensions are the development loop.
How should I upload a per-tenant extension now?
Use the Business Central admin center or its API, which Microsoft names as the recommended path; the in-product Extension Management upload flow and the Automation API extensionUpload endpoint are deprecated and planned for removal in 2027 release wave 1. The admin center API accepts package uploads directly, which makes it straightforward to call from a build pipeline.
Can I get Business Central data into Databricks?
Yes, through the managed Microsoft Dynamics 365 connector in Lakeflow Connect, which reads data exported by Azure Synapse Link to ADLS Gen2 as CSV or Parquet and writes governed tables into Unity Catalog. It supports incremental ingestion and SCD type 2, with a limit of 250 tables per pipeline.