Since runtime 11 (version 22) AL has had namespaces, and Microsoft has moved the whole base application into them. Most per-tenant extensions still do not use them. What a namespace is, what it fixes, how to structure yours, and how to adopt them in an existing app without breaking anything.
For most of AL's life, every object in a Business Central tenant lived in one flat list. Your Codeunit "Sales Helper", an ISV's Codeunit "Sales Helper" and Microsoft's could not coexist, so everyone prefixed everything: "CON Sales Helper", "ABC Sales Helper". Namespaces, introduced in AL runtime 11 with Business Central 2023 release wave 1 (version 22), fix that properly. Microsoft has since moved the entire base application into namespaces. Most partner and per-tenant code has not followed. It should.
A namespace is a dotted name declared at the top of an AL file that scopes every object in that file:
namespace Contoso.Sales.Pricing;
codeunit 50120 "Price Calculator"
{
...
}
The object's full name is now Contoso.Sales.Pricing."Price Calculator". Another app can have Fabrikam.Sales."Price Calculator" and the two do not collide. Within a namespace you refer to objects by their short name; from outside, you either qualify them or add a using directive at the top of the file:
namespace Contoso.Sales.Documents;
using Contoso.Sales.Pricing;
using Microsoft.Sales.Document;
codeunit 50121 "Order Pricing Handler"
{
[EventSubscriber(ObjectType::Table, Database::"Sales Line", OnAfterValidateEvent, Quantity, false, false)]
local procedure OnQuantityValidated(var Rec: Record "Sales Line")
var
Calc: Codeunit "Price Calculator";
begin
...
end;
}
Namespaces apply to object names only. Object IDs are still unique within the tenant and still come from the app's idRanges in app.json; namespaces do not change that.
"Setup" table or a "Helper" codeunit. Prefixes stop being necessary for uniqueness (though see below for why you may keep a short one for readability).Contoso.Sales.Pricing, Contoso.Warehouse.Labels, Contoso.Integration.Courier) tells a new developer where things are and what depends on what, without opening a folder tree. Microsoft's own code is the model: Microsoft.Sales.Document, Microsoft.Inventory.Item, Microsoft.Finance.GeneralLedger.Posting.using directives at the top of a file list exactly which parts of the base application and which other apps that file touches. A file with thirty using lines is telling you something about its design.Record "Sales Line" from a file without a using Microsoft.Sales.Document; gives a warning (AL0769 and relatives) that will one day be an error. Adopting namespaces is how you make that warning go away properly rather than suppressing it.Contoso.Integration.Courier."Shipment Sender" in an Application Insights trace tells you where to look.Root it on your organisation, then the functional area, then optionally the sub-area, following Microsoft's shape so the two read the same way side by side:
Contoso.Sales.Pricing, Contoso.Sales.DocumentsContoso.Purchases.ApprovalsContoso.Inventory.Items, Contoso.Warehouse.LabelsContoso.Finance.ReportingContoso.Integration.Courier, Contoso.Integration.WebShopContoso.System.Setup, Contoso.System.TelemetryRules of thumb: one namespace per folder, and the folder named for it; two to four levels; no namespace with one object in it; and the Microsoft.* and System.* roots are Microsoft's, so never declare one of those. If you are an ISV, root on your product (Fabrikam.ShopFloor.*) so that several of your products can coexist.
AppSource requires a registered affix (prefix or suffix) on object names and field names regardless of namespaces, because the affix also protects field names in table extensions, which namespaces do not cover. Per-tenant extensions are not required to use one, but a three-letter affix on fields and on objects that appear in the client (pages, reports, enum values) is still worth having: a user searching for a page sees "CON Courier Shipments" and knows it is yours, and a developer scanning a table extension can see which fields are Contoso's and which are an ISV's. So: namespaces for structure and uniqueness; a short affix for anything a human sees. The naming post has the convention in full.
Namespaces are not a breaking change for data: they change object names, not IDs, and the platform identifies objects by ID. So you can add a namespace to an existing object and its tables keep their data. The things to do in order:
runtime in app.json to 11.0 or higher (and therefore platform 22 or higher).namespace to each file. Visual Studio Code's AL extension has a code action to add the namespace from the folder path, and a refactoring to add missing using directives from the warnings.using lines; occasionally by qualifying an ambiguous name.using too: coordinate with them, or do it in two releases with the old flat names temporarily aliased. Event subscribers that name your objects are the usual case.For a typical per-tenant extension of a few hundred objects this is a day's work, mostly mechanical, best done at the start of a release wave when the regression tests are being run anyway.
Namespaces are how Business Central code is organised now. Microsoft's code uses them, the compiler nudges you towards them, and they make an extension easier to read, safer to combine with others and clearer about what it depends on. New apps should start with them. Existing apps should adopt them at the next quiet moment. The only reason not to is habit.