Skip to Content

Resilience

The resilience package provides fault-tolerance patterns including circuit breakers and retry with exponential backoff. It uses failsafe-go  under the hood. All patterns are plain Go functions — no decorators or middleware wrappers.

Import

import "github.com/gofastadev/gofasta/pkg/resilience"

Key Functions

FunctionSignatureDescription
NewRetryPolicyfunc NewRetryPolicy[T any](maxRetries int, delay time.Duration) retrypolicy.RetryPolicy[T]Creates a retry policy with exponential backoff
NewCircuitBreakerfunc NewCircuitBreaker[T any](failureThreshold uint, delay time.Duration) circuitbreaker.CircuitBreaker[T]Creates a circuit breaker that opens after a failure threshold
Executefunc Execute[T any](fn func() (T, error), policies ...failsafe.Policy[T]) (T, error)Runs a function with the given failsafe policies

Usage

Retry with Exponential Backoff

retryPolicy := resilience.NewRetryPolicy[*http.Response](3, 100*time.Millisecond) resp, err := resilience.Execute(func() (*http.Response, error) { return externalAPI.Call(ctx, payload) }, retryPolicy)

The retry policy uses exponential backoff from delay up to delay * 10. For example, with a 100ms delay: 100ms, 200ms, 400ms, etc., capped at 1s.

Circuit Breaker

cb := resilience.NewCircuitBreaker[*PaymentResult](5, 30*time.Second) result, err := resilience.Execute(func() (*PaymentResult, error) { return paymentClient.Charge(ctx, amount) }, cb) if err != nil { // Circuit may be open -- handle gracefully return err }

The circuit breaker opens after failureThreshold consecutive failures and stays open for delay before transitioning to half-open.

Combining Policies

You can compose retry and circuit breaker policies together. Policies are applied in order — the innermost policy (last argument) wraps the function first.

retryPolicy := resilience.NewRetryPolicy[*PaymentResult](3, 200*time.Millisecond) cb := resilience.NewCircuitBreaker[*PaymentResult](5, 30*time.Second) result, err := resilience.Execute(func() (*PaymentResult, error) { return paymentClient.Charge(ctx, amount) }, cb, retryPolicy)

Using in a Service

func (s *PaymentService) Charge(ctx context.Context, amount float64) (*PaymentResult, error) { return resilience.Execute(func() (*PaymentResult, error) { return s.paymentClient.Charge(ctx, amount) }, s.circuitBreaker, s.retryPolicy) }
  • Queue — Retry policies for queued jobs
  • Health — Health checks reflect circuit breaker states
  • Observability — Track resilience metrics
Last updated on