DYNEXAL GUIDE • AL PERFORMANCE & DATABASE

Business Central AL Transactions: COMMIT, Locks & Deadlocks

Transaction handling is one of the most important topics for an experienced Business Central developer. A procedure can produce the correct result in a small test environment and still create blocking, inconsistent intermediate states or deadlocks when many users and background processes execute it at the same time.

Core idea: let Business Central manage the normal transaction boundary automatically, and use explicit transaction control only when the business process genuinely requires multiple write transactions.

1. What is a transaction in Business Central?

A transaction is a unit of database work. During AL execution, when a write operation requires a transaction, the runtime automatically starts one. When execution completes, the transaction is normally ended and the updates are committed.

Microsoft documents that Database.Commit() ends the current write transaction. If code needs multiple write transactions during one execution, an explicit Commit() separates those transaction boundaries.

Microsoft Learn — Database.Commit() Method

2. Automatic transaction behavior

Consider a simple operation:

Customer.Get('10000');
Customer."Credit Limit (LCY)" := 50000;
Customer.Modify();

You normally do not need to call Commit() just to save this change. The AL runtime manages the transaction created by the write operation.

Interview point: when asked about COMMIT, first explain the default transaction behavior. Then explain that explicit COMMIT is used to deliberately end the current write transaction and start a new transaction later in the same execution.

3. What does COMMIT actually do?

Database.Commit() ends the current write transaction. This is important because everything written before the commit belongs to the transaction that is being ended, while subsequent writes can belong to another transaction.

InsertRecordA();

Database.Commit();

InsertRecordB();

This creates two transaction phases. The first phase is committed before the second begins.

4. Why unnecessary COMMIT can be dangerous

A common mistake is adding Commit() whenever a developer wants to “make sure the record is saved.” This can change the atomicity of the process.

Imagine an operation that creates a header, creates lines and finally posts a document. If you commit halfway through and a later step fails, the earlier changes may already be permanent. Without that intermediate commit, the whole operation can remain within one transaction boundary and fail as one unit.

CreateHeader();
CreateLines();

// Avoid an unnecessary COMMIT here
PostDocument();

The correct boundary depends on the business requirement. The question is not “Where can I put COMMIT?” but “Which changes must be permanently committed before the next independent phase starts?”

5. COMMIT and long-running processes

There are cases where a large process intentionally uses smaller transaction units. For example, a background process may process thousands of independent records. Keeping every update in one enormous transaction can increase the amount of work and locks held together.

if Item.FindSet() then
    repeat
        ProcessItem(Item);
        Database.Commit();
    until Item.Next() = 0;

However, this pattern changes failure semantics: records processed before a commit can remain committed even if a later record fails. It should therefore be used only when each unit can safely succeed independently.

Design rule: transaction size is a business decision as much as a performance decision. Smaller transactions can reduce lock duration, but they can also reduce all-or-nothing behavior.

6. Database locks in AL

When AL updates data, the database may take locks so concurrent processes do not modify the same data in conflicting ways. Microsoft notes that locking can become a performance issue when processes wait for other processes to release resources.

The practical goal is to keep the time and scope of locks as small as the business process allows.

Microsoft Learn — Performance articles for developers

7. Record.LockTable()

Record.LockTable() explicitly requests update locking for subsequent reads against the table of the record variable until the transaction is committed. This should be used deliberately, not as a general-purpose performance fix.

Item.LockTable();

if Item.Get('1000') then begin
    Item.Inventory := Item.Inventory + 10;
    Item.Modify();
end;

Microsoft recommends delaying explicit locking as much as practical so that only data actually within the update scope is locked.

Microsoft Learn — Reducing database locking

8. How to reduce lock duration

Microsoft's performance guidance specifically recommends limiting the time locks are held and limiting transaction size where appropriate.

9. The integration trap: database transaction + HTTP call

One of the most important architectural considerations is avoiding long database transactions around external calls.

Begin write transaction
        ↓
Modify Business Central data
        ↓
Call external API  ← network delay
        ↓
Wait for response
        ↓
Modify more data
        ↓
Commit

An external API can be slow, unavailable or rate-limited. Holding database resources while waiting for an external system can increase contention.

A safer architecture often separates preparation, external communication and final database updates. The exact pattern depends on whether the operation requires strict atomicity.

10. What is a deadlock?

A deadlock occurs when two or more transactions block each other because each transaction holds a resource that another transaction needs. SQL Server can resolve a deadlock by terminating one of the transactions and rolling it back.

For example:

Transaction A                  Transaction B
------------                   ------------
Locks Customer                 Locks Sales Header
Needs Sales Header             Needs Customer
       │                              │
       └──────── waiting ─────────────┘
                    ↓
                DEADLOCK

Microsoft provides deadlock monitoring and telemetry to help identify the AL object, method and database resources involved.

Microsoft Learn — Monitoring SQL Database Deadlocks

11. How to design to reduce deadlocks

Use a consistent access order

If two processes need the same tables, accessing them in a consistent logical order can reduce circular waiting.

Keep transactions short

The longer a transaction holds resources, the greater the opportunity for another process to collide with it.

Avoid unnecessary LockTable calls

Explicit locking should correspond to a real concurrency requirement. It should not be added simply because a process occasionally experiences a performance problem.

Do not mix unrelated work in one transaction

Unrelated calculations, external calls and large loops can unnecessarily increase the lifetime of the transaction.

12. Error handling and transactions

Error handling must be designed together with transaction behavior. A developer should understand which changes are still part of the current transaction and which changes have already been committed.

Try methods are another special case. Microsoft documents that database changes made by a try method aren't rolled back. For Business Central on-premises, database write transactions inside try methods are restricted by default and can produce a runtime error unless the server configuration allows them.

Microsoft Learn — Handling errors using try methods

Important: do not assume that wrapping code in a try method gives you automatic database rollback. Transaction behavior and error handling must be considered separately.

13. A practical transaction design pattern

Validate input
      ↓
Read setup / configuration
      ↓
Prepare data
      ↓
Start focused write phase
      ↓
Update related records
      ↓
Finish transaction
      ↓
Run independent next phase

This structure makes transaction boundaries easier to reason about. Validation and read-only preparation can often happen before the critical write section, while the write phase can remain as small and deterministic as practical.

14. Troubleshooting locks and deadlocks

When users report that a page is slow or an operation occasionally fails, do not immediately add COMMIT or LockTable. First determine what is actually happening.

Business Central's troubleshooting guidance includes tools for investigating performance issues, database locks, events, permissions and AL debugging.

Microsoft Learn — Troubleshooting tools and guides overview

15. Interview questions you should be ready for

16. Practical checklist for production AL code

Conclusion

Strong Business Central development requires more than knowing AL syntax. Understanding transactions, COMMIT, locks and deadlocks helps you build extensions that behave predictably under concurrent workloads.

The key is to make transaction boundaries intentional: preserve atomic business operations where required, keep locks short, avoid unnecessary explicit locking, and separate slow external work from critical database updates whenever the architecture permits it.

Sources & references

← Back to Dynexal Insights