backoff
A minimal exponential backoff counter for Go with optional jitter support.
Repository Health
Technical Analysis
backoff is a tiny, dependency-free Go package that implements the classic exponential backoff pattern as a simple time.Duration counter. It exposes a Backoff struct with Min, Max, and Factor fields; each call to Duration() returns the next wait interval, multiplying the previous value by Factor until it hits the Max ceiling, and Reset() returns the counter to Min. The entire implementation lives in a single ~100-line file with no external dependencies, making it easy to vendor, audit, or embed directly in retry loops for network calls, database reconnects, or any operation that needs a backoff before retrying.
The package also supports Jitter, which randomizes each returned duration between the previous value and the newly computed one to avoid thundering-herd retry storms across many clients — a technique documented in AWS’s architecture blog on backoff and jitter. A concurrency-safe ForAttempt(attempt) method lets callers compute the duration for a specific attempt number without maintaining per-instance state, useful when tracking many independent backoff counters would otherwise waste memory.
What You Get
- A Backoff struct with configurable Min, Max, and Factor duration bounds
- A Duration() method that returns the next backoff interval and advances the internal attempt counter
- Optional Jitter to randomize delays and avoid synchronized retry storms
- A concurrency-safe ForAttempt(attempt) method for stateless duration lookups
Common Use Cases
- Retrying TCP/network connections with an increasing delay between attempts
- Backing off HTTP client retries after failed requests to a flaky upstream service
- Reconnecting to a database or message queue after a dropped connection
- Rate-limiting retry attempts across many concurrent workers using jitter
Under The Hood
Architecture backoff is a single-file package (backoff.go) built around one exported type, Backoff, that deliberately splits stateful and stateless concerns: Duration() wraps an atomically-incremented uint64 attempt counter (via sync/atomic) and delegates the actual math to ForAttempt(attempt float64), a pure function of the struct’s Min/Max/Factor/Jitter fields. That split lets ForAttempt be called concurrently across many goroutines without a mutex, while Duration() still offers a simple stateful counter for the common case. There is no I/O, no external data flow, and no dependency injection — the whole surface area is five methods (Duration, ForAttempt, Reset, Attempt, Copy) on one struct, which is an appropriately minimal design for the problem it solves.
Tech Stack The package has zero external dependencies — go.mod declares only the module path and a Go 1.13 minimum, and the implementation imports solely from the standard library (math, math/rand, sync/atomic, time). Continuous integration runs via a single GitHub Actions workflow (.github/workflows/build.yml) that runs go test -v ./… against Go >=1.17 on every push and pull request to master. There is no build tooling beyond the standard go build/go test toolchain, which matches the package’s scope as a small importable utility rather than an application.
Code Quality backoff_test.go provides comprehensive coverage for a package this size: fixed backoff sequences at several factors, jitter bounds checking via a between() helper, Reset() behavior, Copy() equivalence, and a concurrent-access test that exercises Duration() from two goroutines simultaneously. Naming is idiomatic Go (exported PascalCase fields and methods, lowercase unexported attempt counter), and since the package performs no I/O or fallible operations, there is no error-handling surface to assess — every method is deterministic given its inputs. No linter configuration (e.g. golangci-lint) is present, but CI does enforce that tests pass on every change.
What Makes It Unique The package is not attempting anything novel — exponential backoff with jitter is a well-documented pattern, and comparable Go libraries exist (e.g. cenkalti/backoff offers more configurability, retry policies, and context support). backoff’s distinguishing trait is deliberate minimalism: zero dependencies, a single file, and a stateless ForAttempt escape hatch for memory-conscious use at scale — a narrow, well-executed take on a standard technique rather than an innovative one.
Used by 3 apps in this directory
Coroot
Analytics · Monitoring
eBPF-powered observability with AI root cause analysis — zero code changes required, full-stack visibility out of the box.
GitLab
Devops · Developer Tools
The complete DevOps platform that unifies Git hosting, CI/CD, issue tracking, and security scanning into a single self-hostable application.
PrivateCaptcha
Security · Authentication
Privacy-first, self-hostable Proof-of-Work CAPTCHA for GDPR-compliant bot protection.