autobreaker

package module
v1.1.2 Latest Latest
Warning

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

Go to latest
Published: Feb 15, 2026 License: MIT Imports: 1 Imported by: 0

README

AutoBreaker

Adaptive circuit breaker for Go with percentage-based thresholds that automatically adjust to traffic patterns.

CI Go Reference Go Report Card License Documentation

Overview

Traditional circuit breakers use static failure thresholds (e.g., "trip after 10 failures"). This creates problems: at high traffic, 10 failures may represent <1% error rate (too sensitive), while at low traffic, 10 failures may be 100% error rate (too slow to protect).

AutoBreaker uses percentage-based thresholds that adapt to request volume automatically. Configure once, works correctly across all traffic levels and environments.

Features:

  • Adaptive Thresholds - Percentage-based failure detection scales with traffic
  • Runtime Configuration - Update settings without restart
  • Zero Dependencies - Standard library only
  • High Performance - <100ns overhead per request, zero allocations
  • Observability - Metrics() and Diagnostics() APIs built-in
  • Thread-Safe - Lock-free atomic operations throughout

Installation

go get github.com/1mb-dev/autobreaker

Requires Go 1.21 or later.

Quick Start

package main

import (
    "fmt"
    "time"
    "github.com/1mb-dev/autobreaker"
)

func main() {
    breaker := autobreaker.New(autobreaker.Settings{
        Name:    "api-client",
        Timeout: 10 * time.Second,
    })

    result, err := breaker.Execute(func() (interface{}, error) {
        return httpClient.Get("https://api.example.com/data")
    })

    if err == autobreaker.ErrOpenState {
        fmt.Println("Circuit open, using fallback")
        return
    }

    fmt.Printf("Result: %v\n", result)
}

Documentation

📚 Complete documentation available at: 1mb-dev.github.io/autobreaker/

The documentation includes:

  • Getting Started - Installation, basic usage, configuration
  • Guides - Architecture, state machine, concurrency, error classification, performance, decision guide
  • Migration - From sony/gobreaker
  • API Reference - Complete API documentation
  • Examples - Production-ready code examples

Basic Configuration

breaker := autobreaker.New(autobreaker.Settings{
    Name:    "service-name",
    Timeout: 30 * time.Second, // Open → HalfOpen transition time
})

Default behavior uses adaptive thresholds (5% failure rate, minimum 20 observations).

For advanced configuration, runtime updates, and complete settings reference, see the Configuration Guide.

How It Works

AutoBreaker calculates failure rate as a percentage of recent requests:

Adaptive: "Trip when error rate > 5%"

At 100 RPS → trips at 50 failures (5% of 1000 req/10s)
At 10 RPS  → trips at 5 failures  (5% of 100 req/10s)

Same config, correct behavior at any traffic level.

The implementation uses a three-state machine (Closed → Open → HalfOpen → Closed) with lock-free atomic operations for minimal overhead.

Performance

Benchmarks (Go 1.21, Apple M1):

Operation Latency Allocations
Execute (Closed) 78.5 ns 0 allocs
Execute (Open) 0.34 ns 0 allocs
UpdateSettings() 89.2 ns 0 allocs

See Performance Guide for detailed analysis.

Examples

Production-ready examples in examples/:

Run examples:

go run examples/production_ready/main.go

Important Notes

Callback Performance: ReadyToTrip, OnStateChange, and IsSuccessful callbacks execute synchronously on every request. Keep them <1μs. Use goroutines for slow operations:

OnStateChange: func(name string, from, to State) {
    go metrics.Record(name, from, to) // Async, non-blocking
}

Compatibility: Drop-in replacement for sony/gobreaker API. Enable adaptive thresholds with AdaptiveThreshold: true.

Status

Production-Ready - v1.1.1

  • 102 tests, 97.1% coverage, race detector clean
  • Zero dependencies, zero allocations in hot path
  • Compatible with Go 1.21+

See Roadmap for future plans.

License

MIT License - see LICENSE file.

Contributing

Contributions welcome! Please open an issue to discuss changes before submitting PRs.

See .github/CONTRIBUTING.md for guidelines.

Documentation

Overview

Package autobreaker provides an adaptive circuit breaker for Go that automatically adjusts failure thresholds based on traffic patterns.

Overview

AutoBreaker implements the circuit breaker pattern with automatic adaptation to request volume. Unlike traditional circuit breakers that use static failure thresholds (e.g., "trip after 10 failures"), AutoBreaker uses percentage-based thresholds that work across different traffic levels without manual tuning.

The Problem

Traditional circuit breakers use absolute failure counts:

  • At high traffic: 10 failures might be <1% error rate (too sensitive, false positives)
  • At low traffic: 10 failures might be 100% error rate (too slow to protect)
  • Different environments need different thresholds (dev/staging/prod)

The Solution

AutoBreaker uses percentage-based thresholds:

  • Same configuration works across 10x+ traffic variance
  • Automatically adapts: at 100 RPS, 5% threshold = 50 failures/10s
  • Automatically adapts: at 10 RPS, 5% threshold = 5 failures/10s
  • One config for all environments

