Course contentsShow
← C#
Lesson 1527 of 1,90814. Background Work and MessagingFree lesson

Configuring Multi-Instance Scaling

Understand how singleton background services behave when running in multiple load-balanced nodes.

In this lesson, you will learn why running a BackgroundService as a singleton in a multi-instance, load-balanced environment leads to duplicate processing conflicts.

When you register a BackgroundService in your .NET application, it starts automatically when the host starts. In a single-server setup, this works perfectly. However, in modern cloud architectures, we scale horizontally by spinning up multiple instances (nodes) of our service behind a load balancer to handle increased traffic.

The Singleton Collision

The term "singleton" in the context of IHostedService refers to the service living for the lifetime of the host process. If you have three instances of your web application running in Kubernetes or Azure App Service, you have three separate processes. Each of those processes will initialize its own instance of your BackgroundService.

If your background task is performing an operation that should only happen once—such as polling a third-party API for updates or clearing a database cache—you are now executing that logic three times simultaneously. This leads to race conditions, redundant API costs, and data inconsistencies.

Visualizing the Conflict

Imagine a background task designed to send a daily report email at midnight. With three instances running, your users will receive that email three times:

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    // This loop runs independently on EVERY instance of the application.
    while (!stoppingToken.IsCancellationRequested)
    {
        await DoWork(); // Triple execution in a 3-node cluster!
        await Task.Delay(TimeSpan.FromHours(24), stoppingToken);
    }
}

Addressing the Scaling Challenge

To prevent this, you cannot rely on the internal process clock or simple loops when scaling out. Instead, you must decouple the scheduling of the work from the execution of the work. Common strategies include using a distributed lock (like Redlock) to ensure only one instance executes the task, or offloading the task definition to a centralized message queue where messages are consumed by one of the available instances.

Key Takeaway: In a multi-instance environment, a BackgroundService acts as a local singleton per node; if you need a global singleton, you must implement external orchestration to prevent duplicate work across your distributed fleet.