Configuration

Configure BackWave's store selection, Worker Group options (Dispatch Policy, poll interval, retries, leases), and per-Queue Concurrency Limits.


BackWave is configured where you call AddBackWave(...): you select a store, register the generated jobs, and declare one or more Worker Groups. This page walks the options you'll reach for most. All of it mirrors the real sample API.

The shape of AddBackWave#

Program.cs
builder.Services.AddBackWave(backwave =>
{
    backwave
        .UseStore(_ => new PostgresJobStore(new PostgresStoreOptions { /* ... */ }))
        .UseJobs(BackWaveJobs.Module);
 
    backwave.AddWorkerGroup(new WorkerGroupOptions { /* ... */ });
});
  • UseStore(...) selects the Storage Adapter (or the In-Memory Store when you don't need durability). See Installation for the store options.
  • UseJobs(BackWaveJobs.Module) registers the Job Registry, a scoped handler per [Job], and the class that declares them, in one call.
  • AddWorkerGroup(...) declares a pool of Workers. You can call it more than once; a process may host several Worker Groups.

Worker Group options#

A Worker Group is one registered pool of Workers that declares which Queues it serves and its Dispatch Policy.

Program.cs
backwave.AddWorkerGroup(new WorkerGroupOptions
{
    Name = "strict-priority",
    Policy = new DispatchPolicy.Strict(["critical", "bulk", "limited"]),
    PollInterval = TimeSpan.FromMilliseconds(250),
    RetryPolicy = new RetryPolicy { MaxAttempts = 5, Backoff = _ => TimeSpan.FromMilliseconds(500) },
});
OptionWhat it controls
NameThe Worker Group's identifier.
PolicyThe Dispatch Policy: which Queue to claim from next.
PollIntervalHow often the pump polls the store for due work. Polling is the source of truth; Wake-Up Hints only cut latency.
RetryPolicyThe attempt ceiling and backoff for jobs this group runs.

Dispatch Policy#

A Worker Group's rule for choosing which Queue to claim from next. Both policies are work-conserving, so a worker never idles while any served Queue has due work.

  • Strict: an ordered list; earlier Queues preempt later ones, and starvation of the tail is accepted by design.

    Policy = new DispatchPolicy.Strict(["critical", "bulk", "limited"]),
  • Weighted: smooth weighted round-robin, deterministic with no randomness. Here high gets six turns per one of low:

    Policy = new DispatchPolicy.Weighted([("high", 6), ("low", 1)]),

Retries#

RetryPolicy sets the attempt ceiling and the backoff between attempts. An Attempt is one execution try; a Lease expiry counts as an attempt just like a thrown exception. When a job exhausts MaxAttempts it lands Dead-Lettered.

Program.cs
RetryPolicy = new RetryPolicy
{
    MaxAttempts = 3,
    Backoff = attempt => TimeSpan.FromMilliseconds(500),
},

Per-Queue Concurrency Limits#

A Concurrency Limit is a per-Queue, cluster-wide cap on simultaneously executing jobs, enforced at claim time. It is distinct from Backpressure (a node's own pool capacity): the Concurrency Limit is one shared counter across the whole cluster for a Queue. A slot is released on terminal state or Lease expiry, never leaked by a crash. Set it through the store:

Program.cs
await app.Services.GetRequiredService<IJobStore>()
    .SetConcurrencyLimitAsync("limited", 1);

Hosting several Worker Groups#

A single process can host multiple Worker Groups (for example a Strict group for priority traffic and a Weighted group for fair sharing) without a separate worker host:

Program.cs
builder.Services.AddBackWave(backwave =>
{
    backwave.AddWorkerGroup(new WorkerGroupOptions
    {
        Name = "strict-priority",
        Policy = new DispatchPolicy.Strict(["critical", "bulk"]),
        RetryPolicy = new RetryPolicy { MaxAttempts = 5 },
    });
 
    backwave.AddWorkerGroup(new WorkerGroupOptions
    {
        Name = "weighted-fair",
        Policy = new DispatchPolicy.Weighted([("high", 6), ("low", 1)]),
        RetryPolicy = new RetryPolicy { MaxAttempts = 3 },
    });
});

Where to go next#