backoff

package
v1.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 26, 2026 License: Apache-2.0 Imports: 2 Imported by: 0

Documentation

Overview

Package backoff provides shared utilities for exponential backoff calculations.

Design Decision: DD-SHARED-001 (to be created) Extracted from Notification service's production-proven implementation.

Business Requirements Enabled: - BR-WE-012: WorkflowExecution - Pre-execution Failure Backoff - BR-NOT-052: Notification - Automatic Retry with Custom Retry Policies - BR-NOT-055: Notification - Graceful Degradation (jitter for anti-thundering herd)

Usage Pattern:

// Flexible multiplier with jitter (Notification pattern)
config := backoff.Config{
    BasePeriod:    30 * time.Second,
    MaxPeriod:     5 * time.Minute,
    Multiplier:    2.0,      // 1.5=conservative, 2=standard, 3=aggressive
    JitterPercent: 10,       // ±10% variance (anti-thundering herd)
}
duration := config.Calculate(attempts)

Benefits: - Single source of truth for backoff calculation - Consistent behavior across all services - Prevents arithmetic errors in manual calculations - Industry best practice (jitter prevents thundering herd) - Flexible strategies (configurable multiplier) - Battle-tested (extracted from Notification v3.1)

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func CalculateWithDefaults

func CalculateWithDefaults(attempts int32) time.Duration

CalculateWithDefaults is a convenience function that uses sensible defaults:

  • BasePeriod: 30s
  • MaxPeriod: 5m
  • Multiplier: 2.0 (standard exponential)
  • JitterPercent: 10 (±10% variance, recommended for production)

This provides a production-ready backoff strategy with anti-thundering herd protection:

  • Attempt 1: ~30s (27-33s with jitter)
  • Attempt 2: ~1m (54-66s with jitter)
  • Attempt 3: ~2m (108-132s with jitter)
  • Attempt 4: ~4m (216-264s with jitter)
  • Attempt 5+: ~5m (270-330s with jitter, capped at 5m)

Use this for: Standard retry scenarios with external API calls or transient failures

func CalculateWithoutJitter

func CalculateWithoutJitter(attempts int32) time.Duration

CalculateWithoutJitter is a convenience function for deterministic backoff:

  • BasePeriod: 30s
  • MaxPeriod: 5m
  • Multiplier: 2.0 (standard exponential)
  • JitterPercent: 0 (no variance)

This provides deterministic backoff without jitter (useful for testing):

  • Attempt 1: 30s (exact)
  • Attempt 2: 1m (exact)
  • Attempt 3: 2m (exact)
  • Attempt 4: 4m (exact)
  • Attempt 5+: 5m (exact, capped)

Use this for: Testing, single-instance deployments, or when deterministic timing is required

Note: This maintains backward compatibility with WE's original implementation

Types

type Config

type Config struct {
	// BasePeriod is the initial backoff duration (e.g., 30s)
	// Formula: duration = BasePeriod * (Multiplier ^ (attempts-1))
	BasePeriod time.Duration

	// MaxPeriod caps the exponential backoff (e.g., 5m)
	// If zero, no cap is applied (not recommended)
	MaxPeriod time.Duration

	// Multiplier for exponential growth (default: 2.0)
	// - 1.5: Conservative (slower growth)
	// - 2.0: Standard exponential (power-of-2)
	// - 3.0: Aggressive (faster growth)
	// Range: 1.0-10.0
	// If zero, defaults to 2.0
	Multiplier float64

	// JitterPercent adds random variance to prevent thundering herd (default: 0)
	// - 0: No jitter (deterministic)
	// - 10: ±10% variance (recommended for production)
	// - 20: ±20% variance (aggressive anti-thundering herd)
	// Range: 0-50
	// Jitter distributes retry attempts over time, reducing API load spikes
	JitterPercent int
}

Config defines the exponential backoff parameters.

This configuration supports flexible backoff strategies with optional jitter to prevent thundering herd problems in distributed systems.

func (Config) Calculate

func (c Config) Calculate(attempts int32) time.Duration

Calculate computes the exponential backoff duration for a given number of attempts.

Formula: duration = BasePeriod * (Multiplier ^ (attempts-1)) With jitter: duration ± (duration * JitterPercent / 100) Capped by: MaxPeriod

Examples:

Standard (Multiplier=2, JitterPercent=0):
- attempts=1 → 30s (30 * 2^0)
- attempts=2 → 1m (30 * 2^1)
- attempts=3 → 2m (30 * 2^2)
- attempts=4 → 4m (30 * 2^3)
- attempts=5 → 5m (capped at MaxPeriod)

Conservative (Multiplier=1.5, JitterPercent=10):
- attempts=1 → 27-33s (30s ±10%)
- attempts=2 → 40-50s (45s ±10%)
- attempts=3 → 60-74s (67s ±10%)

Aggressive (Multiplier=3, JitterPercent=20):
- attempts=1 → 24-36s (30s ±20%)
- attempts=2 → 72-108s (90s ±20%)
- attempts=3 → 216-324s (270s ±20%)

Parameters:

  • attempts: The number of attempts made (1-based: first attempt = 1)

Returns:

  • time.Duration: The calculated backoff duration with optional jitter
  • If attempts < 1, returns BasePeriod
  • If BasePeriod is 0, returns 0

Implementation Notes:

  • Extracted from Notification service (lines 302-346 of notificationrequest_controller.go)
  • Jitter prevents thundering herd when many operations fail simultaneously
  • Multiplier enables flexible strategies (conservative/standard/aggressive)
  • Bounds checking ensures jitter never violates [BasePeriod, MaxPeriod] range

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL