Configure delayed retries

Component: NServiceBus
NuGet Package NServiceBus (6.x)
Starting from NServiceBus Version 6 Delayed Retries Policy (formerly known as Second Level Retries Policy) has been deprecated in favor of the new custom Recoverability policy which allows much more control over the Recoverability behavior. This documentation shows how previous Delayed Retries Policies can be implemented with the new Recoverability Policy.
Delayed Retries cannot be used when transport transactions are disabled or Delayed Delivery is not available. For more information about transport transactions, refer to transport transaction. For more details on the caveats, see: Delayed Delivery article.

Configuring Delayed Retries

  • TimeIncrease: Specified as a TimeSpan. Specifies the delay interval for each retry attempt. This delay increases by the same timespan with each delayed delivery. For example, if the specified value is 10 seconds, i.e. 00:00:10, then the first delayed retry will be at 10 seconds, the subsequent delayed retry will be 20 seconds and so on.
  • NumberOfRetries: Number of times Delayed Retries are performed. Default: 3.
var recoverability = endpointConfiguration.Recoverability();
recoverability.Delayed(
    delayed =>
    {
        delayed.NumberOfRetries(2);
        delayed.TimeIncrease(TimeSpan.FromMinutes(5));
    });

Disabling through code

var recoverability = endpointConfiguration.Recoverability();
recoverability.Delayed(
    delayed =>
    {
        delayed.NumberOfRetries(0);
    });

Custom Retry Policy

Custom retry logic can be configured via code.

var recoverability = endpointConfiguration.Recoverability();
recoverability.CustomPolicy(MyCustomRetryPolicy);

Simple Policy

The following retry policy overrides default 10 seconds delay interval and sets it to 5 seconds.

RecoverabilityAction MyCustomRetryPolicy(RecoverabilityConfig config, ErrorContext context)
{
    var action = DefaultRecoverabilityPolicy.Invoke(config, context);
    if (!(action is DelayedRetry delayedRetryAction))
    {
        return action;
    }
    // Override default delivery delay.
    return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(5));
}

Exception based Policy

Sometimes the number of retries or the delay interval might depend on the error exception thrown. The following retry policy extends the previous one by skipping delayed retries whenever MyBusinessException has been thrown during incoming message processing.

RecoverabilityAction MyCustomRetryPolicy(RecoverabilityConfig config, ErrorContext context)
{
    var action = DefaultRecoverabilityPolicy.Invoke(config, context);

    if (!(action is DelayedRetry delayedRetryAction))
    {
        return action;
    }
    if (context.Exception is MyBusinessException)
    {
        return RecoverabilityAction.MoveToError(config.Failed.ErrorQueue);
    }
    // Override default delivery delay.
    return RecoverabilityAction.DelayedRetry(TimeSpan.FromSeconds(5));
}

Legacy .Retries message receiver

In Versions 5 and below, the Delayed Retries used the [endpoint_name].Retries queue for persistent storage of messages to be retried. To prevent message loss when upgrading to Version 6, a dedicated .Retries queue receiver is started if not explicitly disabled. It serves a purpose of forwarding messages from the .Retries queue to the endpoint's main queue to be retried appropriately.

The receiver is only needed during the upgrade from Versions 5 and below and is not needed for new endpoints using Version 6. For details on upgrade process and how to safely disable the receiver refer to the Version 6 Upgrade Guide.

Letting the receiver continue to run might have negative performance implications depending on the transport being used. For example, for endpoints using either SQL Server or Msmq as its transport, endpoint will periodically poll the .Retries queue to check for messages.

The .Retries receiver can be disabled via code using:

var recoverability = endpointConfiguration.Recoverability();
recoverability.DisableLegacyRetriesSatellite();
This .Retries message receiver and the API to disable it will be removed in Version 7.

Samples


Last modified