Quick Start

Create a circuit breaker with adaptive thresholds:

breaker := autobreaker.New(autobreaker.Settings{
    Name:                 "api-client",
    Timeout:              10 * time.Second,
    AdaptiveThreshold:    true,
    FailureRateThreshold: 0.05, // 5% failure rate trips circuit
    MinimumObservations:  20,   // Require 20 requests before adapting
})

Wrap operations with the circuit breaker:

result, err := breaker.Execute(func() (interface{}, error) {
    return externalService.Call()
})
if err == autobreaker.ErrOpenState {
    // Circuit is open, fail fast
    return nil, err
}

Key Features

  • Adaptive Thresholds: Percentage-based thresholds adapt to traffic volume
  • Runtime Configuration: Update settings without restart via UpdateSettings()
  • Rich Observability: Metrics() and Diagnostics() APIs for monitoring
  • Zero Dependencies: Only standard library
  • High Performance: <100ns overhead per request, lock-free design
  • Thread-Safe: All methods safe for concurrent use
  • Drop-in Replacement: Compatible with sony/gobreaker API

Circuit States

The circuit breaker operates in three states:

  • Closed: Normal operation, requests pass through, failures are counted
  • Open: Circuit has tripped, requests fail fast with ErrOpenState
  • HalfOpen: Testing recovery, limited requests probe backend health

State transitions:

  • Closed → Open: When failure rate exceeds threshold
  • Open → HalfOpen: After timeout duration expires
  • HalfOpen → Closed: When probe requests succeed (recovery detected)
  • HalfOpen → Open: When probe requests fail (still unhealthy)

Observability

Monitor circuit breaker state and behavior:

// Real-time metrics
metrics := breaker.Metrics()
fmt.Printf("State: %s, Failure Rate: %.2f%%\n",
    metrics.State, metrics.FailureRate*100)

// Comprehensive diagnostics
diag := breaker.Diagnostics()
if diag.WillTripNext {
    log.Warn("Circuit about to trip!")
}

Runtime Configuration

Update settings without restarting:

err := breaker.UpdateSettings(autobreaker.SettingsUpdate{
    FailureRateThreshold: autobreaker.Float64Ptr(0.10), // Increase to 10%
    Timeout:              autobreaker.DurationPtr(30 * time.Second),
})

All updates are validated and applied atomically. Settings updates are thread-safe and can be called concurrently with Execute().

Thread Safety

All CircuitBreaker methods are safe for concurrent use:

  • Execute() can be called from multiple goroutines simultaneously
  • UpdateSettings() can be called concurrently with Execute()
  • State(), Counts(), Metrics(), Diagnostics() are thread-safe accessors
  • No external synchronization required

The implementation uses lock-free atomic operations for optimal performance.

Performance

  • Execute() overhead: <100ns per request (in Closed state)
  • Zero allocations in hot path
  • Lock-free design, no contention
  • Scales linearly with concurrent requests

Examples

See the examples/ directory for comprehensive usage examples:

  • examples/basic/ - Fundamental circuit breaker patterns
  • examples/adaptive/ - Adaptive vs static threshold comparison
  • examples/observability/ - Monitoring and diagnostics
  • examples/runtime_config/ - Runtime configuration updates
  • examples/prometheus/ - Prometheus integration
  • examples/production_ready/ - Production deployment patterns

Error Handling

Circuit breaker errors:

  • ErrOpenState: Circuit is open, request rejected (fail fast)
  • ErrTooManyRequests: Too many concurrent requests in half-open state

Application errors are passed through unchanged. Use the IsSuccessful callback to customize which errors count as failures:

breaker := autobreaker.New(autobreaker.Settings{
    IsSuccessful: func(err error) bool {
        // 4xx client errors don't indicate service failure
        return err == nil || isClientError(err)
    },
})

Best Practices

  • Use adaptive thresholds for services with variable traffic
  • Set MinimumObservations to prevent false positives at low traffic
  • Monitor with Metrics() for dashboards and alerts
  • Use Diagnostics() for troubleshooting and incident response
  • Update settings via UpdateSettings() for dynamic tuning
  • Set appropriate Timeout based on service recovery characteristics

Compatibility

AutoBreaker is compatible with sony/gobreaker API for easy migration:

// sony/gobreaker
breaker := gobreaker.NewCircuitBreaker(gobreaker.Settings{
    Name: "api",
})

// autobreaker (drop-in replacement)
breaker := autobreaker.New(autobreaker.Settings{
    Name: "api",
})

Enable adaptive thresholds by setting AdaptiveThreshold: true.

Index

Constants

