Business Central Extension Architecture: A Practical AL Developer Guide
Writing AL code that works is only the first step. A Business Central extension also needs a structure that remains understandable when the project grows, requirements change, integrations are added and multiple developers work on the same solution.
1. What is extension architecture in Business Central?
Extension architecture is the way an AL solution is divided into objects and responsibilities. Business Central provides tables for data, pages for user interaction, codeunits for reusable business logic, reports for output, interfaces for interchangeable implementations, events for extensibility, and permission-related objects for controlled access.
Microsoft's AL documentation describes these objects as core building blocks for developing Business Central applications. A good architecture uses those building blocks deliberately instead of putting all logic into pages or table triggers. Microsoft Learn — Developing Business Central Apps with AL.
2. Start with business capabilities, not just object types
A common beginner approach is to create a table, then place everything related to the feature inside its page. That can work for a small proof of concept, but larger solutions benefit from organizing the design around business capabilities.
Business Requirement
│
▼
Application / Feature
│
┌──────┼────────┐
▼ ▼ ▼
Data Logic Integration
│ │ │
Table Codeunit API / HttpClient
│ │ │
Page Events External system
For example, an “AI Customer Analysis” feature might contain customer context tables, a setup page, an analysis page, a service codeunit, an AI provider interface, an event subscriber and an integration layer. This makes the feature easier to test and replace later.
3. Give each object a clear responsibility
Tables — own the data model
Tables should define fields, keys, relationships and data-related behavior. Avoid turning a table into a large service layer containing unrelated integration and orchestration logic.
Pages — own the user experience
Pages should present and collect information. When a button needs to execute a substantial business process, prefer calling a dedicated codeunit or service method instead of embedding a large procedure directly in the page action.
Codeunits — own reusable business logic
Codeunits are a natural place for processes that may be called from pages, APIs, job queues, event subscribers or other application components. A well-designed codeunit exposes focused procedures rather than becoming a “god codeunit” containing every feature in the application.
Reports — own reporting and document output
Keep report-specific dataset and layout concerns inside report objects. If the report needs complex reusable business calculations, move those calculations into appropriate application services instead of duplicating them across reports.
4. Separate orchestration from implementation
One useful pattern is to have an orchestration codeunit coordinate a process while smaller services perform individual responsibilities.
procedure RunCustomerAnalysis(CustomerNo: Code[20])
var
ContextBuilder: Codeunit "AI Customer Context";
Analyzer: Codeunit "AI Customer Analyzer";
begin
ContextBuilder.Build(CustomerNo);
Analyzer.Analyze(CustomerNo);
end;
The exact implementation will depend on the project, but the design idea is important: the orchestration layer should explain what happens, while specialized components own how each step happens.
5. Use interfaces when implementations may change
Interfaces are useful when the application needs a stable contract but may have multiple implementations. For example, an AI feature could support different providers, or an integration could have different transport implementations.
interface "AI Provider"
{
procedure Analyze(Context: Text): Text;
}
codeunit "Provider A" implements "AI Provider"
{
procedure Analyze(Context: Text): Text
begin
// Provider-specific implementation
end;
}
The interface keeps the calling code focused on the capability instead of the concrete provider. Microsoft documents interfaces as an extensibility mechanism that allows different implementations to satisfy the same contract. Microsoft Learn — Interfaces in AL.
6. Use events to create extension points
Events allow custom functionality to react to application behavior without directly modifying the publisher's implementation. This is especially useful when building an extension on top of standard Business Central functionality.
[EventSubscriber(ObjectType::Codeunit,
Codeunit::"My Sales Service",
'OnAfterProcessOrder',
'', false, false)]
local procedure OnAfterProcessOrder(OrderNo: Code[20])
begin
// Extension-specific follow-up logic
end;
Microsoft describes events as a way to separate custom functionality from application business logic, which can reduce the cost of modifications and upgrades. The EventSubscriber attribute is used on subscriber methods in codeunits. Types of events for extensibility · EventSubscriber attribute.
7. Keep integrations outside core business logic
External integrations should not spread HTTP calls, JSON parsing and authentication details throughout the application. Create a focused integration layer instead.
Business Process
│
▼
Integration Service
│
┌────┴─────┐
▼ ▼
Auth Payload
│ │
└────┬─────┘
▼
HttpClient / API
│
▼
External System
For a Shopify, payment, AI or custom REST integration, the business layer should ideally request an operation such as SendOrder or AnalyzeCustomer. The integration layer should handle endpoint details, headers, JSON serialization, response validation and error mapping.
8. Design security into the architecture
Security should not be added after development. Decide early which users can read or modify the data, which codeunits perform sensitive actions, and which integration credentials are required.
- Use permission sets appropriate to the feature.
- Keep secrets and access tokens out of source code.
- Validate external input before using it in business operations.
- Keep sensitive operations behind controlled application methods.
- Separate read-only analysis from transaction-changing actions where possible.
- Log important integration and processing failures without exposing secrets.
AL provides permission-set objects and other mechanisms for controlling access to application data and functionality. Microsoft Learn — AL development reference.
9. Build for testability
A large procedure that reads data, calls an API, transforms JSON and posts a document in one block is difficult to test. Split the workflow into smaller units with clear inputs and outputs.
Input
↓
Validation
↓
Context / Data preparation
↓
Business calculation
↓
External integration
↓
Response validation
↓
Business action
↓
Result
This structure makes it easier to test validation failures, API failures and business-rule scenarios independently. It also makes troubleshooting easier when a production process fails.
10. Think about performance while designing
Architecture and performance are connected. Avoid unnecessary database reads, repeated calculations and expensive work inside page triggers. When processing large read-only datasets, Business Central supports patterns such as partial records and set-based operations.
Microsoft's developer performance guidance specifically discusses efficient data access, partial records, set-based methods, asynchronous processing and performance testing. Microsoft Learn — Performance articles for developers.
For example, when only a few fields are needed during a read operation, SetLoadFields can limit the fields initially loaded:
Item.SetLoadFields("No.", "Description", "Inventory");
if Item.FindSet() then
repeat
// Read only the fields required by this process.
until Item.Next() = 0;
Partial records can reduce the amount of data loaded, but they require careful handling because accessing fields that were not initially loaded can trigger additional loading. Microsoft Learn — Using partial records.
11. Move non-interactive work to background processing
Long-running or non-urgent work may be better suited to background execution. Business Central supports job queues, scheduled tasks and page background tasks for different asynchronous scenarios.
For example, an integration that synchronizes thousands of records does not necessarily need to block the user interface. A job queue can process recurring work and provide logging and telemetry. Page background tasks can be useful for read-only computations that would otherwise slow down a page. Task Scheduler · Job Queue.
12. A practical project structure
A project does not have to use exactly these filenames, but a predictable structure can make a growing AL solution easier to navigate.
src/
├── Tables/
├── TableExtensions/
├── Pages/
├── PageExtensions/
├── Codeunits/
│ ├── Application/
│ ├── Integration/
│ ├── Services/
│ └── Subscribers/
├── Interfaces/
├── Enums/
├── Reports/
├── ReportExtensions/
├── Queries/
├── Permissions/
└── Tests/
The important part is not the folder names. The important part is that a developer can quickly identify where data, UI, business logic, integrations, events and tests belong.
13. Common architecture mistakes
- God codeunit: one codeunit contains unrelated business processes, integrations and utilities.
- Fat page actions: a page action contains hundreds of lines of business logic.
- Direct modification mindset: custom behavior is tightly coupled to standard implementation instead of using supported extension points.
- Integration leakage: HTTP and JSON details appear throughout business logic.
- No test boundary: every operation depends on live data and external systems.
- Hidden permissions: sensitive operations work only because the developer's own account has broad permissions.
- Performance afterthought: large loops and repeated database access are discovered only after production data grows.
14. Architecture for a real AI + Business Central project
For an AI-enabled Business Central solution, a practical high-level design can look like this:
Business Central UI
│
▼
Application Service
│
┌──────┼─────────┐
▼ ▼ ▼
Data Rules AI Provider
│ │ │
▼ ▼ ▼
BC DB Validation Secure API
│
▼
Human Review
│
▼
Controlled Action
The AI component should not automatically become the owner of business decisions. The application should control what data is supplied, what actions are permitted, how responses are validated and when a human must approve a transaction.
15. Interview-ready answer
Conclusion
Good Business Central architecture is not about creating the maximum number of objects. It is about giving each component a clear responsibility and controlling the dependencies between components.
For an AL developer, the progression is straightforward: first learn the objects, then learn how they interact, then learn how to isolate responsibilities, and finally learn how to design for testing, security, performance and upgrades.