Surefire.Redis
0.3.0
dotnet add package Surefire.Redis --version 0.3.0
NuGet\Install-Package Surefire.Redis -Version 0.3.0
<PackageReference Include="Surefire.Redis" Version="0.3.0" />
<PackageVersion Include="Surefire.Redis" Version="0.3.0" />
<PackageReference Include="Surefire.Redis" />
paket add Surefire.Redis --version 0.3.0
#r "nuget: Surefire.Redis, 0.3.0"
#:package Surefire.Redis@0.3.0
#addin nuget:?package=Surefire.Redis&version=0.3.0
#tool nuget:?package=Surefire.Redis&version=0.3.0
Surefire
Distributed job scheduling for .NET with a minimal API style.
Preview: Surefire is pre-1.0, so APIs and storage schemas may change.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSurefire();
builder.Services.AddSurefireDashboard();
var app = builder.Build();
app.AddJob("Hello", () => "Hello, World!");
app.MapSurefireDashboard();
app.Run();

Features
- Runs across multiple nodes with coordinated claiming and retry handling. Nodes can register the same or different jobs.
- Built-in dashboard with live logs, progress, run history, and node monitoring.
- Per-job cron, retries, queues, timeouts, and rate limits.
- Stream values into and out of jobs with
IAsyncEnumerable<T>. Run batches and consume their results as a list or a stream. - Call jobs from other jobs using
IJobClient. - Native AOT and trimming support.
- OpenTelemetry traces and metrics. ASP.NET Core health checks.
Install
dotnet add package Surefire
dotnet add package Surefire.Dashboard
Comes with an in-memory store and notifications. Provider packages are available for PostgreSQL, SQL Server, SQLite, and Redis.
dotnet add package Surefire.PostgreSql
dotnet add package Surefire.SqlServer
dotnet add package Surefire.Sqlite
dotnet add package Surefire.Redis
For PostgreSQL with AddNpgsqlDataSource, also add Npgsql.DependencyInjection:
dotnet add package Npgsql.DependencyInjection
builder.Services.AddNpgsqlDataSource(builder.Configuration.GetConnectionString("Surefire")!);
builder.Services.AddSurefire(options => options.UsePostgreSql());
Defining jobs
Register jobs as delegates with AddJob. Parameters resolve from DI and from arguments passed when triggering a run.
AddJob returns a builder that can be used to configure cron, retries, timeouts, rate limits, callbacks, etc.
app.AddJob("Add", (int a, int b) => a + b);
app.AddJob("ImportData", async (JobContext ctx, ILogger<Program> logger, CancellationToken ct) =>
{
for (var i = 1; i <= 10; i++)
{
logger.LogInformation("Step {I}/10", i);
await ctx.ReportProgressAsync(i / 10.0);
await Task.Delay(1000, ct);
}
})
.WithDescription("Imports data and reports progress")
.WithRetry(3);
app.AddJob("GenerateReport", async (IReportService reports, CancellationToken ct) =>
{
await reports.GenerateReportAsync(ct);
})
.WithCron("0 * * * *");
Triggering jobs
Use IJobClient to trigger jobs from anywhere in your app, including inside other jobs.
// Fire and forget
await client.TriggerAsync("ImportData");
// Run a job and wait for the result
var sum = await client.RunAsync<int>("Add", new { a = 1, b = 2 });
// Or stream values as they're produced
await foreach (var value in client.StreamAsync<int>("GenerateNumbers"))
{
// ...
}
// Run a batch and get all results at once
var results = await client.RunBatchAsync<Result>("Process", inputs);
// Or stream batch results as they finish
await foreach (var result in client.StreamBatchAsync<Result>("Process", inputs))
{
// ...
}
Inject IJobClient into a job to call other jobs from inside it:
app.AddJob("AddRandom", async (IJobClient client, CancellationToken ct) =>
{
var a = Random.Shared.Next(1, 101);
var b = Random.Shared.Next(1, 101);
var sum = await client.RunAsync<int>("Add", new { a, b }, cancellationToken: ct);
return new { a, b, sum };
});
Lifecycle callbacks
app.AddJob("ProcessOrder", async (int orderId) => { /* ... */ })
.WithRetry(3)
.OnSuccess((JobContext ctx) =>
{
// Run succeeded
})
.OnRetry((JobContext ctx, ILogger<Program> logger) =>
{
logger.LogWarning("Attempt {Attempt} failed", ctx.Attempt);
})
.OnDeadLetter((JobContext ctx) =>
{
// All retries exhausted
});
OnSuccess fires when a run succeeds. OnRetry fires when Surefire schedules another attempt after a failure.
OnDeadLetter fires when no retries remain.
Dashboard
builder.Services.AddSurefireDashboard();
app.MapSurefireDashboard(); // at /surefire
app.MapSurefireDashboard("/"); // at the root
Includes an embedded dashboard that lets you:
- Trigger jobs, enable or disable them, and pause queues
- Cancel runs or rerun completed ones
- View traces, child runs, errors, arguments, and results
- Use a REST API at
{prefix}/api/for the same actions
If you expose the dashboard outside local development, be sure to configure the returned endpoint group with authorization.
Native AOT and trimming
Includes a source generator for AOT and trim-safe job registration, callbacks, and IJobClient calls. Register your
app's JSON source-generated context so job arguments and results can be serialized without reflection:
builder.Services.AddSurefire(options =>
{
options.SerializerOptions.TypeInfoResolverChain.Insert(0, AppJsonContext.Default);
});
[JsonSerializable(typeof(AddArgs))]
[JsonSerializable(typeof(AddResult))]
internal partial class AppJsonContext : JsonSerializerContext;
Contributing
To get started with the sample app, clone the repo and run:
aspire run
Documentation
See the full documentation at batary.dev/surefire.
License
MIT
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- StackExchange.Redis (>= 2.12.14)
- Surefire (>= 0.3.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.0 | 38 | 5/15/2026 |
| 0.2.0 | 97 | 5/11/2026 |
| 0.1.0-preview.1 | 54 | 5/3/2026 |