View Source
const (
	// StateClosed indicates the circuit is closed (normal operation).
	// Requests pass through and failures are counted. If the failure rate
	// exceeds the threshold, the circuit transitions to Open.
	StateClosed = breaker.StateClosed

	// StateOpen indicates the circuit is open (failed state).
	// All requests are rejected immediately with ErrOpenState to prevent
	// cascading failures. After the timeout period, the circuit transitions
	// to HalfOpen to test recovery.
	StateOpen = breaker.StateOpen

	// StateHalfOpen indicates the circuit is testing recovery.
	// A limited number of requests (MaxRequests) are allowed to probe the
	// backend. If they succeed, the circuit closes. If they fail, the circuit
	// reopens.
	StateHalfOpen = breaker.StateHalfOpen
)

Variables

View Source
var (
	// ErrOpenState is returned when Execute() is called but the circuit breaker
	// is in the Open state. This indicates fail-fast behavior to prevent
	// cascading failures. The application should handle this error gracefully,
	// typically by returning a cached response or degraded service.
	ErrOpenState = breaker.ErrOpenState

	// ErrTooManyRequests is returned when too many concurrent requests are
	// attempted in the HalfOpen state. The circuit breaker limits concurrent
	// requests during recovery testing (controlled by MaxRequests setting).
	// This error indicates the circuit is testing recovery and additional
	// concurrent requests should wait or fail fast.
	ErrTooManyRequests = breaker.ErrTooManyRequests
)
View Source
var DurationPtr = breaker.DurationPtr

DurationPtr returns a pointer to the given time.Duration value. Helper function for constructing SettingsUpdate with explicit values.

Example:

breaker.UpdateSettings(autobreaker.SettingsUpdate{
    Timeout: autobreaker.DurationPtr(30 * time.Second),
})
View Source
var Float64Ptr = breaker.Float64Ptr

Float64Ptr returns a pointer to the given float64 value. Helper function for constructing SettingsUpdate with explicit values.

Example:

breaker.UpdateSettings(autobreaker.SettingsUpdate{
    FailureRateThreshold: autobreaker.Float64Ptr(0.10),
})
View Source
var New = breaker.New

New creates a new CircuitBreaker with the given settings.

Settings are validated at creation time. Invalid settings will cause a panic. See Settings type for configuration options and defaults.

Example:

breaker := autobreaker.New(autobreaker.Settings{
    Name:                 "api-client",
    Timeout:              10 * time.Second,
    AdaptiveThreshold:    true,
    FailureRateThreshold: 0.05,
    MinimumObservations:  20,
})

The returned CircuitBreaker is ready to use and thread-safe.

View Source
var Uint32Ptr = breaker.Uint32Ptr

Uint32Ptr returns a pointer to the given uint32 value. Helper function for constructing SettingsUpdate with explicit values.

Example:

breaker.UpdateSettings(autobreaker.SettingsUpdate{
    MaxRequests: autobreaker.Uint32Ptr(10),
})

Functions

This section is empty.

Types

type CircuitBreaker

type CircuitBreaker = breaker.CircuitBreaker

CircuitBreaker is the main type that implements the circuit breaker pattern with adaptive thresholds. See the internal/breaker package for implementation details.

All methods are thread-safe and can be called concurrently.

type Counts

type Counts = breaker.Counts

Counts holds statistics about requests processed by the circuit breaker. Returned by the Counts() method.

type Diagnostics

type Diagnostics = breaker.Diagnostics

Diagnostics provides comprehensive diagnostic information about the circuit breaker. Returned by the Diagnostics() method. Useful for troubleshooting and debugging.

See internal/breaker.Diagnostics for detailed field documentation.

type Metrics

type Metrics = breaker.Metrics

Metrics provides real-time metrics about the circuit breaker state and behavior. Returned by the Metrics() method. Useful for monitoring and dashboards.

See internal/breaker.Metrics for detailed field documentation.

type Settings

type Settings = breaker.Settings

Settings configures a circuit breaker instance. Passed to New() to create a circuit breaker.

See internal/breaker.Settings for detailed field documentation.

type SettingsUpdate

type SettingsUpdate = breaker.SettingsUpdate

SettingsUpdate specifies runtime configuration updates. Used with UpdateSettings() to modify circuit breaker settings without restarting.

Fields set to nil will not be updated. Non-nil fields will update the corresponding setting. See internal/breaker.SettingsUpdate for detailed field documentation.

type State

type State = breaker.State

State represents the current state of the circuit breaker. Valid states are StateClosed, StateOpen, and StateHalfOpen.

Directories

Path Synopsis
examples
adaptive command
Package main demonstrates adaptive threshold usage.
Package main demonstrates adaptive threshold usage.
basic command
Package main demonstrates basic usage of AutoBreaker.
Package main demonstrates basic usage of AutoBreaker.
custom_errors command
Package main demonstrates custom error classification.
Package main demonstrates custom error classification.
http_client command
Package main demonstrates circuit breaker integration with HTTP clients.
Package main demonstrates circuit breaker integration with HTTP clients.
http_server command
Package main demonstrates circuit breaker integration with HTTP servers.
Package main demonstrates circuit breaker integration with HTTP servers.
internal

Jump to

Keyboard shortcuts

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