← Back to blog

Azure Storage Queues in Business Central

What are Azure Storage Queues?

Azure Storage Queues are a simple HTTP-based message storage service provided by Microsoft Azure. They allow different systems and services to communicate asynchronously by placing messages into a queue and reading them out later. Each message can be up to 64 KB in size and queues can contain millions of messages, making them well-suited to high-throughput scenarios.

Why are they useful with Business Central?

Azure Storage Queues are particularly valuable when you need to handle high-volume data flows into Business Central — for example, readings from shop floor machines, IoT sensors, or any external system that produces bursts of events faster than BC can process them in real time. Instead of hitting BC's API directly under load, external systems push messages to the queue and BC polls and processes them at its own pace, preventing timeouts and throttling.

GitHub repository

A full proof-of-concept implementation is available on GitHub: nocubicles/AzureStorageQueues. The repository contains the complete AL extension you can clone, adapt, and deploy to your own Business Central environment.

AL code example

The core logic lives in a single codeunit. ProcessMessagesFromQueue is called recursively so it keeps polling until the queue is drained. Process fetches the current batch of messages, inserts them into a staging table, and then deletes them from the queue to acknowledge receipt. GenerateMessagesToQueue is a helper used for testing — it pushes sample messages into the queue so you have something to consume.

codeunit 50101 "Manage Queues"
{
    procedure ProcessMessagesFromQueue()
    var
        HasMessages: Boolean;
    begin
        HasMessages := Process();
        if HasMessages then
            ProcessMessagesFromQueue();
    end;

    local procedure Process(): Boolean
    var
        AzureQueueMgt: Codeunit "Azure Queue Management";
        QueueMessage: Record "Queue Message";
        MessageList: List of [Text];
        MessageText: Text;
        MessageId: Text;
        PopReceipt: Text;
    begin
        AzureQueueMgt.GetMessages(MessageList);

        if MessageList.Count() = 0 then
            exit(false);

        foreach MessageText in MessageList do begin
            QueueMessage.Init();
            QueueMessage."Entry No." := 0;
            QueueMessage."Message Text" := CopyStr(MessageText, 1, MaxStrLen(QueueMessage."Message Text"));
            QueueMessage."Received At" := CurrentDateTime();
            QueueMessage.Insert(true);

            AzureQueueMgt.DeleteMessage(MessageId, PopReceipt);
        end;

        exit(true);
    end;

    procedure GenerateMessagesToQueue()
    var
        AzureQueueMgt: Codeunit "Azure Queue Management";
        i: Integer;
    begin
        for i := 1 to 10 do
            AzureQueueMgt.SendMessage('Test message ' + Format(i));
    end;
}

How it works

This is a proof-of-concept that demonstrates the polling pattern. ProcessMessagesFromQueue calls itself recursively — each call invokes Process, which fetches a batch from Azure, writes the messages to a BC table, and deletes them from the queue. When Process returns false (empty queue), recursion stops. In production you would typically run this from a Job Queue entry on a scheduled interval rather than as an unbounded recursion, and you would add error handling and retry logic around the delete step to avoid losing messages on failure.