
Some Business Central restrictions become so familiar that developers stop questioning them. They design around the limitation, build the workaround into the pattern, and eventually forget it was ever a choice rather than a fact of the platform. Version 29 just removed one of those restrictions, and I think it deserves more attention than a single line in a feature list usually gets.
The real question isn’t “what changed in v29’s indexing capability.”
The real question is “how much AL design has been quietly shaped around a rule that no longer needs to exist.”
The Rule That Shaped AL Design for Years
Keys defined in a table extension have always been secondary keys, since a table extension inherits the primary key of the table it extends. Version 18 solved half of the problem: before that release, a table extension could only build keys on the fields it added itself. From version 18 onward, a key could also be built on fields that already existed in the base table a real fix for a real category of performance issues, since a base-app key combining a field like External Document No. with another field left no useful index for a direct lookup on that field alone.
What version 18 didn’t solve was the mixed case, and the mixed case is the one that kept showing up in actual projects. A key defined in an extension could be all base table fields, or all fields from the extension never both together. The compiler enforced this directly, error AL0423, stating that the specified fields had to come from the same table.
Picture a Region Code field added to Sales Invoice Header for a customer’s regional reporting requirement. A user wants a list filtered by Sell-to Customer No. and sorted by Region Code, on a table with a few million rows. Sell-to Customer No. lives in the base table. Region Code lives in the extension. Under the old rule, those two fields could never share a key, regardless of how naturally they belonged together from a business perspective.
Why the Restriction Existed, and Why It’s Gone Now
This was never really a Business Central design decision. It was SQL. Under the old data model, fields added by a table extension were stored in a companion table, physically separate from the base table, joined at read time. Version 23 improved this by consolidating every extension on a table into a single shared companion table, so the server needed at most one join regardless of how many extensions were installed. But there were still two physical tables underneath, and SQL Server cannot build a single index across two separate tables. AL0423 wasn’t an arbitrary rule. It was the platform passing along the database’s actual constraint.
Version 29 changes the storage model itself. All fields on an AL table base and extension now live in the same physical table in the database, and Microsoft attributes the new cross-boundary key capability directly to that change. Once the fields are physically together, the reason for the restriction disappears. One table, one index, no conflict.
Verification Matters More Than the Announcement
Microsoft’s release notes describe the capability in a single sentence. That’s accurate, but a documentation sentence and a working feature aren’t always distinguishable from the outside on day one of a preview and this one doesn’t require database access or an on-premises release to check. It’s a compile test: define an extension with a key mixing a base table field and an extension field, then compile it once against version 28 symbols and once against version 29 preview symbols. Independent testing by BC practitioners confirms exactly the behavior the release notes describe the key fails to compile with AL0423 against v28, and compiles and publishes cleanly against v29, visible afterward in Index Management. That’s the difference between “the documentation says this is possible” and “this is possible, verified directly” the same instinct worth applying to the new SQL column-limit compiler warnings introduced in the same release.
What This Doesn’t Make Free
The constraint disappearing doesn’t mean indexes are now free to add without consequence.
The 40-key-per-table limit hasn’t moved, and it predates this change entirely. Cross-boundary keys are about to look very attractive on high-traffic tables, and on a table with several extensions installed, that budget gets consumed faster than anyone plans for. Every index also costs write an index that makes one list fast makes every insert and modify on that table slightly slower, and on tables like Sales Invoice Header, Item Ledger Entry, or G/L Entry, that’s not a theoretical cost worth ignoring. Adding an index to a large base table means building it during schema sync, which turns a small AL change into an upgrade-window question that deserves testing against real data volumes, not a demo dataset.
There’s a subtler risk too. Nothing stops several independent apps from each adding their own cross-boundary index to a widely extended table like Customer. Each decision is defensible in isolation, the write cost is shared across all of them, and no single publisher sees the whole picture. Anyone maintaining apps across multiple ISV environments should have this on the list of things worth checking before assuming a new index is free.
The AL0423 restriction shaped real architectural decisions for as long as it existed, and most of those decisions were reasonable given the constraint that existed at the time. Its removal doesn’t retroactively make those old workarounds wrong.
What it does mean is that the next key definition doesn’t need one, and developers who have spent years automatically reaching for a duplication pattern or a cross-table filter now have a genuinely simpler option one that’s worth testing directly rather than assuming from the release notes, and worth weighing against a 40-key budget and a write-cost tradeoff that haven’t gone anywhere.
Leave a Reply