backoff
Exponential backoff and retry for Go, with a generic Retry function, typed errors, and RetryAfter support for rate-limited APIs.
Repository Health
Technical Analysis
backoff is a Go library implementing the exponential backoff algorithm ported from Google’s HTTP Client Library for Java. It exposes a generic Retry[T any] function that wraps any fallible operation, retrying it with a randomized exponential delay until it succeeds, returns a permanent error, or a configurable limit is reached.
Version 7 layers on typed error introspection via *RetryError (carrying both the last operation error and the reason retrying stopped), a RetryAfter mechanism for honoring server-specified retry delays (e.g. HTTP 429 Retry-After headers), and independent limits for context cancellation, max tries, and max elapsed time — all implemented with zero external dependencies.
What You Get
- Generic
Retry[T any]function that retries any typed operation with exponential backoff, context support, max-tries and max-elapsed-time limits *RetryErrorwithLastErrandCausefields, inspectable viaerrors.Is/errors.Asor theAsRetryErrorhelperPermanent(err)to stop retrying immediately on non-transient errorsRetryAfter(duration, cause)to honor server-specified delays (e.g. HTTP 429Retry-After) and reset the backoff schedule- Pluggable
BackOffinterface withExponentialBackOff,ConstantBackOff,ZeroBackOff, andStopBackOffimplementations Tickertype for channel-based retry loops outside ofRetry
Common Use Cases
- Resilient HTTP clients - wrap outbound API calls in Retry so transient 5xx errors and network blips are retried automatically while 4xx client errors stop immediately via Permanent
- Rate-limit-aware API integrations - return RetryAfter from an operation when a downstream service responds with a Retry-After header, so the client waits the server-requested duration before retrying
- Bounded background job retries - combine WithMaxTries and WithMaxElapsedTime to cap how long a background task keeps retrying before giving up and surfacing a typed ErrExhausted or ErrMaxElapsedTime cause
- Custom retry loops - use Ticker directly when you need a channel of retry ticks instead of a blocking Retry call, for integrating backoff timing into existing select-based control flow
Under The Hood
Architecture The package is a flat, single-directory Go module with each file owning one concern: backoff.go defines the BackOff interface and the trivial ZeroBackOff/StopBackOff/ConstantBackOff policies, exponential.go implements ExponentialBackOff’s randomized-interval formula, retry.go layers the generic Retry[T any] orchestration (context handling, MaxTries, MaxElapsedTime, RetryAfter, Permanent) on top of any BackOff, error.go defines the RetryError/RetryAfterError error types and sentinel causes, and ticker.go/timer.go provide a channel-based alternative to Retry plus an internal timer abstraction that keeps the package testable without real sleeps. Nothing in Retry depends on ExponentialBackOff directly — it only requires the BackOff interface — so swapping in a custom policy changes no other code.
Tech Stack The module (github.com/cenkalti/backoff/v7, go.mod targets Go 1.23) has zero third-party dependencies, relying entirely on the standard library: context for cancellation, errors for Is/As-based error chains, math/rand/v2 for jittered intervals, sync for the Ticker’s stop-once semantics, and time throughout. Retry’s use of Go generics (Operation[T any]) lets callers get back a strongly typed result instead of an any that needs a type assertion, a change introduced in the v5-v7 rewrites documented in CHANGELOG.md.
Code Quality Testing is extensive and table-driven: retry_test.go alone runs to nearly 600 lines covering permanent errors, RetryAfter resets, context cancellation races, and max-tries/max-elapsed-time interactions, with additional dedicated suites for the ticker, exponential formula, and tries counter. Error handling is explicit and typed throughout — RetryError implements Unwrap() []error so both Cause and LastErr participate in errors.Is/errors.As chains — and naming is consistent with Go conventions. A GitHub Actions workflow (.github/workflows/go.yaml) runs the test suite in CI, and doc comments are dense enough to double as the package’s primary documentation.
What Makes It Unique The library doesn’t reinvent exponential backoff — the algorithm is the well-known jittered-multiplicative one ported from Google’s Java HTTP client — but its v6/v7 API design is notably deliberate about failure introspection: every Retry failure surfaces through one RetryError type that separates “what failed” (LastErr) from “why retrying stopped” (Cause), and RetryAfter lets an operation hand the scheduler a server-dictated delay without abandoning the surrounding backoff state. The CHANGELOG shows this API was iterated through several breaking major versions specifically to make error handling less ambiguous, rather than adding new backoff algorithms.
Used by 2 apps in this directory
Bytebase
Devops
An open-source database CI/CD and DevSecOps platform — schema migration review, GitOps-driven changes, data masking, and access control across MySQL, PostgreSQL, Oracle, Snowflake, MongoDB, and more.
CubeSandbox
Developer Tools · Security · AI Agents
Instant, concurrent, hardware-isolated MicroVM sandboxes for AI agents — E2B-API compatible, sub-60ms cold starts, and a built-in zero-trust egress proxy, all self-hostable at scale.