Version v0.1 · dotnet
Distributed Execution
How workers coordinate via leases and jitter to safely distribute background workload.
Distributed Execution
DurableStack is designed for multiple workers competing for work across instances.
It distributes load by combining claim limits, jittered polling, and lease ownership.
Core model
Each worker loop does three things:
- materializes due recurring runs
- claims available due runs up to local capacity
- executes claimed runs with lease heartbeat protection
Local concurrency is bounded by:
BatchSize/ClaimBatchSizeMaxConcurrentRuns
Why jitter matters
Without jitter, workers poll at the same interval boundaries and create synchronized load spikes.
With PollJitterEnabled, each worker randomizes poll delay by a bounded ratio:
- delay factor =
1 +/- PollJitterRatio - default ratio is
0.2(up to +/-20%)
This naturally spreads claim attempts over time and reduces thundering herd behavior against the store.
Example
If PollIntervalSeconds = 5 and PollJitterRatio = 0.2, each poll is roughly between 4 and 6 seconds.
builder.Services.AddDurableStackPostgres(connectionString, options =>
{
options.PollIntervalSeconds = 5;
options.PollJitterEnabled = true;
options.PollJitterRatio = 0.2;
});
How lease ownership prevents duplicate active execution
When a worker claims a run, the run is leased to that worker for LeaseDuration.
Only the lease owner should be executing that run at that time.
During execution:
- a background heartbeat extends lease ownership periodically
- extension cadence is half lease duration
If the worker crashes or stops heartbeating, lease expires and another worker can reclaim the run.
This model limits execution to one active lease owner per run under normal operation while enabling recovery after failures.
Single execution of each run, practically
The system targets single active execution per run through lease ownership.
As with any distributed lease model, edge cases (crash/network timing) can lead to re-attempts, so handlers must remain idempotent.
Think of the guarantee as:
- single active lease owner in normal operation
- durable recovery and retry when interruptions occur
Worker identity in distributed environments
Set a unique WorkerName per process/container.
DurableStack uses worker identity for lease ownership, diagnostics, and operational traceability.
var workerName = $"{Environment.MachineName}-{Environment.ProcessId}";
builder.Services.AddDurableStackPostgres(connectionString, options =>
{
options.WorkerName = workerName;
});
Practical tuning guidance
- Start with moderate
BatchSizeandMaxConcurrentRuns. - Enable poll jitter in multi-worker deployments.
- Set
LeaseDurationabove normal execution time for routine jobs. - Monitor retries and lease extensions before increasing throughput aggressively.