Interactive AL directly in Visual Studio Code

Being able to type and run AL commands directly in VS Code has been a dream of mine for quite a while. Finally, I got a prototype running, check it out:

https://youtu.be/5Akuv7T4TUk

In this video, Erik demonstrates an exciting evolution of his Interactive AL project: running an interactive AL terminal directly inside Visual Studio Code. Building on his previous work where the interactive AL experience lived inside Business Central, Erik has now bridged the gap so developers can type AL commands in a VS Code terminal and interact with Business Central in real time — reading records, modifying data, committing transactions, and more.

What Is Interactive AL?

A few weeks prior, Erik created an AL compiler/interpreter that replicated the experience of an old Commodore 64-style interactive environment — but for Business Central’s AL language. In that earlier iteration, the interactive terminal ran inside Business Central itself. Erik admits he made “some lame excuses” for why it had to stay there. But now, those excuses are gone: Interactive AL runs directly in Visual Studio Code.

Demo: The AL Terminal in VS Code

With a standard AL project open in VS Code, Erik shows a new “AL Terminal” panel in the terminal section. Here’s a taste of what the interactive session looks like:

  • Get today’s date: Simply type an expression and get the result — pure AL, evaluated live.
  • Create variables on the fly: Declare a variable c as a Record of Customer.
  • List variables: Type list to see all currently declared variables in the session.
  • Navigate records: Call c.FindFirst, c.Next, c.FindLast to walk through the Customer table.
  • Read and write fields: Check c.Name, then assign it: c.Name := 'YouTube Demo'.
  • Modify and commit: Call c.Modify to update the record (opening a database transaction), then Commit to persist the change.
  • Multiple variable types: Declare integers, decimals, and more — all persisted within the session.

This is a fully interactive AL experience right inside VS Code.

How It Works: Architecture Overview

The system consists of several components working together:

1. The VS Code Client (C# .NET Component)

Running in the VS Code terminal is a small C# application. Its job is simple: read input from the keyboard and send it as a web service request to Business Central via an endpoint called al-console-execute. This is an unbound codeunit exposed through OData.

2. The Execute Function (Web Service Layer)

When the client sends a command, it hits an Execute function in Business Central. On the very first call, this function initializes a session by calling StartNewWorker, which creates a background session in Business Central. A unique worker ID (GUID) is assigned so the web service and the background session can identify each other.

3. The Worker Session (Background Codeunit)

The worker is a codeunit with approximately 107 lines of code. Its OnRun trigger contains a main loop:

while true do begin
    // Check for new tasks
    // Execute AL commands
    // Write results
    Sleep(1);
end;

The Sleep(1) call ensures the worker doesn’t consume all server resources, giving other threads a chance to execute. The worker continuously polls a “Thread Task” table for new commands to execute. When it finds one, it compiles and runs the AL code (using Erik’s AL compiler/interpreter), then writes the result to a “Result” table.

4. The Communication Tables

Two simple tables facilitate communication between the web service and the worker session:

  • Thread Task table: Contains a worker ID, timestamp, task ID, and the AL code to execute. The web service writes commands here.
  • Result table: Has the same primary key structure, plus fields for the result text, a “completed” flag, and error information. The worker writes results here.

5. Session Timeout

To prevent background sessions from running forever, Erik implemented a five-minute timeout. If no commands are received within that window, the worker session terminates. The next command simply creates a new session — though any variables from the old session are lost.

The Key Trick: Read Uncommitted

The most critical technical insight in this architecture is the use of read uncommitted queries. Normally, AL reads only committed data. But in an interactive session, when a user modifies a record and hasn’t yet called Commit, there’s uncommitted data sitting in the worker’s transaction.

Both the worker (reading new tasks) and the web service (reading results) use queries with ReadUncommitted set. This means:

  • The worker can see tasks written by the web service immediately, without waiting for a commit.
  • The web service can see results written by the worker, even if those results exist within an uncommitted (or eventually rolled-back) transaction.

This enables real-time, bi-directional communication between sessions using the database as the intermediary — the only inter-session communication mechanism available in the cloud.

The Bulk Insert Gotcha

Erik shared a debugging story that had him stumped for weeks. Sometimes the read uncommitted approach worked; sometimes it didn’t. The revelation came to him while playing a concert: bulk inserts.

Business Central optimizes unprotected inserts by buffering them into bulk SQL insert statements rather than executing them individually. The problem is that bulk-inserted records aren’t visible to other sessions reading uncommitted data until the bulk batch is flushed.

The fix? Wrap the insert in a conditional:

if Result.Insert() then;  // Prevents bulk insert optimization

As documented by Microsoft, if the insert is encapsulated in a conditional that checks the return value, bulk insert optimization is not triggered. This ensures each insert is written to SQL immediately and becomes visible to the other session’s uncommitted reads right away.

Inter-Session Communication: Broader Applications

While Erik uses this read-uncommitted-via-database pattern specifically for the interactive AL terminal, he notes it has much broader applications. Any scenario where you need two Business Central sessions to communicate can leverage this approach:

  • One session initializes and starts a background worker.
  • Communication happens through database tables with read uncommitted queries.
  • Results are available even if the worker’s transaction eventually rolls back.

Erik mentions that on-premises deployments have an alternative: using .NET interop and static, thread-safe objects for inter-session communication. But in the cloud, the database is the only viable channel. He expressed hope that Microsoft might one day provide proper inter-thread communication mechanisms like semaphores and signals.

The AL Project Context

The demo runs within a standard AL project. Here’s the sample HelloWorld.al file visible in the project:

pageextension 50100 CustomerListExt extends "Customer List"
{
    trigger OnOpenPage();
    begin
        Message(GenerateAwesomeMessage(TODAY()));
    end;

    local procedure GenerateAwesomeMessage(T: Date): Text
    var
        d: Integer;
        m: Integer;
        y: Integer;
    begin
        d := 3;
        m := 4;
        y := 5;
        newProcedure(d, m);
    end;

    local procedure newProcedure(var d: Integer; var m: Integer): Text
    begin
        for d := m to m * 5 do begin
            for m := d to d * 5 do begin
                if d = m then
                    exit('Test!!!');
            end;
        end;
    end;
}

While this file isn’t directly related to the interactive terminal functionality, it demonstrates the standard AL development context in which the terminal operates.

Performance Considerations

Erik is upfront about performance: the AL compiler/interpreter is “dead slow” because it’s AL interpreting AL — hundreds of lines of code execute to run a single line of input. However, for interactive exploration and debugging scenarios, the flexibility far outweighs the speed limitations. The system is reliable and responsive enough for practical use.

What’s Next

Erik outlined his vision for the next steps: supporting snippet files (stored in a .snippet folder within your AL project) that can be loaded and executed in the interactive terminal. This would allow developers to keep small, reusable pieces of AL code alongside their project and run them interactively against Business Central.

Summary

This video showcases a compelling proof of concept: an interactive AL REPL (Read-Eval-Print Loop) running inside Visual Studio Code that communicates with a live Business Central environment. The architecture cleverly uses background sessions, database tables, and read uncommitted queries to create persistent, stateful inter-session communication. The bulk insert gotcha and its workaround provide a valuable lesson for anyone working with real-time data visibility between Business Central sessions. While still a proof of concept with hardcoded elements, the system demonstrates that interactive AL development directly from VS Code is not just possible — it works.