In this video, I take a look at how Business Central handles database transactions. Check it out:

In this video, Erik explores how transactions and the Commit() function work in AL for Business Central — and more importantly, why you should almost never use Commit() unless you have a very specific reason. The inspiration came from encountering a Commit() placed inside an event subscriber, which caused significant problems in a production environment.
Understanding Transactions in Business Central
To understand why Commit() can be dangerous, you first need to understand how Business Central handles transactions. Erik starts by demonstrating this directly in the application.
When you’re sitting on the Customer List page — or really any page — and you have the opportunity to interact with the system (click buttons, select actions, etc.), your session is not inside a database transaction. There’s no active transaction at that point.
As soon as you perform an action — say, clicking Delete on a record, or clicking Post Payments — a transaction begins. The system processes your request, and when it’s done, the transaction is committed automatically. You’re then back to having no active transaction.
The key takeaways from this UI-level behavior are:
- Every user interaction that triggers server-side code starts a new transaction.
- When that code finishes successfully, the transaction is implicitly committed.
- If an error occurs, the transaction is automatically rolled back — bringing the data back to the state it was in when the user last had control.
Implicit Transactions: You Don’t Need Begin or Commit
Erik demonstrates this with a simple page action that modifies a customer record:
pageextension 50100 CustomerListExt extends "Customer List"
{
actions
{
addfirst(processing)
{
action(Test)
{
Caption = 'Test';
ApplicationArea = All;
trigger OnAction()
begin
Rec.Name := Format(Random(100));
Rec.Modify();
end;
}
}
}
}
This code clearly writes to the database. But notice two things that are absent:
- There is no “begin transaction” statement.
- There is no
Commit()statement.
Both happen automatically. When the action trigger fires, the platform initializes a transaction. When the trigger completes without error, the platform commits it. You don’t need to — and shouldn’t — write either statement.
What Happens When You Add an Unnecessary Commit?
If you add a Commit() call to the same code:
trigger OnAction()
begin
Rec.Name := Format(Random(100));
Rec.Modify();
Commit();
end;
The result looks the same from the user’s perspective. But under the hood, something different is happening: you now get two transactions. The first transaction covers everything up to the Commit(). After the commit, a new transaction is potentially started for whatever remains. And then there’s still the implicit commit at the end when control returns to the UI.
In this trivial case, nothing goes wrong. But the unnecessary Commit() is setting a dangerous pattern.
Errors Are Rollbacks
In AL, an Error() is the equivalent of a rollback in traditional database terminology. If you raise an error, everything that happened since the beginning of the current transaction — meaning since the last Commit() or since the user action started — gets rolled back.
trigger OnAction()
begin
Rec.Name := Format(Random(100));
Rec.Modify();
Error('Something went wrong');
end;
The modify is undone, and the database returns to its prior state. This is one of the most powerful features of the transaction model in Business Central — and it’s precisely what Commit() can break.
The Real Danger: Commit Inside Event Subscribers
This is the scenario that inspired the video. Consider an event subscriber like this:
codeunit 50100 MySubscribers
{
[EventSubscriber(ObjectType::Table, Database::"Sales Line", OnAfterValidateEvent, 'Some Field', false, false)]
local procedure OnAfterValidateSomeField(var Rec: Record "Sales Line")
begin
// some logic
Commit();
end;
}
This Commit() will now fire in every context where that field validation event is raised — including deep inside posting routines like Codeunit 80 (Sales-Post). During posting, the system processes quantities to ship, quantities to invoice, and many other steps in a single transaction. If your event subscriber commits in the middle of that process, you’ve effectively split the posting into two separate transactions.
When everything goes well, the impact is hard to notice. But when an error occurs in the second half of the posting:
- The first half has already been committed and cannot be rolled back.
- The second half gets rolled back by the error.
- You end up with half-posted documents — entries in some ledgers but not others — creating a data integrity nightmare.
The rule is clear: unless you absolutely know every context in which your event subscriber will fire, and you have a very specific need for it, never put a Commit() inside an event subscriber.
When Is It Appropriate to Use Commit?
Erik notes that it’s actually very rare to use Commit() in AL code, but there are a few legitimate cases:
1. Separating Critical Operations from Non-Critical Ones
A common pattern is in a root-level function where you post a document and then send an email notification. You want the posting to be permanent, and if the email fails, it should not roll back the posting:
// Post the document
PostSalesInvoice(SalesHeader);
Commit(); // Ensure the posting is saved
// Send notification — failure here won't affect the posting
SendEmailNotification(SalesHeader);
2. Opening UI After a Database Operation
As discussed earlier, when you’re in the UI, you cannot be inside a transaction. If your code needs to write to the database and then open a page or confirmation dialog, you need to commit first:
// Save some data
SomeRecord.Modify();
Commit(); // End the transaction
// Now safe to open UI
PAGE.Run(PAGE::"Some Page", SomeRecord);
Source Code Reference
Here’s the page extension Erik was working with during the video, which also includes some experimental code in the OnOpenPage trigger:
namespace DefaultPublisher.ELI5Transactions;
using Microsoft.Sales.Customer;
using Microsoft.Sales.Document;
pageextension 50100 CustomerListExt extends "Customer List"
{
trigger OnOpenPage();
var
i: Integer;
SH: Record "Sales Header";
begin
Clear(SH);
SH."Document Type" := SH."Document Type"::Quote;
SH.Insert(true);
end;
}
Summary
The transaction model in Business Central and AL is designed to handle most scenarios automatically. Here’s what to remember:
- Transactions start and commit implicitly — you don’t need to manage them manually in most cases.
- Errors automatically roll back transactions, which is the equivalent of a database rollback.
- Adding an explicit
Commit()splits your operation into multiple transactions, which can lead to partial data writes if an error occurs after the commit. - Never place
Commit()in event subscribers unless you have an extremely well-understood reason — you don’t control every context in which that subscriber fires. - Legitimate uses of
Commit()include separating critical operations from non-critical follow-up tasks (like emailing) and committing data before opening UI elements.
When in doubt, let the platform handle transactions for you. That’s how AL is designed to work.