π Introduction
Sending emails, processing files, creating reports, and syncing data are just a few of the background tasks that are frequently required in contemporary apps. Synchronous execution of these processes can cause your application to lag and negatively impact user experience.
Hangfire can help in this situation.
An open-source framework called Hangfire is used in .NET applications to manage background tasks. It enables you to persist tasks, run them consistently in the background, and monitor them through a dashboard.
π― Why Use Hangfire?
β
Run background jobs without blocking the main thread
β
Persistent jobs (stored in database)
β
Automatic retries
β
Built-in dashboard UI
β
Supports delayed, recurring, and fire-and-forget jobs
β
Works with ASP.NET Core / .NET 9
π§± Prerequisites
Before starting, make sure you have:
π¦ Step 1: Install Required Packages
Run the following commands:
dotnet add package Hangfire
dotnet add package Hangfire.AspNetCore
dotnet add package Hangfire.SqlServer
βοΈ Step 2: Configure Hangfire in Program.cs
In .NET 9 (minimal hosting model), everything is configured inside Program.cs.
using Hangfire;
using Hangfire.SqlServer;
var builder = WebApplication.CreateBuilder(args);
// Add Hangfire services
builder.Services.AddHangfire(config =>
config.UseSqlServerStorage(builder.Configuration.GetConnectionString("DefaultConnection")));
builder.Services.AddHangfireServer();
var app = builder.Build();
π₯οΈ Step 3: Enable Hangfire Dashboard
Add this middleware:
app.UseHangfireDashboard("/hangfire");
Now run your application and open:
π https://localhost:xxxx/hangfire
Youβll see the Hangfire dashboard.
![hangfire dashboard-01]()
ποΈ Step 4: Configure Database
Add the connection string in appsettings.json:
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=HangfireDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},
When you run the app, Hangfire automatically creates the required tables.
π§βπ» Step 5: Create Background Jobs
1. Fire-and-Forget Job
Runs immediately in the background.
BackgroundJob.Enqueue(() => Console.WriteLine("Hello from Hangfire!"));
2. Delayed Job
Runs after a delay.
BackgroundJob.Schedule(() => Console.WriteLine("Delayed job"), TimeSpan.FromMinutes(5));
3. Recurring Job
Runs repeatedly (like CRON jobs).
RecurringJob.AddOrUpdate(
"my-recurring-job",
() => Console.WriteLine("Recurring job running"),
Cron.Minutely);
4. Continuation Job
Runs after another job finishes.
var jobId = BackgroundJob.Enqueue(() => Console.WriteLine("First job"));
BackgroundJob.ContinueJobWith(jobId, () => Console.WriteLine("Second job"));
π§© Step 6: Using Hangfire with Services (Best Practice)
Instead of calling methods directly, use dependency injection.
Create a service:
public class EmailService
{
public void SendEmail(string to)
{
Console.WriteLine($"Email sent to {to}");
}
}
Register service:
builder.Services.AddScoped<EmailService>();
Use in Hangfire:
BackgroundJob.Enqueue<EmailService>(x => x.SendEmail("[email protected]"));
π Step 7: Secure Hangfire Dashboard (Important)
By default, the dashboard is public. Secure it:
app.UseHangfireDashboard("/hangfire", new DashboardOptions
{
Authorization = new[] { new HangfireAuthorizationFilter() }
});
Create custom authorization:
using Hangfire.Dashboard;
public class HangfireAuthorizationFilter : IDashboardAuthorizationFilter
{
public bool Authorize(DashboardContext context)
{
return true; // Replace with real auth logic
}
}
β‘ Step 8: Handling Failures & Retries
Hangfire automatically retries failed jobs.
You can customize:
[AutomaticRetry(Attempts = 3)]
public void ProcessJob()
{
throw new Exception("Error");
}
π Step 9: Monitoring Jobs
Hangfire dashboard provides:
π§ Best Practices
β
Use Interfaces for Jobs
public interface IEmailService
{
void SendEmail(string to);
}
β
Keep Jobs Small & Focused
Avoid long-running monolithic tasks.
β
Use Queues for Scaling
builder.Services.AddHangfire(config =>
config.UseSqlServerStorage(connectionString));
builder.Services.AddHangfireServer(options =>
{
options.Queues = new[] { "default", "critical" };
});
β
Avoid Heavy Logic in Controllers
Move background logic to services.
π Whatβs New in .NET 9 Context?
While Hangfire itself is framework-agnostic, .NET 9 improvements help:
β‘ Better performance for background services
β‘ Improved dependency injection
β‘ Native AOT compatibility (with limitations)
β‘ Minimal APIs integration
app.MapGet("/send-email", () =>
{
BackgroundJob.Enqueue<EmailService>(x => x.SendEmail("[email protected]"));
return "Job Scheduled!";
});
π Conclusion
Integrating Hangfire in .NET 9 is straightforward and extremely powerful. It allows you to:
For any real-world application (especially enterprise apps), Hangfire is almost a must-have for background processing.
π¬ Interview Tip
If asked:
π βHow do you handle background processing in .NET?β
You can say:
βI use Hangfire for background job processing because it provides persistent jobs, retry mechanisms, and a dashboard for monitoring. It integrates well with ASP.NET Core and supports recurring, delayed, and chained jobs.β