Flectic
Business Central Development - Platform-Neutral

Business Central Extensions: How AL Extensions Actually Work

A practical, platform-neutral guide to the extension-only model that runs modern Business Central - what AL extensions are, when to choose a Per-Tenant Extension (PTE) versus an AppSource app versus a DEV build, how the install and upgrade lifecycle works, and why upgrade safety is the long-term cost that decides whether BC customization pays off. Written by a partner that implements both Dynamics 365 and Odoo for SMEs across Canada, the UK, and the US.

Foundations

What Are Business Central Extensions?

A Business Central extension is an AL-language package that adds or modifies functionality without touching the base application's source code. Since Microsoft moved the product away from C/AL and C/SIDE - completing the shift at Business Central Wave 2 (version 15) - the product is fully extension-based. Even the base application itself ships as an extension, alongside the open-source System Application modules that partners can consume.

Extensions are written in AL (Application Language), Microsoft's only supported language for Business Central development. They use constructs like tableextension, pageextension, and enumextension - plus event subscriptions and interfaces - to extend base objects rather than overwrite them. This extension-only architecture is what lets Microsoft ship twice-yearly major release waves without partners re-merging customizations into the core - the exact problem that made the old C/SIDE base-code modifications so expensive to maintain.

If you are weighing BC against a modular platform like Odoo (where Odoo Studio customizations layer on top of the core in a similar no-touch way), the parallel is real but the mechanics differ: BC enforces a compiled, signed, version-bound package model, while Odoo's customizations sit inside the app's own inheritance chain. Either way, the strategic lesson for SMEs is identical - extend, do not modify the vendor's base code.

Developer basics

How AL Extensions Work

Development happens in Visual Studio Code with the official AL Language extension installed. The AL: Go! command scaffolds a new project against a sandbox tenant, generating the app.json manifest, launch.json, and a sample HelloWorld page - enough to publish to a sandbox on the first run.

An extension's identity lives in app.json: a unique app ID (GUID), a version number, dependencies on other extensions (including the base application and the System Application), and the object ID range assigned to the publisher. Microsoft's documented object ranges reserve 0-49,999 for the Business Central base application - it must never be used in extensions - while 50,000-99,999 is the range for customer and partner customizations (the classic PTE range). Higher reserved ranges are allocated by Microsoft to AppSource publishers, typically in the 70,000,000+ block.

Inside the package, AL enforces a clean structure: one object per .al file, a consistent prefix or suffix naming convention to avoid collisions, namespaces, PascalCase variables, 4-space indentation, and lowercase keywords. Microsoft's CodeCop and AppSourceCop analyzers enforce these conventions at compile time and flag issues before publish - AppSourceCop is mandatory for any app heading to AppSource validation.

The core decision

Extension Types: PTE vs AppSource vs DEV

Business Central supports three extension scopes, and choosing the right one is one of the most consequential decisions in any BC customization project. Microsoft's developer documentation defines them by scope: Global, Per-Tenant (PTE), and Dev.

Global apps are published by Microsoft or via AppSource and are available across tenants. Per-Tenant Extensions (PTEs) are uploaded directly to a specific environment and exist only there - their metadata and assemblies are not shared across environments, though a PTE can depend on Global apps, other PTEs, or DEV extensions. DEV extensions live only in sandbox environments and are uninstalled when the sandbox is updated or relocated, which is why they are strictly for development and throwaway exploration.

The simplest framing for an SME: if the customization would be valuable to many customers, build an AppSource app; if it is bespoke to one customer's processes, build a PTE; if it is throwaway exploration in a sandbox, use a DEV extension.

Per-Tenant Extensions vs AppSource apps at a glance
DimensionPer-Tenant Extension (PTE)AppSource app
AudienceA single customer environmentMany customers via AppSource
DistributionUploaded directly to the tenantPublished and marketed through AppSource
PricingNegotiated directly between partner and customerFree, free-trial, or transactable (per-user monthly/yearly)
Object ID range50,000-99,999 (customer/partner range)Microsoft-allocated reserved range (typically 70,000,000+)
Cross-environmentNot shared - unique per environmentShared across all installed tenants
Go-to-market effortLow - partner uploads the .appHigh - Partner Center plans, entitlements, Microsoft validation
End-to-end workflow

The AL Extension Development Lifecycle

A typical PTE engagement moves through a predictable loop. The partner scaffolds the project in VS Code, develops against a sandbox, tests, and then publishes the compiled .app file to the customer's production environment via the Extension Management page or, since 2024 release wave 2, through the Business Central admin center.

On first install, an optional Install codeunit (SubType = Install) runs two triggers: OnInstallAppPerDatabase fires once per database, and OnInstallAppPerCompany fires once per company. These triggers seed default data, set up configuration, or migrate entries from a legacy table. Install codeunits run on first install and on reinstall - they do not run on a version upgrade, which is handled by a separate Upgrade codeunit.

  1. 01
    Scaffold and develop

    Run AL: Go! in VS Code against a sandbox, write table/page/enum extensions and event subscribers, and validate with CodeCop and AppSourceCop analyzers.

  2. 02
    Test in sandbox

    Publish as a DEV extension to a sandbox, exercise the new behavior, and confirm no regressions against the base objects you extended.

  3. 03
    Package the .app

    Compile the project to a signed .app file with the correct app ID, version, and assigned object ID range recorded in app.json.

  4. 04
    Install or deploy

    Upload the .app to the customer's environment via Extension Management or the admin center (PTE), or submit to AppSource for Microsoft validation (Global app).

  5. 05
    Maintain and upgrade

    Ship new versions with an Upgrade codeunit that migrates data and schema between versions, using upgrade tags to keep each step idempotent.

