In Business Central 2026 release wave 2, AL developers can turn database indexes off and on from AL code. Microsoft shipped it to general availability in October 2026 under roadmap ID 573314, with the stated purpose that app publishers can ship index management to match their features.
That sentence is doing more work than it looks. Until now, a secondary key in an AL table or table extension was effectively a permanent decision made at compile time. You defined the key, the platform created the index in SQL, and every insert, update and delete in every company paid to maintain it. The only lever an app publisher had was to ship the key or leave it out.
What actually changed, in three releases
It helps to see this as the third step of a sequence instead of a single feature.
In 2022 release wave 1 (BC20), Business Central exposed the Database Missing Indexes page, which reads SQL Server's sys.dm_db_missing_index_details dynamic management view and lists the columns the query optimizer wishes were indexed, along with seeks, scans, average impact and an estimated benefit figure calculated as (seeks + scans) x (average total costs) x (average impact). Microsoft is explicit that these are suggestions and not mandatory, because indexes cost storage and slow writes.
In 2026 release wave 1 (BC28), administrators got the other half. They can now see which indexes exist, how much storage each one occupies, how often it has been used, and they can turn the unused ones off. That lives on the Table Data Management page, reached from Table Information, and it works per company. Microsoft's guidance is to turn off nonunique indexes with low usage to reduce storage costs and improve write performance.
BC29 moves that same capability into AL. The admin page actions now have code equivalents in codeunit 2000000029, "Index Management", which means an extension can decide its own index strategy at install time, at upgrade time, or when a user toggles a feature on in setup. Yun Zhu's walkthrough of the BC29 feature shows the updated methods mapping directly onto the actions on the Index Management page, with the index identified through table 2000000041, the virtual "Field" table.
Why per-company matters more than per-tenant
The detail that changes designs is this one. For per-company tables, a complete SQL table definition exists for each company, including all indexes. So you can define a key with Enabled = false and selectively enable it for a subset of companies without touching the others.
Think about what that means for an ISV shipping one extension to a tenant that runs eight companies. Maybe two of them use your advanced warehouse allocation feature and the other six installed the app because it came in the bundle. Before BC29, all eight paid the write cost on every index your feature needs. Now the six that do not use it carry none of it.
There's an asymmetry in the timing you have to design around. Disabling an index takes effect immediately. Enabling one is queued for the next scheduled midnight process, because SQL Server has to scan the whole table to rebuild the index, which the Table keys documentation also flags as potentially time-consuming. So you get a cheap, instant switch off, and a switch back on that's nothing you can do in the middle of a user's click.
A concrete walkthrough
Here is the shape of how a team would use it. Say your extension adds a reporting feature that filters Cust. Ledger Entry by a combination the base application does not index well. You ship the key disabled in the table extension, and enable it only where the feature is switched on.
First, define the key so the platform knows about it but SQL does not maintain it. From the table keys documentation, a secondary key becomes an index only when it's marked enabled:
tableextension 50100 "Cust. Ledger Entry Ext" extends "Cust. Ledger Entry"
{
keys
{
key(AgingAnalysis; "Customer No.", "Due Date", Open)
{
Enabled = false;
}
}
}
Then, when the user enables your feature in its setup page, call into the index management codeunit to switch the index on for that company. The exact method signatures are in codeunit 2000000029 in your BC29 symbols, and the illustration below shows the pattern instead of a verbatim API:
// Illustration of the pattern. Check the signatures in
// codeunit 2000000029 "Index Management" against your symbols.
trigger OnAfterValidate()
var
IndexManagement: Codeunit "Index Management";
begin
if Rec."Enable Aging Analysis" then
IndexManagement.TurnIndexOn(Database::"Cust. Ledger Entry", 'AgingAnalysis')
else
IndexManagement.TurnIndexOff(Database::"Cust. Ledger Entry", 'AgingAnalysis');
end;
The index name is the part people get wrong. You identify it through the virtual Field table (2000000041), which is also how you enumerate keys and check which fields are part of them.
Three rules constrain you, and they're not negotiable. Unique indexes, primary keys and the $systemid index all stay where they are. Every table in Business Central has a unique secondary key on SystemId, and the platform protects it. SIFT indexes are protected from the AL path too, though BC29 does give administrators a separate way to turn SIFT indexes on and off in the application.
What it costs and what it requires
No licence line item, no add-on. It's part of the platform in version 29.0, which started 2026 release wave 2 and is available worldwide on standard multi-tenant cloud. What it requires is a BC29 environment, your extension recompiled against the 29.0 symbols, and a decision about who owns the index strategy.
That last one is the real cost. An ISV that ships index management in code and an administrator who manages indexes from the Table Data Management page are now two parties with hands on the same lever. If your app turns an index on at every upgrade and the customer's admin turns it off every quarter because it looks unused, you have built a slow argument. Decide who wins before you ship, write it into the app's documentation, and make the AL side read current state before it changes anything.
Where the limits are
This is no substitute for writing queries that match your keys. If a list page is slow because a FlowField recalculates on every row, adding an index is treating a symptom; Microsoft's performance guidance for developers says to remove the calculated field from the page definition entirely, since setting Visible or Enabled to false isn't enough.
It's also the wrong tool for analytics. Turning indexes on in production so that a month-end report runs faster is paying a write-side tax, every day, for a read that happens twelve times a year. Business Central's transactional database is tuned for transactions. Heavy aggregation, multi-year trend analysis, forecasting and anything that joins ERP data to data from other systems belongs somewhere else.
That somewhere else is often Databricks, with one catch for Business Central readers.
The managed Dynamics 365 connector in Lakeflow Connect reads what Azure Synapse Link exports from Dataverse, and Business Central keeps its data in its own database, so that connector doesn't reach it. The pipeline gets built instead: a scheduled job reads the standard API pages with a lastModifiedDateTime filter, so each run picks up only what changed, or reads the tables the open-source bc2adls extension exports to a lake.
Once the data lands, the planning and forecasting workloads come off the ERP entirely, and the indexes you were keeping alive for them can go. If you're working out how to get ERP data into a lakehouse in the first place, we've written about that path, and about the reporting choice between built-in, Power BI and a lakehouse.
What to do first
Start by measuring before you write any code. Open Table Information, pick your five largest per-company tables, and look at the index storage size and usage statistics on the Table Data Management page. The index information comes from a virtual table called Database Index, which exposes the SQL dynamic management view with two sets of usage metrics, user* and last_user*. An index with a null last-user-seek is a candidate.
Then go the other way and open Database Missing Indexes, sorted by estimated benefit. Read both lists together. The pattern you want to find is an index you're paying for that nobody reads, sitting on the same table as a suggestion nobody has acted on.
Only after that should you put index management into AL. Ship new keys disabled by default, enable them from your feature's setup, and remember that enabling waits for midnight so your install experience cannot depend on it being ready. Log what you change and why, because in eighteen months somebody will ask why an index exists in company A and not company B, and the answer should live in the app where anyone can find it.
Frequently asked questions
Which Business Central version is needed to turn indexes on and off from AL?
Business Central 2026 release wave 2, version 29.0, where the feature reached general availability in October 2026. The administrator-facing version of index management, on the Table Data Management page, arrived one wave earlier in 2026 release wave 1 and applies to BC28 and later.
Can you disable a primary key or a SIFT index from AL?
No. Unique indexes, primary keys and $systemid indexes are protected and cannot be turned off, and SIFT indexes are protected from this path as well. BC29 gives administrators a separate feature for turning SIFT indexes on and off in the application.
How long does it take for a disabled index to come back?
Disabling is immediate; enabling is queued for the next scheduled midnight process, because SQL Server rebuilds the index by scanning the whole table. Design any feature toggle that depends on an index so it degrades gracefully until the rebuild completes.
Does turning indexes off reduce the Business Central database size?
Yes, and that is one of the stated reasons for the feature. Indexes consume storage, and Microsoft's guidance is to turn off nonunique, low-usage indexes to reduce storage costs and improve write performance. The Table Data Management page shows index storage size per index per company so you can see what each one is costing before you remove it.