AL Development

Writing maintainable AL extensions for Business Central

June 2026 · 7 min read · Enhanced365 Solutions

After more than a decade building extensions in AL and, before that, C/AL, I've learned that the difference between an extension that ages gracefully and one that becomes a millstone rarely comes down to cleverness. It comes down to discipline — a handful of habits applied consistently. These are the ones I hold to on every commercial build and client project.

Prefix everything, without exception

Every object, every field, every control this app introduces carries the same affix. It looks fussy, but it's the single most important habit for a shared platform: it guarantees your objects never collide with Microsoft's, a partner's, or another app's, and it's a hard requirement for AppSource. Set the mandatory affix in AppSourceCop.json on day one and let the compiler enforce it, rather than relying on willpower.

One object per file

A codebase where E365PTPanelSetup.Table.al contains exactly one table is a codebase you can navigate blind. It makes diffs readable, merges sane, and onboarding painless. The few seconds it takes to create another file are repaid every time someone — including future you — goes looking for something.

Keep the public surface small

The part of your extension that other code depends on should be a deliberate, minimal contract: ideally a single facade codeunit and a set of published integration events. Everything behind that stays internal and free to change. When you need to refactor the guts six months later — and you will — a small, stable public surface is what lets you do it without breaking anyone who built on top of you.

Use the modern language properly

Enums instead of options. NoImplicitWith switched on. No stray Commit() calls papering over a design problem. These aren't stylistic preferences; they're what keeps an extension compatible and predictable as Business Central moves forward. Fighting the platform's direction is a debt you pay back with interest at every upgrade.

Fill in the unglamorous metadata

An ApplicationArea and a meaningful ToolTip on every field and action. DataClassification on everything that holds data. A permission set that actually reflects what the app touches. It's tedious, but it's the difference between an app that feels native and one that feels bolted on — and most of it is mandatory for AppSource anyway.

Choose keys by how you read, not just how you store

The primary key is obvious; the secondary keys are where performance is won or lost. Before adding a key, look at the actual filters and sorts your pages and queries use, and design for those read paths. A well-chosen key is invisible; a missing one shows up as a slow list the day a customer's data grows.

Write down your judgement calls

Every non-trivial build involves decisions that aren't self-evident from the code — why a value is stored this way, why a shortcut was taken, what was deliberately left out. I keep a short DECISIONS.md and log them as I go. It costs a sentence at the time and saves an afternoon of archaeology later.

None of this is exotic. It's the quiet, boring discipline that separates an extension you can hand over with confidence from one you apologise for. Maintainability isn't a feature you add at the end — it's a hundred small choices you make along the way.

al development

Need a custom BC extension built properly?

Every enquiry reaches the consultant who'd do the work — usually a reply within one business day.

See AL development