The non-negotiable part

Upgrade Safety: Why Compatibility Matters

Business Central ships twice-yearly major release waves, and every installed extension must stay compatible with them. If a publisher lets an extension go incompatible and does not ship a compatible version in time, Microsoft can automatically uninstall the extension to keep the tenant operational - typically after a sequence of an incompatible-extension warning during the preview phase, a failed auto-update at the next major update, and a grace period for the publisher to respond.

Version-to-version migration is handled by an Upgrade codeunit (SubType = Upgrade). Microsoft's developer documentation defines its triggers: OnCheckPreconditions (and its PerDatabase/PerCompany variants) to fail fast if the environment is not ready; OnUpgradePerDatabase and OnUpgradePerCompany to perform the actual data and schema migration; and OnValidateUpgrade (with its PerDatabase/PerCompany variants) to assert the result is sound - an error here rolls the upgrade back.

Upgrade tags - recorded in a per-tenant upgrade tag table - are the recommended way to make each migration step idempotent, so a re-run does not double-apply data changes. The operational lesson is simple but easy to underestimate: every extension you install is a long-term maintenance commitment, not a one-time deployment. Either the publisher keeps it compatible with each major release wave, or the customer eventually loses upgrade headroom and risks an forced uninstall.

Admin operations

Managing Extensions: Install, Upload, Uninstall

Administrators manage extensions from the Extension Management page inside Business Central. From there they can install AppSource apps, upload and deploy PTE .app files, and uninstall extensions when no longer needed.

Since 2024 release wave 2, administrators can also manage Per-Tenant Extensions through the Business Central admin center and its API - the same surface already used to manage AppSource apps. This unifies PTE and AppSource operations and gives partners a cleaner remote-management story across environments.

Uninstalling an extension retains its data by default; the extension can be reinstalled later and the data is still there. To purge the data, an admin must explicitly choose to delete it - via clean-mode sync through the Administration Shell, or through the Delete Orphaned Extension Data page in the client. Dependents must be uninstalled first, which protects against accidentally orphaning another extension that relies on the one being removed.

Platform-neutral practice

How Flectic Approaches BC Extensions

Flectic implements Business Central (and Odoo) for SMEs across Canada, the UK, and the US. On BC projects we default to the fewest, most disciplined extensions possible - because every extension is a long-term upgrade commitment, and the partners who over-extend are the ones whose customers lose upgrade headroom two release waves later.

Our AI-Assisted Delivery model is designed to deliver up to 3x faster than a traditional partner engagement on suitably scoped work - not unconditionally, and never as a substitute for the prerequisites that actually de-risk a BC project: a clean RapidStart data load, a documented extension inventory, and an upgrade-tag discipline from version one. If your current BC environment has accumulated years of ad-hoc PTEs, an Extension Readiness review is usually the highest-value first step.

Frequently asked questions

What is the difference between a PTE and an AppSource app in Business Central?

A Per-Tenant Extension (PTE) is uploaded directly to one specific customer environment and exists only there, using the 50,000-99,999 object ID range. An AppSource app is published through Microsoft's marketplace, available across tenants, and uses a Microsoft-allocated reserved object ID range (typically 70,000,000+). PTEs are for bespoke, single-customer customizations; AppSource apps are for functionality many customers would pay for.

What is a DEV extension in Business Central?

A DEV extension lives only in a sandbox environment and is used for development and throwaway exploration. It is uninstalled automatically when the sandbox is updated or relocated, so it should never be used for production customizations. PTEs and Global (AppSource) apps are the two scopes that can run in production.

Do Business Central extensions run on version upgrades?

No. Install codeunits (SubType = Install) run OnInstallAppPerDatabase and OnInstallAppPerCompany triggers on first install and reinstall only. A version upgrade is handled by a separate Upgrade codeunit (SubType = Upgrade) with OnCheckPreconditions, OnUpgradePerDatabase/PerCompany, and OnValidateUpgrade triggers, made idempotent with upgrade tags.

Can Microsoft automatically uninstall a Business Central extension?

Yes. If an extension is incompatible with an upcoming major release wave and the publisher does not ship a compatible version within the grace period, Microsoft can automatically uninstall the extension to keep the tenant operational. This is why every extension is a long-term compatibility commitment, not a one-time deployment.

What happens to data when you uninstall a Business Central extension?

Uninstalling an extension retains its data by default - the extension can be reinstalled and the data is still there. To remove the data, an admin must explicitly delete it via clean-mode sync or the Delete Orphaned Extension Data page. Dependents must be uninstalled first, which prevents orphaning another extension that depends on it.

How are Business Central extensions different from Odoo Studio customizations?

Both layer on top of the vendor's base application without modifying core source code, but the mechanics differ. BC extensions are compiled, signed, version-bound AL packages with enforced object ID ranges and a formal install/upgrade codeunit lifecycle. Odoo Studio customizations sit inside Odoo's own inheritance chain and are managed in-app. Flectic implements both and recommends the fewest, most disciplined customizations on either platform.

Planning a Business Central customization or extension project?

Flectic implements Business Central (and Odoo) for SMEs across Canada, the UK, and the US - platform-neutral advice, Success by Design methodology, and AI-Assisted delivery designed to deliver up to 3x faster on suitably scoped work. Book an ERP Readiness Call and we will map your extension scope, object ID strategy, and upgrade-safety plan before any code is written.

Book an ERP Readiness Call
Response within one business day

Sources