Skip to content
-
Subscribe to our newsletter & never miss our best posts. Subscribe Now!
stackengineeringhub_logo stackengineeringhub_logo Stack Engineering Hub
stackengineeringhub_logo stackengineeringhub_logo Stack Engineering Hub
  • Home
  • Blog
  • ASP.NET Core
  • ASP.NET
  • ADO.NET
  • LINQ
  • Sql Server
  • SignalR
  • Web Services
  • Visual Studio
  • Web Development
  • Windows Services
  • Home
  • Blog
  • ASP.NET Core
  • ASP.NET
  • ADO.NET
  • LINQ
  • Sql Server
  • SignalR
  • Web Services
  • Visual Studio
  • Web Development
  • Windows Services
Close

Search

Trending Now:
ASP.NET sql server wcf jquery asp.net core
Subscribe
stackengineeringhub_logo stackengineeringhub_logo Stack Engineering Hub
stackengineeringhub_logo stackengineeringhub_logo Stack Engineering Hub
  • Home
  • Blog
  • ASP.NET Core
  • ASP.NET
  • ADO.NET
  • LINQ
  • Sql Server
  • SignalR
  • Web Services
  • Visual Studio
  • Web Development
  • Windows Services
  • Home
  • Blog
  • ASP.NET Core
  • ASP.NET
  • ADO.NET
  • LINQ
  • Sql Server
  • SignalR
  • Web Services
  • Visual Studio
  • Web Development
  • Windows Services
Close

Search

Trending Now:
ASP.NET sql server wcf jquery asp.net core
Subscribe
Home/ASP.NET/Background Services in .NET: Hosted Services, Workers, Scheduling & Best Practices
background-services-in-dotnet-2
ASP.NET

Background Services in .NET: Hosted Services, Workers, Scheduling & Best Practices

By SEHUser
September 12, 2026 10 Min Read
1

Background Services in .NET: Hosted Services, Workers, Scheduling & Best Practices

Background Services in .NET are an important part of modern application development when a task needs to run independently of an HTTP request. Instead of making a user wait while an application sends emails, processes files, generates reports, synchronizes data, or performs database maintenance, these operations can execute in the background. ASP.NET Core provides built-in support for background processing through IHostedService and BackgroundService, while the Worker Service template makes it possible to build dedicated long-running processes. In this guide, we will understand how Background Services in .NET work, how to implement them with practical C# examples, how Dependency Injection works inside workers, how to handle scoped services, scheduling, cancellation, errors, logging, and the production practices developers should follow when building enterprise applications.

What Are Background Services in .NET?

Background Services in .NET are long-running or recurring processes that execute independently from normal HTTP request processing. They are managed by the .NET Generic Host and can start when an application starts and stop gracefully when the application shuts down. A background service is useful when work does not need to be completed during the current web request.

For example, an API may receive an order and immediately return a response while a background service processes invoice generation, email notifications, inventory synchronization, or audit operations separately. This design prevents slow operations from unnecessarily increasing API response time.

Common Background Processing Scenarios

  • Email and notification processing
  • Scheduled database cleanup
  • Report generation
  • File and document processing
  • Queue and message processing
  • Data synchronization
  • Cache refresh operations
  • Third-party API polling
  • Log and audit processing
  • Periodic maintenance tasks

How Background Services Work

Background Services are managed by the .NET Generic Host. When an ASP.NET Core application starts, the host initializes configuration, Dependency Injection, logging, and registered hosted services. The hosted service then begins its execution independently of incoming HTTP requests.

When the application receives a shutdown signal, the host provides a cancellation mechanism to the background service. A well-designed worker observes this cancellation signal and stops gracefully instead of continuing indefinitely.

Typical Lifecycle

  1. The application starts.
  2. The .NET host initializes registered services.
  3. The hosted service starts execution.
  4. The background operation performs its work.
  5. The service continues until cancellation or application shutdown.
  6. The cancellation token signals the service to stop.
  7. The service completes active work and exits.

This lifecycle is especially important in production applications because background processes must not simply disappear when the application is restarted, deployed, or stopped.

IHostedService in .NET

IHostedService is the fundamental interface used by .NET for hosted background processes. It exposes two primary methods: StartAsync() and StopAsync(). This approach provides direct control over the startup and shutdown lifecycle of a service.

public class EmailHostedService : IHostedService
{
    public Task StartAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("Email service started.");
        return Task.CompletedTask;
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        Console.WriteLine("Email service stopped.");
        return Task.CompletedTask;
    }
}

Implementing IHostedService directly can be useful when you need precise control over lifecycle behavior. However, for most continuously running background workloads, the BackgroundService base class provides a cleaner implementation.

What Is BackgroundService?

