In this video, I’m trying to bust an old myth around deleting records in AL. I found myself using a pattern that I have used for the last couple of decades, but why? Instead of exploring this privately, I recorded my little investigation. Check it out:

In this video, Erik explores a question that many AL developers have probably asked themselves at some point: can you safely delete records inside a loop in AL without using a second record variable? If you’ve been developing in NAV/Business Central for years, you’ve likely inherited the pattern of copying a record to a second variable before deleting. Erik puts this to the test on BC27 to find out if that old pattern is still necessary.
The Old Pattern: Two Record Variables
If you’ve been in the NAV/Business Central world for a while, you’ll recognize this pattern immediately. When you need to iterate through a set of records and conditionally delete some of them, the classic approach was:
- Iterate using one record variable
- Copy the record to a second variable
- Delete using the second variable
The idea was to preserve the iteration state of the first variable so that Next() would continue to work correctly. Erik found himself reaching for this pattern again and stopped to ask: “Sure, we did that in the ’90s, but do we still have to do it this way?”
Experiment 1: What Happens After You Delete a Record?
Erik starts with the most basic question: after you call Delete() on a record variable, does the variable still hold its value?
He retrieves customer C00060 using Get(), then calls Delete(). After the delete, he formats the record variable and displays it in an error message. The result: the record variable still holds its values in memory, even though the database record is gone.
The next question: what does Next() do on a deleted record? Erik tested this and found that Next() works just fine — it moves to the next record in the set as expected.
Experiment 2: Deleting Inside a FindSet Loop
This is the real test. Erik sets up a filtered loop using FindSet() and repeat..until, deleting a specific record mid-iteration:
namespace DefaultPublisher.DeleteRecords;
using Microsoft.Sales.Customer;
pageextension 50100 CustomerListExt extends "Customer List"
{
trigger OnOpenPage();
var
c: Record Customer;
C2: Record Customer;
begin
c.setfilter("No.", 'C00060..');
//c.Get('C00060');
if c.findset(false) then
repeat
if C."No." = 'C00070' then
c.Delete();
until c.Next() = 0;
end;
}
The code filters customers from C00060 onwards, loops through them, and deletes only C00070. The result: it works perfectly. The record is deleted and the loop continues to the next record without any issues. No second record variable needed.
Does the ForUpdate Parameter Matter?
Erik also tested whether the ForUpdate parameter on FindSet() makes a difference for deletes. He tried both FindSet(true) and FindSet(false) — and observed no difference in behavior for the delete operation.
Looking at the official documentation, Erik found that the ForUpdate parameter controls whether records are read with an update lock. Setting it to false means you can still modify or delete records, but the updates won’t be performed optimistically. It’s essentially a hint to the AL engine about your intentions and how locking should be handled — it doesn’t prevent you from deleting records.
Key Takeaways
- After calling
Delete(), the record variable still holds its values in memory. The record is gone from the database, but the variable remains usable. Next()works correctly after a delete. The AL runtime can still navigate to the next record in the set.- You do NOT need a second record variable to delete records inside a loop. The old two-variable pattern is unnecessary in modern Business Central (tested on BC27).
- The
ForUpdateparameter onFindSet()doesn’t change whether you can delete. It controls locking behavior, not permissions to modify the record set.
A Note on Compatibility
Erik points out that this was tested on BC27 (Business Central 2025 Wave 2, runtime 16.0). He acknowledges that older versions of Business Central or NAV may have behaved differently, which is likely why the two-variable pattern became so deeply ingrained in the community. If you’re working on an older version, it’s worth verifying this behavior yourself.
Conclusion
Sometimes the patterns we’ve carried for decades no longer apply. In modern Business Central, deleting records inside a FindSet loop works exactly as you’d hope — no extra record variables, no copying, no workarounds. Erik’s advice: always question yourself and the patterns you’ve inherited. Just because “that’s the way it’s always been done” doesn’t mean it’s still the right way. Take a few minutes to test your assumptions — you might end up with cleaner, simpler code.