Skip to content

Retry & Dead Letter Queue

Retry Policies

GrydJobs uses Polly for retry policy management.

How Retries Work

  1. A job fails with an exception
  2. GrydJobs checks the retry policy configured for that job type
  3. If retries remain, the job is re-enqueued after the backoff delay
  4. If all retries are exhausted, the job is moved to the Dead Letter Queue

Configuration

csharp
builder.Services.AddGrydJobs(options =>
{
    // Default policy for all jobs
    options.DefaultRetryPolicy = new RetryPolicyOptions
    {
        MaxRetries = 3,
        InitialDelay = TimeSpan.FromSeconds(10),
        BackoffType = BackoffType.Exponential
    };

    // Per-job overrides
    options.RetryPolicies
        .Register<CriticalJob>(maxRetries: 10, delay: TimeSpan.FromMinutes(1))
        .Register<IdempotentJob>(maxRetries: 20, delay: TimeSpan.FromSeconds(5));
});

Retry Timeline Example (Exponential Backoff)

AttemptDelayTotal Elapsed
1st retry10s10s
2nd retry20s30s
3rd retry40s1m 10s
4th retry80s2m 30s
5th retry160s5m 10s

Dead Letter Queue

Jobs that exhaust all retry attempts are automatically moved to the Dead Letter Queue (DLQ).

DLQ Entry Contents

Each dead letter entry preserves:

  • Original job ID — reference to the source job
  • Job type name — the .NET type of the failed job
  • Error details — last error message and stack trace
  • Reason — why the job was dead-lettered (MaxRetriesExceeded, Timeout, Manual)
  • Attempt count — total number of execution attempts
  • Timestamps — original enqueue time and dead-letter time
  • Correlation ID — for distributed tracing
  • Tenant ID — for multi-tenant isolation

Inspecting the DLQ

http
GET /api/v1/dead-letter-jobs?page=1&pageSize=20

Response:

json
{
  "items": [
    {
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "originalJobId": "ext-12345",
      "jobTypeName": "MyApp.Jobs.ImportDataJob",
      "lastErrorMessage": "Connection timeout after 30s",
      "reason": "MaxRetriesExceeded",
      "totalAttempts": 5,
      "deadLetteredAt": "2026-02-18T14:30:00Z"
    }
  ],
  "totalCount": 1,
  "pageNumber": 1,
  "pageSize": 20
}

Retrying Dead Letter Jobs

Retry a single job:

http
POST /api/v1/dead-letter-jobs/{id}/retry

Purging the DLQ

Remove old entries:

http
POST /api/v1/dead-letter-jobs/purge
Content-Type: application/json

{ "retentionDays": 30 }

Automatic Cleanup

GrydJobs includes a background service that automatically purges DLQ entries older than DeadLetterRetentionDays:

csharp
options.DeadLetterRetentionDays = 30; // Auto-purge after 30 days
options.DeadLetterRetentionDays = null; // Disable auto-purge

Released under the MIT License.