BackgroundService is an abstract base class provided by .NET that implements IHostedService. Instead of manually implementing both startup and shutdown methods, developers normally override ExecuteAsync() and place the long-running logic there.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Background worker is running.");

            await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
        }
    }
}

The stoppingToken is important because it allows the worker to detect when the application is shutting down. Using the token with asynchronous operations such as Task.Delay() makes the service responsive to cancellation.

Registering a Background Service

After creating the worker class, register it with the application’s Dependency Injection container using AddHostedService(). Once registered, the .NET host manages its lifecycle automatically.

builder.Services.AddHostedService<Worker>();

You do not need to create the worker manually with the new keyword. The Dependency Injection container creates the service and the host starts it when the application starts.

If you are not familiar with Dependency Injection and service lifetimes, see our Dependency Injection in ASP.NET Core guide. Understanding service lifetimes becomes particularly important when Background Services use database or repository components.

Using Dependency Injection in Background Services

Background Services can use Dependency Injection just like controllers and other application components. Logging services, configuration, repositories, HTTP clients, business services, and other dependencies can be provided through constructor injection.

public class ReportWorker : BackgroundService
{
    private readonly ILogger<ReportWorker> _logger;
    private readonly IReportService _reportService;

    public ReportWorker(
        ILogger<ReportWorker> logger,
        IReportService reportService)
    {
        _logger = logger;
        _reportService = reportService;
    }

    protected override async Task ExecuteAsync(
        CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await _reportService.GenerateReports();

            await Task.Delay(
                TimeSpan.FromHours(1),
                stoppingToken);
        }
    }
}

This approach keeps the worker focused on orchestration while the actual business rules remain inside separate services. That separation makes the application easier to test, maintain, and extend.

Using Scoped Services in BackgroundService

One of the most important concepts when working with Background Services is service lifetime. A hosted service is effectively managed as a singleton, while components such as Entity Framework Core DbContext are commonly registered with a scoped lifetime.

Injecting a scoped service directly into a singleton background service can create a lifetime mismatch. Instead, create a new Dependency Injection scope for each unit of work.

public class DataWorker : BackgroundService
{
    private readonly IServiceScopeFactory _scopeFactory;

    public DataWorker(IServiceScopeFactory scopeFactory)
    {
        _scopeFactory = scopeFactory;
    }

    protected override async Task ExecuteAsync(
        CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            using var scope = _scopeFactory.CreateScope();

            var repository = scope.ServiceProvider
                .GetRequiredService<IEmployeeRepository>();

            await repository.ProcessPendingRecords();

            await Task.Delay(
                TimeSpan.FromMinutes(5),
                stoppingToken);
        }
    }
}

Creating a scope ensures that scoped dependencies are created and disposed correctly. This is particularly useful for database operations because a new database context can be created for each processing cycle.

Scheduling Tasks with Background Services

A simple Background Service can perform scheduled work by using Task.Delay(). For example, an application may need to execute a cleanup process every 30 minutes.

protected override async Task ExecuteAsync(
    CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        await CleanupTemporaryFiles();

        await Task.Delay(
            TimeSpan.FromMinutes(30),
            stoppingToken);
    }
}

This approach is suitable for simple recurring operations. However, if the application requires complex schedules such as cron expressions, multiple job types, persistent job storage, or distributed scheduling, a dedicated job-processing solution may be more appropriate.

Background Services and ASP.NET Core Applications

Background processing is separate from the normal HTTP request pipeline. Controllers receive requests, execute application logic, and return responses, while hosted services can continue processing independently. Understanding the ASP.NET Core request lifecycle helps developers decide which operations belong inside a request and which should be moved to background processing.

For a deeper understanding of how ASP.NET Core processes requests, see our ASP.NET Core Lifecycle Explained article.

Background Services with Database Operations

Database processing is one of the most common uses of Background Services. For example, an application can periodically identify pending records, process them, and update their status. When using Entity Framework Core, create an appropriate scope and avoid keeping a database context alive for the entire lifetime of the worker.

If your background worker communicates with SQL Server, it is useful to understand how ASP.NET Core applications establish database connectivity and configure Entity Framework Core. Our Connecting SQL with ASP.NET Core guide provides a practical foundation for this scenario.

Error Handling in Background Services

A background worker should not fail silently. External APIs can become unavailable, databases can temporarily reject connections, and individual records can contain invalid data. Always handle expected exceptions and log enough information to diagnose the problem.

try
{
    await ProcessPendingOrders();
}
catch (Exception ex)
{
    _logger.LogError(
        ex,
        "Error occurred while processing pending orders.");
}

For transient failures, retry strategies can be introduced with controlled delays and maximum retry attempts. Avoid retrying indefinitely because a continuously failing external dependency can cause excessive resource consumption.

