A new version of AL is out, and keeping with tradition, I take a look at what’s new for developers in 2022 Wave 2, aka version 21. Check it out:

In this late-night release celebration video, Erik dives into everything new in Business Central AL version 21 (2022 Wave 2) — the “Hacker Edition.” He walks through the official Microsoft documentation, the AL extension changelog, and even fires up a decompiler to inspect the compiler DLLs for hidden changes. The goal: give you the full picture of what’s actually shipped versus what’s been promised for the wave.
Understanding the Wave Release Cadence
An important point Erik emphasizes right from the start: Microsoft uses six-month “waves” for their release cycle. Version 21.0 is the first release of 2022 Wave 2, but that doesn’t mean everything promised for the wave ships on day one. Expect features to trickle in through 21.1, 21.2, and beyond. Don’t be surprised when announced features aren’t immediately available.
The Official Feature List
Connect to Azure Functions from AL Code
Microsoft has announced a wrapper codeunit for easily connecting to Azure Functions from AL code. However, this one isn’t available yet — it’s slated for later in the wave (October 2022 timeframe). It will likely land in 21.1 or 21.2.
Application Area Inheritance
If you’ve ever been annoyed by having to type ApplicationArea = All; on every single control on a page, this one’s for you. You can now set a default ApplicationArea at the page level, and all controls will inherit it. This is long overdue and eliminates massive amounts of boilerplate. Compare the old way, seen in the source code:
page 50100 "My Customer THing"
{
Caption = 'My Customer THing';
PageType = Card;
SourceTable = Customer;
layout
{
area(content)
{
group(General)
{
Caption = 'General';
field("Allow Line Disc."; Rec."Allow Line Disc.")
{
ApplicationArea = All; // Previously required on EVERY field
ToolTip = 'Specifies if a sales line discount is calculated...';
}
field(Amount; Rec.Amount)
{
ApplicationArea = All; // Repeated over and over
ToolTip = 'Specifies the value of the Amount field.';
}
// ... and so on for every field
}
}
}
}
With version 21, you’ll be able to set this once at the page level and have it propagate to all controls.
Code Actions Across Workspace and Projects
Code actions (which were covered in a previous video on the channel) now support wider scopes. You can apply a code action across an entire project or solution — not just individual files. This is especially useful for bulk-fixing things like adding the Rec. prefix to implicit record references.
Resource Exposure Policy for Dev Extensions
Imagine a sandbox environment where multiple partners are working on a big project. Previously, dev-deployed extensions were always open for debugging by anyone with access. Now you can apply a resource exposure policy even to dev-deployed extensions, preventing other partners from debugging your code.
The app.json now includes these settings, and importantly, the defaults have shifted back toward openness:
{
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"runtime": "11.0",
"features": [
"NoImplicitWith"
]
}
Erik has a strong opinion here: unless you truly need to protect your IP and your customers are aware of that arrangement, make your source code downloadable. He’s seen too many cases where customers have an app running in Business Central, the original developer is gone, there’s no repo, no source anywhere — and nobody can download the code because the resource exposure policy blocks it.
Custom Actions (Power Automate Flows in Action Bar)
Despite the generic-sounding name, “custom actions” specifically means the ability to put a Power Automate flow trigger directly into the action bar of a page. Erik has reservations about this feature: the flow ID and environment are hard-coded in the AL code, which means any change to the flow requires redeploying the extension. Given how “fluffy” (frequently changing) flows tend to be, this feels like a better fit for the Simple Object Designer, where customers can manage their own flow integrations without developer involvement.
NoImplicitWith Enabled by Default
The NoImplicitWith feature flag can now be enabled as a default setting in app.json. Most developers have already been using this for years thanks to analyzer warnings, but it’s good to have it as an official default:
"features": [
"NoImplicitWith"
]
Debugging Improvements
Three significant debugging improvements arrive in launch.json settings:
- Exclude temporary records on break-on-record-write: When debugging, record write breakpoints can now skip temporary tables, reducing noise.
- Exclude try functions on break-on-error: This is the one Erik is most excited about. Certain codeunits (Azure Blob Storage, CRM integrations, etc.) are full of try functions that deliberately trigger errors to test conditions. When debugging, this causes an avalanche of breaks with no visible source code. You can now set
"excludeTry": truein the break-on-error configuration. - Launch in a specific company: When you have many companies in a database, your debug session can now target a specific startup company, rather than landing on whichever one the system picks.
IntelliSense Improvements
- Table keys are now suggested when defining sorting on data item properties.
- Record tooltips now show a primary key indicator — not just an asterisk, but actual primary key information visible both in tooltips and IntelliSense.
AppSource Monetization and Entitlements
Microsoft is building toward AppSource transactability with credit card payments and per-user licensing. For now, what’s available is the ability to define entitlements in AL that can be connected to future AppSource purchase mechanisms. An entitlement is essentially a new licensing primitive — if a user has paid, they get access to certain objects; if not, they get limited or no access. Erik notes this is “at least three years too late for a lot of partners” but is glad it’s finally moving forward.
Option Access Syntax in Formulas
Where you previously had to write raw numbers (e.g., a table number) in properties like SourceTableView, you can now use option access syntax like Database::Customer. This is more readable and protects against issues when objects are renumbered.
Data Transfer Object for Faster Upgrades
A new DataTransfer type enables raw, high-speed data copying during upgrade scenarios. Erik’s decompiler reveals the full API surface:
SetTables(SourceTable, DestinationTable)AddFieldValue(SourceField, DestinationField)AddSourceFilter(...)AddJoin(...)CopyFields()CopyRows()
Erik mentioned he asked Microsoft about using this outside of upgrade scenarios — for general high-speed data movement — and “they just smiled,” which may or may not be a promising sign.
XML Port Parameters via OData
In SOAP, you could pass an XMLPort as a parameter on a function exposed by a codeunit. Now the same capability comes to OData. Erik is somewhat puzzled by this choice, noting that most developers have been asking for the ability to pass JsonObject or JsonArray as parameters for OData-exposed functions instead.
Permission Set Composition with Exclude
This is a feature Erik plans to dedicate a full video to. You can now compose permission sets with both include and exclude logic:
- Permission Set 5 → includes Permission Set 4, excludes Permission Set 3
- Permission Set 4 → includes Permission Sets 2 and 3
- Permission Set 2 → includes Permission Set 1
Assigning Permission Set 4 gives you: 1, 2, 3, 4. Assigning Permission Set 5 gives you: 1, 2, 4, 5 (because 3 is excluded). This solves a real pain point where partners currently have to copy Microsoft’s permission sets, remove unwanted items, and then manually maintain them when Microsoft adds new objects in updates — with no delta communication from Microsoft about what changed.
Database Row Version Access
New properties LastUsedRowVersion and MinimumActiveRowVersion are now available and tagged with version 10.0 in the compiler. This gives AL code direct access to database row version information.
AL-Go for GitHub
While the AL-Go extension for VS Code has been around since the beginning (creating projects, setting up launch.json and app.json), AL-Go for GitHub extends this to full DevOps workflows with repos and CI/CD pipelines. A dedicated video is planned.
The Decompiler Deep Dive
Erik’s “hacker edition” approach involves decompiling the AL compiler DLLs to find what’s tagged for each runtime version. Everything in the compiler is version-tagged, and this tag controls what’s available based on the runtime setting in app.json:
"runtime": "11.0"
By searching for tags, Erik can verify which features actually shipped. Interesting finding: the Report.PrintOnlyIfDetail function is tagged with version 10.1 in the 10.0 compiler, and the changelog lists it under 10.1, yet it appears to compile when the compilation scope is set to cloud. The feature is there, even if the versioning is a bit confusing.
Also notable: between versions 9.0 and 10.0, there was very little activity in minor versions 9.1 through 9.5. Version 10.0 brought a significant batch of changes.
Other Notable Changes
- Promoted Action Groups and Action References: Part of the new modern action bar, which will be covered in dedicated videos.
- Generate/Update Permission Sets command: A new command replaces the old XML-based approach and the community-created “ALS as AL Creator” workaround.
- Code action settings enabled by default: Previously hidden behind secret settings that no one knew about — Erik’s earlier video on discovering and enabling these apparently got noticed by Microsoft.
- Improved compiler performance: General performance improvements, and Erik notes that credential caching seems significantly better — fewer re-authentication prompts compared to version 9.
- Snapshot debugging improvements: The snapshot debugger now shows all lines hit during the session, eliminating the need to place breakpoints everywhere.
- SQL lock visibility during debugging: You can now see SQL locks while debugging.
- New snippet for reports: The
treportsnippet now includes the default rendering layout property. - Option type equality: Option types are now always considered equal since they’re represented as integers, allowing direct comparison.
Version Milestone: AL Compiler 10.0
Erik points out a notable milestone: this is version 10.0 of the AL compiler. Remembering that NAV 2018 was version 0, we’ve now had 10 full releases of AL. The product is getting genuinely mature — “ahead of Linux,” as Erik quips (referencing Linux’s long stay on kernel version 6).
Summary
Version 21 brings a substantial set of improvements across debugging, permissions, IntelliSense, the modern action bar, entitlements, data transfer operations, and developer quality-of-life features. While not everything promised for 2022 Wave 2 has landed yet, the foundation is solid. The key takeaways: the debugging improvements (especially excluding try functions) are immediately impactful, permission set composition with exclude logic solves a real operational pain point, the data transfer object opens up fast upgrade scenarios, and ApplicationArea inheritance eliminates a huge amount of boilerplate. Let Erik know in the comments which features deserve dedicated deep-dive videos — and remember, Microsoft is watching too.