autobreaker

package module
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Nov 10, 2025 License: MIT Imports: 1 Imported by: 0

README

AutoBreaker

CI Go Reference Go Report Card License

Adaptive circuit breaker for Go that automatically adjusts to your traffic patterns.

Why AutoBreaker?

Traditional circuit breakers use static thresholds (e.g., "trip after 10 failures"). This causes problems:

  • 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)
  • Configuration burden: Different thresholds needed for dev/staging/prod

AutoBreaker solves this by using percentage-based thresholds that adapt to request volume automatically.

Features

  • Adaptive Thresholds: Same config works across different traffic volumes
  • Runtime Configuration: Update settings without restart
  • Drop-in Replacement: Compatible with sony/gobreaker API
  • Zero Dependencies: Only standard library
  • High Performance: <100ns overhead per request
  • Rich Observability: Detailed metrics and insights built-in

Quick Start

package main

import (
    "github.com/vnykmshr/autobreaker"
    "fmt"
    "time"
)

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

    // Wrap your operation
    result, err := breaker.Execute(func() (interface{}, error) {
        return callExternalAPI()
    })

    if err != nil {
        fmt.Printf("Circuit breaker: %v\n", err)
        return
    }

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

⚠️ Performance Warning: User Callbacks

Critical: ReadyToTrip, OnStateChange, and IsSuccessful callbacks run synchronously on every request. Slow callbacks will block all traffic.

Requirements:

  • Keep callbacks <1μs (microsecond)
  • No I/O, network calls, or time.Sleep()
  • For slow work, spawn goroutines:
    OnStateChange: func(name string, from, to State) {
        go metrics.Record(name, from, to) // Async, non-blocking
    }
    

Why: Callbacks execute on the hot path. A 10ms callback = 10ms added to every request.

How It Works

AutoBreaker adapts failure thresholds as a percentage of recent requests instead of absolute counts:

Static:   "Trip after 10 failures in 10 seconds"
Problem:  At 100 RPS → 10 failures = 1% (too sensitive)
          At 10 RPS → 10 failures = 100% (too slow)

Adaptive: "Trip when error rate > 5% over 10 second window"
Behavior: At 100 RPS → trips at 50 failures
          At 10 RPS → trips at 5 failures
          ✓ Same config, right behavior

Installation

go get github.com/vnykmshr/autobreaker

Status

Production-Ready - v1.0.0

  • Adaptive thresholds with runtime configuration
  • 102 tests, 97.1% coverage, race-detector clean
  • <100ns overhead, zero allocations, zero dependencies
  • 9 production examples (HTTP, Prometheus, runtime config)
  • Full observability (Metrics, Diagnostics)

Examples

See comprehensive examples in the examples/ directory:

Run any example:

go run examples/production_ready/main.go
go run examples/runtime_config/main.go
go run examples/observability/main.go

Philosophy

AutoBreaker follows a lean approach:

  • ✅ Solve real problems (traffic-aware thresholds)
  • ✅ Simple, measurable improvements
  • ✅ Production-grade reliability
  • ❌ No AI bloat or unnecessary complexity
  • ❌ No external dependencies
  • ❌ No magic behavior

Roadmap

  • Phase 1: Core circuit breaker
  • Phase 2A: Adaptive thresholds
  • Phase 3A: Observability & metrics
  • Phase 4A: Runtime configuration
  • 🔍 Phase 4B/5: Feature requests - RFC: Sliding Windows, RFC: Middleware

Note: v1.0 may be feature-complete. Future phases depend on validated community demand.

License

MIT License - see LICENSE file for details.

Contributing

Contributions welcome! Please open an issue first to discuss proposed changes.

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