Cancellation and Graceful Shutdown

Every long-running Background Service should respect its cancellation token. The host uses cancellation to notify the worker that the application is stopping. Ignoring the token can delay shutdown and may leave operations incomplete.

while (!stoppingToken.IsCancellationRequested)
{
    await ProcessWork(stoppingToken);

    await Task.Delay(
        TimeSpan.FromSeconds(10),
        stoppingToken);
}

Pass the cancellation token to database, HTTP, file, and other asynchronous operations whenever the API supports it. This allows ongoing work to stop more efficiently during deployment or application shutdown.

Logging and Monitoring

Logging is essential for background processing because there is no user sitting in front of a browser waiting for an error message. Log meaningful information such as job start time, completion time, processing count, failures, retry attempts, and execution duration.

Avoid excessive logging inside high-frequency loops. Instead, use structured logs that provide useful operational information. In production systems, combine application logs with monitoring and alerting so that failed background processes can be detected quickly.

Worker Service Template

A Worker Service is a .NET project template specifically designed for long-running background applications. It is useful when the application does not need to expose HTTP endpoints and its primary responsibility is background processing.

dotnet new worker -n BackgroundWorkerDemo

Worker Services are useful for queue consumers, scheduled processing, Windows Services, Linux services, containerized workers, and other applications that need to run continuously without a web interface.

BackgroundService vs IHostedService

Feature IHostedService BackgroundService
Implementation Manual lifecycle implementation Provides a ready-made base class
Lifecycle Control More direct control Built into the base class
Long-Running Work Supported Excellent choice
Code Complexity Higher Lower
Common Usage Custom lifecycle scenarios Workers and recurring processing

Performance Best Practices

Background processing should be designed carefully because a worker can consume resources continuously. Prefer asynchronous APIs and avoid blocking calls such as Thread.Sleep(). Process database records in reasonable batches and avoid loading large datasets into memory unnecessarily.

  • Use async and await for I/O operations.
  • Always respect CancellationToken.
  • Avoid unnecessary infinite loops without delays.
  • Use Dependency Injection instead of manually creating dependencies.
  • Create scopes for scoped services.
  • Process large datasets in batches.
  • Reuse HTTP clients through IHttpClientFactory.
  • Log failures and important processing metrics.
  • Use retry policies for transient failures.
  • Keep business logic outside the worker class.

Common Mistakes to Avoid

Several problems appear repeatedly in production Background Services. Injecting a scoped database context directly into a long-lived worker is a common mistake. Another problem is ignoring cancellation, which can make deployments and application shutdown slower than expected.

  • Injecting scoped services directly into a singleton worker.
  • Ignoring cancellation tokens.
  • Using blocking operations inside asynchronous code.
  • Allowing an unhandled exception to stop important processing.
  • Running CPU-heavy operations without considering resource usage.
  • Creating excessive Dependency Injection scopes.
  • Logging every iteration of a high-frequency loop.
  • Using a Background Service when a durable job or message queue is more appropriate.

When Should You Use Background Services?

Use Background Services when an operation can be performed independently of the user’s current request. Typical examples include email processing, report generation, scheduled cleanup, data synchronization, file processing, queue consumption, cache refreshes, and integration with external systems.

For simple application-level background processing, BackgroundService is often an excellent choice. For mission-critical workloads requiring guaranteed delivery, persistence, distributed execution, or advanced scheduling, consider a dedicated queue or job-processing architecture.

ASP.NET Core Web API and Background Processing

A common enterprise architecture is to expose an ASP.NET Core Web API for receiving requests while using a Background Service to process work asynchronously. For example, an API can accept a large file upload, store the file and create a processing record, and then return a response immediately. The background worker can process the file without keeping the HTTP request open.

This pattern can significantly improve perceived API performance because users do not have to wait for lengthy operations. If you are building APIs with ASP.NET Core, our ASP.NET Core Web API guide provides a useful starting point.

Production Considerations

A production Background Service should be treated as an operational component rather than simply an infinite loop. Consider what happens when the application restarts, the database becomes unavailable, two application instances run simultaneously, or a worker crashes while processing a record.

For simple workloads, an in-process Background Service may be sufficient. For distributed enterprise systems, durable queues, scheduled job platforms, or separate worker applications can provide stronger reliability and scalability. The architecture should be selected according to the importance and volume of the workload.

Official Documentation

For the latest implementation details, lifecycle behavior, and supported APIs, developers should refer to the official Microsoft Learn documentation for hosted services in ASP.NET Core.

Conclusion

