Documentation
¶
Overview ¶
Package backoff provides pluggable exponential backoff strategies, with optional jitter, for retry policies.
bi := backoff.NewFullJitterBackoffInterval(500 * time.Millisecond)
for {
if err := doSomething(); err != nil {
time.Sleep(bi.Next())
continue
}
break
}
Jitter strategies are modeled after the AWS Architecture Blog reference "Exponential Backoff and Jitter": https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/
- FullJitter implements that article's recommended (and, per its own simulation, most effective) strategy and is this package's default.
- EqualJitter implements the article's "Equal Jitter" strategy, trading some desynchronization power for a wait that never gets too short.
- DecorrelatedJitter implements the article's "Decorrelated Jitter" strategy as its own NextFunc rather than a JitterFunc, since its recurrence depends on the previously returned sleep instead of a Multiplier-based ramp -- see DecorrelatedNextFunc.
- PercentJitter is this package's own narrower-band alternative and is not one of the strategies the article names.
Index ¶
- Constants
- func DecorrelatedNextFunc(b *BackoffInterval) time.Duration
- func DecorrelatedResetFunc(b *BackoffInterval)
- func EqualJitter(interval time.Duration, _ *ExponentialConfig) time.Duration
- func ExponentialNextFunc(b *BackoffInterval) time.Duration
- func ExponentialResetFunc(b *BackoffInterval)
- func FullJitter(interval time.Duration, _ *ExponentialConfig) time.Duration
- func PercentJitter(interval time.Duration, config *ExponentialConfig) time.Duration
- type Backoff
- type BackoffInterval
- func NewBackoffInterval(interval time.Duration) *BackoffInterval
- func NewDecorrelatedBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func NewEqualJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func NewExponentialBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func NewFullJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func NewJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func NewPercentJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
- func (b *BackoffInterval) Current() time.Duration
- func (b *BackoffInterval) Next() time.Duration
- func (b *BackoffInterval) Reset()
- func (b *BackoffInterval) WithConfig(config any) *BackoffInterval
- func (b *BackoffInterval) WithNextFunc(nextFunc NextFunc) *BackoffInterval
- func (b *BackoffInterval) WithResetFunc(resetFunc ResetFunc) *BackoffInterval
- func (b *BackoffInterval) WithState(state any) *BackoffInterval
- func (b *BackoffInterval) WrapError(err error) error
- type DecorrelatedConfig
- type DecorrelatedState
- type ExponentialConfig
- type ExponentialState
- type JitterFunc
- type NextFunc
- type ResetFunc
Constants ¶
const DefaultMaxAttempts = 3
DefaultMaxAttempts is the default number of attempts at DefaultMaxInterval before resetting ExponentialBackoff to its initial interval (e.g., 3 attempts). It controls how long the backoff persists at the maximum delay.
const DefaultMaxInterval = 1 * time.Minute
DefaultMaxInterval is the default maximum delay for ExponentialBackoff (e.g., 1 minute). It caps the interval to prevent excessively long retries.
const DefaultMultiplier = 2.0
DefaultMultiplier is the default factor by which the interval grows in ExponentialBackoff (e.g., 2.0 means each attempt’s delay is 2.0 times the previous one). It determines the exponential growth rate. While 2.0 is a classic default in many sources, modern AWS SDKs and some HTTP clients often use 1.5 as a less aggressive default (to avoid excessive wait times early). See ModerateBackoffMultiplier for a gentler alternative.
const DefaultRandomizer = 0.25
DefaultRandomizer is the default jitter magnitude for ExponentialBackoff specifying the relative deviation (e.g., 0.25 means ±25% of the interval). It controls the randomness added to desynchronize retries.
const DefaultStartInterval = 250 * time.Millisecond
DefaultStartInterval is the default starting delay for ExponentialBackoff (e.g., 500ms for the first retry). It sets the baseline for the backoff sequence.
const ModerateMultiplier = 1.5
ModerateMultiplier is an alternative multiplier for ExponentialBackoff, increasing the interval by 1.5x each attempt for a gentler escalation compared to BackoffMultiplier. Use this for scenarios where slower retry growth is preferred, such as less contended systems.
Variables ¶
This section is empty.
Functions ¶
func DecorrelatedNextFunc ¶
func DecorrelatedNextFunc(b *BackoffInterval) time.Duration
DecorrelatedNextFunc implements the "Decorrelated Jitter" strategy from the AWS "Exponential Backoff and Jitter" reference (https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/):
sleep = min(cap, random(base, sleep_prev * 3))
Unlike ExponentialNextFunc, there is no deterministic ramp separate from the jitter: each call's randomization is derived directly from the previously returned sleep, not from a Multiplier-based doubling. The AWS reference defines no MaxAttempts/Cycles reset for this strategy, so none is applied here -- the sequence runs indefinitely.
Thread-safe: locks the BackoffInterval's mutex to ensure consistent state updates.
func DecorrelatedResetFunc ¶
func DecorrelatedResetFunc(b *BackoffInterval)
DecorrelatedResetFunc resets a Decorrelated Jitter sequence's sleep back to the initial interval. Thread-safe: locks the BackoffInterval's mutex to ensure consistent state updates.
func EqualJitter ¶
func EqualJitter(interval time.Duration, _ *ExponentialConfig) time.Duration
EqualJitter implements the "Equal Jitter" strategy from the AWS "Exponential Backoff and Jitter" reference (https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/): sleep = half + random(0, half), where half = interval/2. It always keeps at least half of the computed interval, trading some of FullJitter's desynchronization power for a wait that never collapses close to zero -- useful when a very short retry would still likely fail (e.g. the remote side needs a minimum recovery time).
func ExponentialNextFunc ¶
func ExponentialNextFunc(b *BackoffInterval) time.Duration
ExponentialNextFunc implements the exponential backoff logic for BackoffInterval. It returns the next interval duration for a retry attempt, updating the internal state accordingly. The interval increases exponentially with each call, up to the configured maximum. If the maximum interval is reached for a number of attempts specified by MaxAttempts, the cycle is reset and begins again from the initial interval. If jitter is enabled (Jittered == true), the interval is randomized within a range defined by the Randomizer setting to help prevent synchronized retries.
Thread-safe: locks the BackoffInterval's mutex to ensure consistent state updates.
func ExponentialResetFunc ¶
func ExponentialResetFunc(b *BackoffInterval)
ExponentialResetFunc resets the state of an Exponential backoff sequence to the initial configuration. It sets the interval and counters back to their starting values, so the next call will begin anew. Thread-safe: locks the BackoffInterval's mutex to ensure consistent state updates.
func FullJitter ¶
func FullJitter(interval time.Duration, _ *ExponentialConfig) time.Duration
FullJitter implements the "Full Jitter" strategy from the AWS "Exponential Backoff and Jitter" reference (https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/): sleep = random(0, interval). It desynchronizes retrying clients more effectively than PercentJitter, including on the very first (cold-start) attempt, and is the package's default jitter strategy.
func PercentJitter ¶
func PercentJitter(interval time.Duration, config *ExponentialConfig) time.Duration
PercentJitter randomizes interval within a symmetric band of ±config.Randomizer (e.g. 0.25 means ±25%). If Randomizer <= 0, interval is returned unchanged. This is the package's original jitter formula; it does not match any of the strategies named in the AWS "Exponential Backoff and Jitter" reference (see FullJitter), but is kept as an explicit opt-in.
Types ¶
type Backoff ¶
type Backoff interface {
Current() time.Duration
// Next returns the duration to wait before the next retry attempt.
// The duration may vary depending on the backoff strategy (e.g., fixed,
// exponential).
Next() time.Duration
// Reset resets the backoff state to its initial configuration, allowing
// the backoff sequence to start anew.
Reset()
// WrapError wraps err with the current backoff interval, so callers can
// surface how long the next retry will wait without losing the original
// error via errors.Is/errors.As.
WrapError(err error) error
}
Backoff defines an interface for backoff strategies that generate retry delays. Implementations provide the next delay duration and a method to reset the backoff state.
type BackoffInterval ¶
type BackoffInterval struct {
// Interval is the current Interval duration, used as the default if no
// nextFunc is set.
Interval time.Duration
// InitialInterval is the initial interval, used as the default if no
// nextFunc is set.
InitialInterval time.Duration
// Config is an optional configuration object (e.g., *ExponentialConfig)
// associated with the backoff logic.
Config any
// State is an optional state object (e.g., *ExponentialState) for
// maintaining backoff progress.
State any
// contains filtered or unexported fields
}
BackoffInterval implements a flexible backoff mechanism with pluggable logic for generating the next interval and resetting state.
func NewBackoffInterval ¶
func NewBackoffInterval(interval time.Duration) *BackoffInterval
NewBackoffInterval creates a new BackoffInterval with the specified initial interval. By default, the returned BackoffInterval has no nextFunc or resetFunc set, so it will always return the provided interval unless those are configured.
func NewDecorrelatedBackoffInterval ¶
func NewDecorrelatedBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewDecorrelatedBackoffInterval constructs a new BackoffInterval using the Decorrelated Jitter strategy. The first argument is the initial interval, used as both the recurrence's base and the starting sleep (required). You may override config/state by passing string-keyed options, e.g.:
NewDecorrelatedBackoffInterval(
10*time.Second,
"config", &DecorrelatedConfig{...},
)
func NewEqualJitterBackoffInterval ¶
func NewEqualJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewEqualJitterBackoffInterval constructs an exponential backoff using the "Equal Jitter" strategy (see EqualJitter): each wait stays within [interval/2, interval] instead of ranging down to zero. Prefer this over FullJitter when a very short wait would still likely fail against the resource being retried.
func NewExponentialBackoffInterval ¶
func NewExponentialBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewExponentialBackoffInterval constructs a new BackoffInterval using exponential settings. The first argument is the initial interval (required). You may override config/state by passing string-keyed options, e.g.:
NewExponentialBackoffInterval(
10*time.Second,
"config", &ExponentialConfig{...},
"state", &ExponentialState{...},
)
func NewFullJitterBackoffInterval ¶
func NewFullJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewFullJitterBackoffInterval constructs an exponential backoff using the "Full Jitter" strategy (see FullJitter): each wait is randomized across the entire range [0, interval]. This spreads out retrying clients the most and is the strategy AWS's "Exponential Backoff and Jitter" reference found most effective at reducing total client/server work -- use it as the default choice for retrying against a shared/remote resource unless you have a specific reason to prefer a narrower spread.
func NewJitterBackoffInterval ¶
func NewJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewJitterBackoffInterval constructs an exponential backoff with jitter enabled using whichever JitterStrategy the caller configures (via the "config" option); if none is set, it defaults to FullJitter. Prefer the explicit NewFullJitterBackoffInterval / NewPercentJitterBackoffInterval constructors when you want a specific strategy without reaching into Config yourself.
func NewPercentJitterBackoffInterval ¶
func NewPercentJitterBackoffInterval(interval time.Duration, options ...any) *BackoffInterval
NewPercentJitterBackoffInterval constructs an exponential backoff using the "Percent Jitter" strategy (see PercentJitter): each wait stays within ±Randomizer of the computed interval instead of ranging down to zero. It desynchronizes retries less aggressively than FullJitter, but keeps waits close to the "expected" backoff curve, which is useful when a caller (or a human reading logs) needs the wait time to stay roughly predictable.
func (*BackoffInterval) Current ¶
func (b *BackoffInterval) Current() time.Duration
Current returns the current interval duration for this backoff instance. This method is thread-safe.
func (*BackoffInterval) Next ¶
func (b *BackoffInterval) Next() time.Duration
Next returns the duration to wait before the next retry attempt by invoking the configured nextFunc. If no nextFunc is set, it returns the current interval as a fixed delay.
func (*BackoffInterval) Reset ¶
func (b *BackoffInterval) Reset()
Reset resets the backoff state to its initial configuration, allowing the backoff sequence to start anew. If no resetFunc is configured, this is a no-op.
func (*BackoffInterval) WithConfig ¶
func (b *BackoffInterval) WithConfig(config any) *BackoffInterval
WithConfig sets the configuration object for the BackoffInterval and returns the instance for chaining.
The config can be any type (e.g., *ExponentialConfig).
func (*BackoffInterval) WithNextFunc ¶
func (b *BackoffInterval) WithNextFunc(nextFunc NextFunc) *BackoffInterval
WithNextFunc sets the function that computes the next interval for the BackoffInterval and returns the instance for chaining.
func (*BackoffInterval) WithResetFunc ¶
func (b *BackoffInterval) WithResetFunc(resetFunc ResetFunc) *BackoffInterval
WithResetFunc sets the function that resets the BackoffInterval's state to its initial configuration and returns the instance for chaining.
func (*BackoffInterval) WithState ¶
func (b *BackoffInterval) WithState(state any) *BackoffInterval
WithState sets the state object for the BackoffInterval and returns the instance for chaining.
The state can be any type (e.g., *ExponentialState).
func (*BackoffInterval) WrapError ¶
func (b *BackoffInterval) WrapError(err error) error
WrapError wraps err with the current backoff interval using %w, so the original error remains inspectable via errors.Is/errors.As while the message carries how long the next retry will wait.
type DecorrelatedConfig ¶
DecorrelatedConfig holds configuration parameters for DecorrelatedNextFunc.
type DecorrelatedState ¶
type DecorrelatedState struct {
// contains filtered or unexported fields
}
DecorrelatedState tracks the runtime state of a Decorrelated Jitter sequence: the previous sleep value the recurrence is based on.
type ExponentialConfig ¶
type ExponentialConfig struct {
// Jitter determines whether to apply randomization to each interval.
Jitter bool
// JitterStrategy selects the randomization formula applied when Jitter is
// true. If nil, FullJitter is used.
JitterStrategy JitterFunc
// MaxAttempts is the number of attempts to use the maximum interval before
// resetting.
MaxAttempts int
// MaxInterval caps the maximum delay between retries.
MaxInterval time.Duration
// Multiplier is the factor by which the interval increases after each
// retry.
Multiplier float64
// Randomizer specifies the magnitude of jitter as a fraction of the
// interval (e.g., 0.25 means ±25%). Only consulted by PercentJitter.
Randomizer float64
}
ExponentialConfig holds configuration parameters for an exponential backoff strategy.
type ExponentialState ¶
type ExponentialState struct {
// Cycles counts the number of times the backoff sequence has reached maxed
// out attempts and reset.
Cycles int
// contains filtered or unexported fields
}
ExponentialState tracks the runtime state of an exponential backoff sequence.
type JitterFunc ¶
type JitterFunc func(interval time.Duration, config *ExponentialConfig) time.Duration
JitterFunc computes a jittered duration from the exponentially-ramped, already-capped interval. Implementations may consult config (e.g. Randomizer for PercentJitter) but must not mutate it.
type NextFunc ¶
type NextFunc func(*BackoffInterval) time.Duration
NextFunc defines a function that, given a BackoffInterval, computes and returns the next interval duration.
type ResetFunc ¶
type ResetFunc func(*BackoffInterval)
ResetFunc defines a function that, given a BackoffInterval, resets its internal state to the initial configuration.