# Configuration

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`

```csharp title="Program.cs" {3-7}
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](/docs/introduction/install) 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.

```csharp title="Program.cs" {3-6}
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) },
});
```

| Option | What it controls |
| --- | --- |
| `Name` | The Worker Group's identifier. |
| `Policy` | The **Dispatch Policy**: which Queue to claim from next. |
| `PollInterval` | How often the pump polls the store for due work. Polling is the source of truth; Wake-Up Hints only cut latency. |
| `RetryPolicy` | The 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.

  ```csharp
  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`:

  ```csharp
  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**.

```csharp title="Program.cs" {1-5}
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:

```csharp title="Program.cs" {1-2}
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:

```csharp title="Program.cs" {3-8,10-15}
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

- [Storage](/docs/storage/overview): the Storage Adapters and the determinism
  boundary they sit on.
- [Dashboard & Operations](/docs/dashboard-operations/overview): Dashboard
  Permissions and Operator Actions for running BackWave in production.
- [Virtual-Time Testing](/docs/testing/behavior-over-time): assert on exactly what ran.