Background Services in .NET provide a clean way to execute long-running, scheduled, and asynchronous workloads without keeping users waiting for an HTTP request to finish. The built-in IHostedService interface provides lifecycle control, while BackgroundService simplifies the implementation of continuous background processing. With Dependency Injection, scoped service management, cancellation tokens, structured logging, exception handling, and appropriate retry strategies, developers can build reliable background processing components for enterprise applications.

For most modern ASP.NET Core applications, start with BackgroundService when the workload is simple and application-level. As requirements become more complex, evaluate queues, dedicated Worker Services, scheduled job systems, or distributed processing architectures. The key is to keep background work isolated from HTTP request processing and design it with reliability, observability, cancellation, and scalability in mind.

Frequently Asked Questions

What is a Background Service in .NET?

A Background Service in .NET is a process that runs independently of normal HTTP requests. It is commonly used for scheduled jobs, email processing, file processing, database maintenance, queue consumption, and data synchronization.

What is the difference between IHostedService and BackgroundService?

IHostedService is the base interface that exposes startup and shutdown methods. BackgroundService is an abstract implementation that simplifies long-running workloads by allowing developers to override ExecuteAsync().

Can BackgroundService use Dependency Injection?

Yes. Background Services support Dependency Injection. Services such as loggers, repositories, configuration providers, HTTP clients, and business services can be injected. Scoped dependencies should normally be resolved inside a newly created service scope.

Can Background Services run scheduled tasks?

Yes. A simple worker can use Task.Delay() and a cancellation token to perform work at regular intervals. More complex scheduling requirements may be better handled by a dedicated scheduling or job-processing solution.

Should every background task use BackgroundService?

No. BackgroundService is suitable for many application-level workloads, but durable queues, distributed jobs, complex scheduling, and guaranteed processing may require specialized infrastructure. Select the solution according to workload reliability, scalability, and persistence requirements.

🚀 Stay Updated with Latest Tech Insights

Get practical coding tips, tutorials, and developer insights directly in your inbox.

We don’t spam! Read our privacy policy for more info.

Check your inbox or spam folder to confirm your subscription.

🚀 Stay Updated with Latest Tech Insights

Get practical coding tips, tutorials, and developer insights directly in your inbox.

We don’t spam! Read our privacy policy for more info.

Check your inbox or spam folder to confirm your subscription.

Tags:

.NETASP.NET CoreAsynchronous ProgrammingBackground ServicesBackgroundServiceC#IHostedServiceWorker Service
Author

SEHUser

Follow Me
Other Articles
global-exception-handling-in-net
Previous

Global Exception Handling in .NET: Complete Guide with Middleware and Best Practices

clean-architecture-in-dotnet
Next

Clean Architecture in .NET: A Practical Guide for Developers

One Comment
  1. Async and Await in .NET: Practical C# Guide says:
    September 16, 2026 at 3:56 pm

    […] host shuts down, the worker should observe the supplied cancellation token and stop cleanly. Our Background Services in .NET guide covers hosted services, cancellation, scoped dependencies, scheduling, and production […]

    Reply

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

About This Site

Stack Engineering Hub focuses on providing high-quality tutorials, guides, and insights on technologies such as ASP.NET, C#, SQL Server, Web APIs, and system design.

Search

Latest Tech Articles

  • .NET Performance Optimization Guide: Practical Techniques for Faster Applications
  • Async and Await in .NET: Practical C# Guide
  • Design Patterns in C#: Practical Guide for Developers
  • Unit of Work Pattern in C#: Complete Guide with Real-World Example
  • Repository Pattern in .NET: Complete Developer Guide

Join Us

🚀 Stay Updated with Latest Tech Insights

Get practical coding tips, tutorials, and developer insights directly in your inbox.

We don’t spam! Read our privacy policy for more info.

Check your inbox or spam folder to confirm your subscription.

Quick Links

  • About Us
  • Contact Us
  • Privacy Policy
  • Terms & Conditions
  • Disclaimer

Recent Posts

  • .NET Performance Optimization Guide: Practical Techniques for Faster Applications
  • Async and Await in .NET: Practical C# Guide
  • Design Patterns in C#: Practical Guide for Developers
  • Unit of Work Pattern in C#: Complete Guide with Real-World Example
  • Repository Pattern in .NET: Complete Developer Guide

Archives

  • September 2026 (10)
  • July 2026 (19)
  • June 2026 (18)
  • May 2026 (24)
  • April 2026 (3)
  • March 2026 (3)

Find Us

Address
Bhopal,
Madhya Pradesh, India

Hours
Monday–Friday: 10:00AM–5:00PM
Saturday & Sunday: 11:00AM–3:00PM

Copyright 2026 — Stack Engineering Hub. All Rights Reserved. Developed by Code Scanner IT Solutions