Skip to main content
Version: monitor_v0.x.x

Circuit Breaker

Release Discord Test

A Circuit Breaker is a software design pattern used to prevent system failures when a service is experiencing high failures or slow responses. It helps improve system resilience by stopping requests to an unhealthy service and allowing recovery once it stabilizes.

How It Works​

  1. Closed State:

    • Requests are allowed to pass normally.
    • Failures are counted.
    • If failures exceed a defined threshold, the circuit switches to Open state.
  2. Open State:

    • Requests are blocked immediately to prevent overload.
    • The circuit stays open for a timeout period before moving to Half-Open.
  3. Half-Open State:

    • Allows a limited number of requests to test service recovery.
    • If requests succeed, the circuit resets to Closed.
    • If requests fail, the circuit returns to Open.

Benefits of Using a Circuit Breaker​

✅ Prevents cascading failures in microservices.
✅ Improves system reliability by avoiding repeated failed requests.
✅ Reduces load on struggling services and allows recovery.

Install​

go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/circuitbreaker

Signature​

circuitbreaker.New(config ...circuitbreaker.Config) *circuitbreaker.Middleware

Config​

PropertyTypeDescriptionDefault
FailureThresholdintNumber of consecutive errors required to open the circuit5
Timeouttime.DurationTimeout for the circuit breaker10 * time.Second
SuccessThresholdintNumber of successful requests required to close the circuit5
HalfOpenMaxConcurrentintMax concurrent requests in half-open state1
IsFailurefunc(error) boolCustom function to determine if an error is a failureStatus >= 500
OnOpenfunc(*fiber.Ctx)Callback function when the circuit is opened503 response
OnClosefunc(*fiber.Ctx)Callback function when the circuit is closedContinue request
OnHalfOpenfunc(*fiber.Ctx)Callback function when the circuit is half-open429 response

Circuit Breaker Usage in Fiber (Example)​

This guide explains how to use a Circuit Breaker in a Fiber application at different levels, from basic setup to advanced customization.

1. Basic Setup​

A global Circuit Breaker protects all routes.

Example: Applying Circuit Breaker to All Routes

package main

import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/contrib/circuitbreaker"
)

func main() {
app := fiber.New()

// Create a new Circuit Breaker with custom configuration
cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3, // Max failures before opening the circuit
Timeout: 5 * time.Second, // Wait time before retrying
SuccessThreshold: 2, // Required successes to move back to closed state
})

// Apply Circuit Breaker to ALL routes
app.Use(circuitbreaker.Middleware(cb))

// Sample Route
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, world!")
})

// Optional: Expose health check endpoint
app.Get("/health/circuit", cb.HealthHandler())

// Optional: Expose metrics about the circuit breaker:
app.Get("/metrics/circuit", func(c *fiber.Ctx) error {
return c.JSON(cb.GetStateStats())
})

app.Listen(":3000")

// In your application shutdown logic
app.Shutdown(func() {
// Make sure to stop the circuit breaker when your application shuts down:
cb.Stop()
})
}

2. Route & Route-Group Specific Circuit Breaker​

Apply the Circuit Breaker only to specific routes.

app.Get("/protected", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
return c.SendString("Protected service running")
})

Apply the Circuit Breaker only to specific routes groups.

app := route.Group("/api")
app.Use(circuitbreaker.Middleware(cb))

// All routes in this group will be protected
app.Get("/users", getUsersHandler)
app.Post("/users", createUserHandler)

3. Circuit Breaker with Custom Failure Handling​

Customize the response when the circuit opens.

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3,
Timeout: 10 * time.Second,
OnOpen: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusServiceUnavailable).
JSON(fiber.Map{"error": "Circuit Open: Service unavailable"})
},
OnHalfOpen: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusTooManyRequests).
JSON(fiber.Map{"error": "Circuit Half-Open: Retrying service"})
},
OnClose: func(c *fiber.Ctx) error {
return c.Status(fiber.StatusOK).
JSON(fiber.Map{"message": "Circuit Closed: Service recovered"})
},
})

// Apply to a specific route
app.Get("/custom", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
return c.SendString("This service is protected by a Circuit Breaker")
})

✅ Now, when failures exceed the threshold, *custom error responses will be sent.

4. Circuit Breaker for External API Calls​

Use a Circuit Breaker when calling an external API.


app.Get("/external-api", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
// Simulating an external API call
resp, err := fiber.Get("https://example.com/api")
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "External API failed")
}
return c.SendString(resp.Body())
})

✅ If the external API fails repeatedly, the circuit breaker prevents further calls.

5. Circuit Breaker with Concurrent Requests Handling​

Use a semaphore-based approach to limit concurrent requests.

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 3,
Timeout: 5 * time.Second,
SuccessThreshold: 2,
HalfOpenSemaphore: make(chan struct{}, 2), // Allow only 2 concurrent requests
})

app.Get("/half-open-limit", circuitbreaker.Middleware(cb), func(c *fiber.Ctx) error {
time.Sleep(2 * time.Second) // Simulating slow response
return c.SendString("Half-Open: Limited concurrent requests")
})

✅ When in half-open state, only 2 concurrent requests are allowed.

6. Circuit Breaker with Custom Metrics​

Integrate Prometheus metrics and structured logging.

cb := circuitbreaker.New(circuitbreaker.Config{
FailureThreshold: 5,
Timeout: 10 * time.Second,
OnOpen: func(c *fiber.Ctx) error {
log.Println("Circuit Breaker Opened!")
prometheus.Inc("circuit_breaker_open_count")
return c.Status(fiber.StatusServiceUnavailable).JSON(fiber.Map{"error": "Service Down"})
},
})

✅ Logs when the circuit opens & increments Prometheus metrics.

7. Advanced: Multiple Circuit Breakers for Different Services​

Use different Circuit Breakers for different services.


dbCB := circuitbreaker.New(circuitbreaker.Config{FailureThreshold: 5, Timeout: 10 * time.Second})
apiCB := circuitbreaker.New(circuitbreaker.Config{FailureThreshold: 3, Timeout: 5 * time.Second})

app.Get("/db-service", circuitbreaker.Middleware(dbCB), func(c *fiber.Ctx) error {
return c.SendString("DB service request")
})

app.Get("/api-service", circuitbreaker.Middleware(apiCB), func(c *fiber.Ctx) error {
return c.SendString("External API service request")
})

✅ Each service has its own failure threshold & timeout.