ZeroAlloc.Scheduling.Redis 2.2.10

dotnet add package ZeroAlloc.Scheduling.Redis --version 2.2.10
                    
NuGet\Install-Package ZeroAlloc.Scheduling.Redis -Version 2.2.10
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ZeroAlloc.Scheduling.Redis" Version="2.2.10" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ZeroAlloc.Scheduling.Redis" Version="2.2.10" />
                    
Directory.Packages.props
<PackageReference Include="ZeroAlloc.Scheduling.Redis" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ZeroAlloc.Scheduling.Redis --version 2.2.10
                    
#r "nuget: ZeroAlloc.Scheduling.Redis, 2.2.10"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ZeroAlloc.Scheduling.Redis@2.2.10
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ZeroAlloc.Scheduling.Redis&version=2.2.10
                    
Install as a Cake Addin
#tool nuget:?package=ZeroAlloc.Scheduling.Redis&version=2.2.10
                    
Install as a Cake Tool

ZeroAlloc.Scheduling

NuGet Build License: MIT AOT GitHub Sponsors

ZeroAlloc.Scheduling is a source-generated background job scheduler for .NET 8, 9 and 10. Decorate any class with [Job] and the source generator wires up the executor, DI registration, and recurring startup automatically — no reflection, no convention scanning at runtime.

Install

The source generator is bundled into the main package — a single PackageReference is all you need:

dotnet add package ZeroAlloc.Scheduling
dotnet add package ZeroAlloc.Scheduling.InMemory   # or EfCore / Orm / Redis

The standalone ZeroAlloc.Scheduling.Generator package is still published for backwards compatibility with existing direct PackageReferences, but new consumers should reference only ZeroAlloc.Scheduling.

Example

using System.Text.Json.Serialization;
using Microsoft.Extensions.DependencyInjection;
using ZeroAlloc.Scheduling;
using ZeroAlloc.Scheduling.InMemory;
using ZeroAlloc.Serialisation;

// 1. Define jobs — the generator picks them up automatically.
//    [ZeroAllocSerializable] plus a JsonSerializerContext give each job an AOT-safe serializer,
//    because the store persists every job as bytes.
[Job(Every = Every.Hour)]
[ZeroAllocSerializable(SerializationFormat.SystemTextJson)]
public sealed class CleanupExpiredSessionsJob : IJob
{
    public ValueTask ExecuteAsync(JobContext ctx, CancellationToken ct)
        => ctx.Services.GetRequiredService<ISessionRepository>().DeleteExpiredAsync(ct);
}

[Job]
[ZeroAllocSerializable(SerializationFormat.SystemTextJson)]
public sealed record SendOrderConfirmationJob(int OrderId) : IJob
{
    public ValueTask ExecuteAsync(JobContext ctx, CancellationToken ct)
        => ctx.Services.GetRequiredService<IOrderMailer>().SendConfirmationAsync(OrderId, ct);
}

[JsonSerializable(typeof(CleanupExpiredSessionsJob))]
internal sealed partial class CleanupExpiredSessionsJobJsonContext : JsonSerializerContext;

[JsonSerializable(typeof(SendOrderConfirmationJob))]
internal sealed partial class SendOrderConfirmationJobJsonContext : JsonSerializerContext;

// 2. Register — the generated Add...Job() methods wire each executor, and the recurring startup
//    for CleanupExpiredSessionsJob. AddSerializerDispatcher() is generated by ZeroAlloc.Serialisation,
//    which ZeroAlloc.Scheduling brings in; see docs/migrating-to-v2.md.
services.AddSerializerDispatcher();
services.AddScheduling()
        .WithInMemoryStore()
        .AddCleanupExpiredSessionsJob()
        .AddSendOrderConfirmationJob();

// 3. Enqueue a one-off job from application code
public class OrderService(IScheduler scheduler)
{
    public async Task CompleteOrderAsync(Order order, CancellationToken ct)
    {
        await ProcessAsync(order, ct);
        await scheduler.EnqueueAsync(new SendOrderConfirmationJob(order.Id), ct);
    }
}

Performance

Head-to-head vs Coravel 6.0.2 (de-facto in-process scheduler) and a hand-rolled BackgroundService + Timer baseline. BenchmarkDotNet 0.15.8, .NET 10.0.13, measured 2026-10-15. Allocations are exact. Speed is shown as same-run ratios, because the benchmark host is a shared VM; absolute timings are not published.

Operation Coravel Naive Timer ZA.Scheduling
Job registration 696 B per Schedule() call — (compile-time) compile-time, 0 B at runtime
Single dispatch (registration only) indistinguishable from an empty method, 0 B indistinguishable from an empty method, 0 B

