Retry & Backoff
When jobs fail with ordinary errors, Monque automatically retries them using exponential backoff. Retry delays give an unavailable service time to recover. Jobs become failed when they reach the configured failure limit.
Quick Reference
Section titled “Quick Reference”| Option / Property | Default | Description |
|---|---|---|
maxRetries | 10 | Failure count at which a job becomes permanently failed |
baseRetryInterval | 1000ms | Base delay for backoff calculation |
maxBackoffDelay | 86400000ms | Maximum backoff cap (24h) |
Job.failCount | - | Number of failed attempts |
Job.failReason | - | Last error message |
How Retries Work
Section titled “How Retries Work”- Worker handler throws an error or returns rejected promise
failCountis incrementedfailReasonis set to the error message- If the error is
NonRetryableErrororfailCount >= maxRetries: mark asfailed - Otherwise: schedule retry with backoff
Backoff Formula
Section titled “Backoff Formula”The delay varies randomly by ±25% around baseDelay, then is capped at
maxBackoffDelay. This spreads retries when many jobs fail together.
Example Timeline
Section titled “Example Timeline”With default settings (baseRetryInterval: 1000ms, maxRetries: 10), a job can run
once initially and retry up to nine times. The tenth failure is terminal. Delays below
are before jitter:
| Failed attempt | failCount | Delay before next attempt |
|---|---|---|
| Initial run | 1 | 2s |
| 1st retry | 2 | 4s |
| 2nd retry | 3 | 8s |
| 3rd retry | 4 | 16s |
| 4th retry | 5 | 32s |
| 5th retry | 6 | 64s |
| 6th retry | 7 | 128s |
| 7th retry | 8 | 256s |
| 8th retry | 9 | 512s |
| 9th retry | 10 | No retry; failed permanently |
Configuration
Section titled “Configuration”Global Settings
Section titled “Global Settings”Configure retry behavior in MonqueOptions:
Per-Worker Settings
Section titled “Per-Worker Settings”Override the same options when registering a worker:
Each omitted value inherits the scheduler setting. maxRetries: 0 or 1 makes the
first failure terminal; NonRetryableError always skips retries. Worker overrides
use the same failure-count and jitter rules as scheduler settings.
Settings belong to the local worker, not the stored job. Configure workers for the same job name consistently across scheduler instances. Replacing a worker affects future executions; an active execution keeps the retry settings it started with.
Ts.ED forwards these settings from @Job('send', { maxRetries: 5 }); see
Ts.ED integration.
Configuration Options
Section titled “Configuration Options”| Option | Default | Description |
|---|---|---|
maxRetries | 10 | Failure count at which retries stop |
baseRetryInterval | 1000 (1s) | Base delay multiplied by backoff factor |
maxBackoffDelay | 86400000 | Maximum delay cap (24 hours) |
Monitoring Retries
Section titled “Monitoring Retries”Via Events
Section titled “Via Events”Subscribe to job:fail events:
Via Job Properties
Section titled “Via Job Properties”Error Handling Patterns
Section titled “Error Handling Patterns”Transient vs Permanent Failures
Section titled “Transient vs Permanent Failures”Throw NonRetryableError when retrying cannot resolve the problem:
Requires @monque/core 1.14.0 or later on every worker using this error. Import the
class from the same installed core package used by your scheduler; matching an error’s
name alone does not disable retries. Subclasses of NonRetryableError also stop retries.
The job becomes failed immediately. failCount increases by one, failReason stores
the message, and job:fail reports willRetry: false. Ordinary errors keep the configured
backoff policy. Catching an error and returning normally still records a successful run.
For recurring jobs, this stops the recurring job as well: no next occurrence is scheduled, matching exhausted-retry behavior. The cron expression and timezone remain available.
After fixing the cause, you can use retryJob(), bulk retry, the Management API, or
Dashboard’s Retry action. Manual retry resets the failure count and runs the job again;
a successful recurring job then resumes its schedule. The error does not permanently
prohibit operator retries.
Management and Dashboard use the existing failed status, failure reason, and attempt
count. No migration or new status is needed; persisted jobs do not record a separate
non-retryable flag.
Circuit Breaker Pattern
Section titled “Circuit Breaker Pattern”Recurring Job Retries
Section titled “Recurring Job Retries”Recurring jobs use the same retry delays, then return to their cron schedule:
- Failed job retries with exponential backoff
- After successful completion (including successful retry), job reschedules using original cron
- The next cron occurrence is calculated after the successful run; missed occurrences are not replayed
Example
Section titled “Example”Best Practices
Section titled “Best Practices”1. Set Appropriate Retry Limits
Section titled “1. Set Appropriate Retry Limits”2. Log Retry Context
Section titled “2. Log Retry Context”3. Handle Dead Letter Queue
Section titled “3. Handle Dead Letter Queue”4. Implement Backoff Jitter (Manual)
Section titled “4. Implement Backoff Jitter (Manual)”Add a random delay if many workers might retry a service at the same time:
Disabling Retries
Section titled “Disabling Retries”Set maxRetries: 0 for jobs that should never retry:
Next Steps
Section titled “Next Steps”- Jobs - Understand job lifecycle
- Workers - Configure worker behavior
- Change Streams - Configure job discovery
API Reference
Section titled “API Reference”MonqueOptions- Retry configuration optionsJob- Job interface withfailCount,failReasonMonqueEventMap- Events includingjob:failMonqueError- Base error class