relay
A small, dependency-free HTTP client wrapper for Go that adds retries, timeouts, and circuit breaking around the standard library.
relay wraps *http.Transport and the standard
net/http client with the three resilience patterns most
services need when calling other services: bounded retries with backoff,
per-attempt and total timeouts, and a circuit breaker that stops hammering a
failing upstream. It does not introduce a new request type, a new context
model, or a custom logging framework — you keep using
*http.Request and context.Context.
Why relay
Retries with backoff
Bounded attempts with exponential backoff and full jitter. You decide which responses and errors are retryable.
Two layers of timeout
A per-attempt deadline keeps a single slow call from eating the whole budget, while the parent context bounds the total.
Circuit breaking
A per-client breaker trips after repeated failures and recovers through a half-open probe, shedding load fast.
Standard library only
No third-party dependencies. The wrapped transport stays a plain
http.RoundTripper you can swap out.
Install
Requires Go 1.21 or newer.
go get relay.example/relay@latest
Then import it:
import "relay.example/relay"
Quick start
Construct a client once, reuse it everywhere. A relay.Client is
safe for concurrent use.
package main
import (
"context"
"fmt"
"io"
"log"
"time"
"relay.example/relay"
)
func main() {
client := relay.New(
relay.WithTimeout(2*time.Second),
relay.WithRetry(relay.RetryPolicy{
MaxAttempts: 4,
RetryOn: relay.RetryIdempotent,
}),
relay.WithCircuitBreaker(relay.BreakerConfig{
FailureThreshold: 5,
OpenTimeout: 10 * time.Second,
}),
)
ctx, cancel := context.WithTimeout(context.Background(), 8*time.Second)
defer cancel()
resp, err := client.Get(ctx, "http://service.internal/health")
if err != nil {
log.Fatalf("request failed: %v", err)
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Printf("%d: %s\n", resp.StatusCode, body)
}
From here:
- Getting started — install, first request, and how the pieces fit.
- Configuration — every option explained, with defaults.
- API reference — types, functions, and errors.
- Examples — common patterns copied from real use.