Honest reading: Coravel's Schedule() is a runtime call that allocates a queue entry; 100 calls allocate 76,320 B and take 15.36× as long as one in the same run. ZA.Scheduling's [Job] registration happens at compile time via source generation — no equivalent runtime cost. For dispatch overhead, ZA matches a hand-written Timer: BenchmarkDotNet cannot tell either from an empty method. The value of the abstraction is [Job] itself (declarative retries / cron / store-backed persistence), not raw dispatch speed.

Full methodology + design analysis: docs/performance.md.

Features

  • Source generator — [Job] on a class emits a typed executor, DI extension method, and optional recurring startup (IHostedService)
  • Recurring jobs — [Job(Cron = "0 * * * *")] or [Job(Every = Every.Hour)] — scheduled via Cronos at startup
  • Retry with backoff — exponential retry up to MaxAttempts (per-job or global); dead-letters after exhaustion
  • Multiple backends — InMemory (dev/test), EF Core (SQL Server / PostgreSQL / SQLite), ZeroAlloc.ORM, Redis
  • Dashboard — embedded HTML/JS dashboard via app.MapJobsDashboard("/jobs")
  • Blazor component — <JobsDashboard> Razor component for integration into Blazor apps
  • Mediator bridge — [Job] + IRequest<Unit> auto-registers MediatorJobTypeExecutor<T>, routing execution through ZeroAlloc.Mediator pipeline behaviors
  • Native AOT compatible — no reflection at runtime; all dispatch resolved at compile time

Dashboard

An embedded HTML/JS dashboard — summary cards for each job state, a live-refreshing table with per-row requeue / delete actions, and fully responsive down to mobile widths.

app.MapJobsDashboard("/jobs");

// Optional: protect with auth
app.MapJobsDashboard("/jobs").RequireAuthorization("AdminPolicy");

Scheduler dashboard — desktop

Tablet (768 × 1024) and mobile (375 × 812) captures live in docs/screenshots/.

See Dashboard for the full endpoint reference and the Blazor component.

Packages

Package Description
ZeroAlloc.Scheduling Core interfaces, worker service, scheduler, bundled source generator
ZeroAlloc.Scheduling.Generator Source generator — legacy, already bundled inside ZeroAlloc.Scheduling
ZeroAlloc.Scheduling.InMemory In-process store for development and testing
ZeroAlloc.Scheduling.EfCore EF Core store (SQL Server, PostgreSQL, SQLite)
ZeroAlloc.Scheduling.Orm ZeroAlloc.ORM store (SQLite, PostgreSQL, SQL Server), WithOrm(); net10.0 only
ZeroAlloc.Scheduling.Redis Redis store for distributed deployments
ZeroAlloc.Scheduling.Dashboard Embedded HTML dashboard (MapJobsDashboard)
ZeroAlloc.Scheduling.Dashboard.Blazor Blazor component library
ZeroAlloc.Scheduling.Mediator ZeroAlloc.Mediator bridge
ZeroAlloc.Scheduling.Resilience ZeroAlloc.Resilience bridge: retry, timeout and circuit-breaker around job execution
ZeroAlloc.Scheduling.Telemetry ZeroAlloc.Telemetry bridge: OpenTelemetry spans and metrics for job execution (WithTelemetry())

Documentation

Page Description
Getting Started Install and schedule your first job in five minutes
Source Generator [Job], Every, Cron, generated extension methods
Backends InMemory, EF Core, and Redis store configuration
Dashboard Embedded HTML dashboard and Blazor component
Mediator Bridge Route job execution through ZeroAlloc.Mediator
Resilience Bridge Wrap job execution in ZeroAlloc.Resilience policies
Telemetry Bridge OpenTelemetry spans and metrics for job execution
Migrating to v2 The serializer choice 2.0 made explicit, and the AOT-safe job setup
Diagnostics ZASCH001, ZASCH011, ZASCH012 and ZASCH013 compiler diagnostic reference
Performance Throughput, allocation profile, and tuning guide

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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
2.2.10 0 10/15/2026
2.2.9 104 10/12/2026
2.2.8 91 10/12/2026
2.2.7 109 10/11/2026
2.2.6 168 10/11/2026
2.2.5 114 10/11/2026
2.2.4 102 10/11/2026
2.2.3 91 10/11/2026
2.2.2 99 10/10/2026
2.2.1 109 10/10/2026
2.2.0 110 10/10/2026
2.1.0 117 10/10/2026
2.0.17 94 10/10/2026
2.0.15 97 10/9/2026
2.0.14 87 10/7/2026
2.0.13 103 10/7/2026
2.0.12 93 10/6/2026
2.0.11 99 10/4/2026
2.0.10 99 10/3/2026
2.0.9 95 10/2/2026
Loading failed