Not every task in an ASP.NET Core application should execute during an HTTP request. Operations such as sending emails, generating reports, processing files, or synchronizing data can increase response times and negatively impact the user experience if performed synchronously.
Background processing allows these long-running or non-critical tasks to execute independently of incoming requests. ASP.NET Core offers several approaches, each designed for different workloads and scalability requirements.
In this article, we'll compare the most common background processing options and discuss when to use each one in production applications.
Why Use Background Processing?
Imagine an e-commerce application where placing an order triggers several operations:
Save the order
Send a confirmation email
Generate an invoice
Update inventory
Notify the warehouse
If all these tasks execute before returning a response, users experience unnecessary delays.
Instead, the API can immediately acknowledge the order while background workers process the remaining tasks asynchronously.
This improves application responsiveness and allows long-running operations to execute independently.
BackgroundService
BackgroundService is the built-in solution for running long-lived background tasks in ASP.NET Core.
Example:
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine("Running background task...");
await Task.Delay(5000, stoppingToken);
}
}
}
Register the service:
builder.Services.AddHostedService<Worker>();
Best Use Cases
Periodic cleanup tasks
Cache refresh
Monitoring services
Scheduled synchronization
Health checks
It is lightweight and requires no external dependencies.
Hangfire
Hangfire is a popular library for persistent background jobs.
Unlike BackgroundService, Hangfire stores jobs in persistent storage such as SQL Server or Redis. Jobs survive application restarts and provide automatic retry capabilities.
Example:
BackgroundJob.Enqueue<IEmailService>(
service => service.SendWelcomeEmail(userId));
Hangfire also provides a dashboard for monitoring:
Running jobs
Failed jobs
Scheduled jobs
Retries
Best Use Cases
Email processing
Report generation
Scheduled notifications
Long-running business workflows
Quartz.NET
Quartz.NET is a powerful scheduling library for recurring and calendar-based jobs.
Example scenarios include:
Every day at midnight
Every Monday morning
First day of each month
Every five minutes
Quartz.NET supports advanced scheduling expressions that are difficult to implement using simple timers.
Best Use Cases
Scheduled reports
Database maintenance
Data synchronization
Batch processing
Azure Functions
Azure Functions provide serverless background execution based on events.
Functions can be triggered by:
HTTP requests
Timers
Azure Storage
Azure Service Bus
Event Grid
Blob uploads
Example timer trigger:
[Function("CleanupJob")]
public void Run(
[TimerTrigger("0 */5 * * * *")] TimerInfo timer)
{
Console.WriteLine("Cleanup executed.");
}
Azure automatically scales the execution based on workload.
Best Use Cases
Cloud-native applications
Event-driven systems
Scheduled cloud jobs
Lightweight automation
Azure Service Bus
For enterprise applications, asynchronous messaging is often the preferred approach.
Instead of executing work immediately, an API publishes a message.
Client
│
ASP.NET Core API
│
Azure Service Bus
│
Background Worker
The worker processes messages independently.
Benefits include:
Loose coupling
Improved reliability
Automatic retries
Load leveling
Better scalability
This approach is widely used in microservices architectures.
Join the conversation! Your thoughts help the community grow.