Skip to content

Circuit Breaker Best Practices — Complete Implementation Guide

DodaTech Updated 2026-06-28 6 min read

In this tutorial, you will learn about Circuit Breaker Best Practices. We cover key concepts, practical examples, and best practices to help you master this topic.

Circuit breaker best practices help you avoid common pitfalls in production deployments by establishing threshold guidelines, error classification rules, monitoring practices, and integration patterns.

What You'll Learn

By the end of this tutorial, you will know the industry-standard best practices for configuring, deploying, and maintaining circuit breakers in production systems.

Why It Matters

Getting circuit breaker configuration wrong creates more problems than it solves. Best practices prevent the most common failure modes and ensure your circuit breakers actually improve resilience.

Real-World Use

DodaTech's platform team maintains a circuit breaker standard that every microservice must follow, including threshold ranges, logging requirements, and monitoring dashboard integration.

Best Practices Learning Path

flowchart LR
  A[Performance Tuning] --> B[Best Practices]
  B --> C[Threshold Guidelines]
  B --> D[Error Classification]
  B --> E[Monitoring]
  B --> F{You Are Here}
  style F fill:#f90,color:#fff

Threshold Configuration Guidelines

Choosing the right failure threshold and reset timeout depends on your service's normal failure rate and recovery time.

class ConfigurableCircuit {
  constructor(options = {}) {
    this.failureThreshold = options.failureThreshold || 5;
    this.successThreshold = options.successThreshold || 2;
    this.resetTimeout = options.resetTimeout || 30000;
    this.errorType = options.errorType || "all";
    this.state = "closed";
    this.failureCount = 0;
    this.successCount = 0;
  }

  get recommendedSettings() {
    return {
      "high-volume-api": { failureThreshold: 10, resetTimeout: 15000 },
      "database-connection": { failureThreshold: 3, resetTimeout: 60000 },
      "third-party-api": { failureThreshold: 5, resetTimeout: 30000 },
      "file-processing": { failureThreshold: 2, resetTimeout: 120000 }
    };
  }
}

const dbCircuit = new ConfigurableCircuit({
  failureThreshold: 3,
  resetTimeout: 60000,
  errorType: "timeout"
});
console.log("DB circuit threshold:", dbCircuit.failureThreshold);
console.log("DB circuit timeout:", dbCircuit.resetTimeout);
// DB circuit threshold: 3
// DB circuit timeout: 60000

Classifying Errors Correctly

Not all errors should open the circuit. Classify errors into those that indicate systemic failure and those that don't.

class ErrorClassifier {
  static isSystemic(error) {
    const systemicErrors = [
      "ECONNREFUSED",
      "ECONNRESET",
      "ETIMEDOUT",
      "ESOCKETTIMEDOUT",
      "EAI_AGAIN"
    ];
    return systemicErrors.includes(error.code);
  }

  static isClientError(error) {
    return error.statusCode >= 400 && error.statusCode < 500;
  }

  static shouldTripCircuit(error) {
    if (this.isClientError(error)) return false;
    if (this.isSystemic(error)) return true;
    return error.statusCode >= 500;
  }
}

const errors = [
  { code: "ECONNREFUSED", statusCode: 0 },
  { code: "ERR_HTTP_REQUEST", statusCode: 400 },
  { code: "ERR_HTTP_REQUEST", statusCode: 503 }
];

errors.forEach(err => {
  console.log(
    "Error:", err.code, err.statusCode,
    "-> Trip circuit:", ErrorClassifier.shouldTripCircuit(err)
  );
});
// Error: ECONNREFUSED 0 -> Trip circuit: true
// Error: ERR_HTTP_REQUEST 400 -> Trip circuit: false
// Error: ERR_HTTP_REQUEST 503 -> Trip circuit: true

Logging and Monitoring Integration

Every state transition must be logged and every open event must trigger an alert.

class ObservableCircuitBreaker {
  constructor(options = {}) {
    this.threshold = options.threshold || 5;
    this.resetTimeout = options.resetTimeout || 30000;
    this.state = "closed";
    this.failureCount = 0;
    this.listeners = new Map();
  }

  on(event, callback) {
    if (!this.listeners.has(event)) {
      this.listeners.set(event, []);
    }
    this.listeners.get(event).push(callback);
  }

  emit(event, data) {
    const callbacks = this.listeners.get(event) || [];
    callbacks.forEach(cb => cb(data));
  }

  transitionTo(newState) {
    const oldState = this.state;
    this.state = newState;
    this.emit("stateChange", { from: oldState, to: newState, time: new Date() });
  }
}

const cb = new ObservableCircuitBreaker();
cb.on("stateChange", event => {
  console.log("ALERT: Circuit", event.from, "->", event.to, "at", event.time);
});
cb.transitionTo("open");
cb.transitionTo("half-open");
cb.transitionTo("closed");
// ALERT: Circuit closed -> open at ...
// ALERT: Circuit open -> half-open at ...
// ALERT: Circuit half-open -> closed at ...

Common Mistakes

  1. Using the same threshold for all services -- Each downstream service has different reliability characteristics. A third-party API might need a threshold of 10 while a database connection needs 3.

  2. Not classifying errors before counting -- Treating 400 Bad Request the same as 503 Service Unavailable opens the circuit on client mistakes. Only count server-side and network errors.

  3. Setting reset timeout too short -- A 5-second timeout causes rapid open-close cycling (thrashing). Minimum recommended is 15 seconds for APIs, 60 seconds for databases.

  4. Forgetting to integrate with health checks -- When the circuit is open, the health check endpoint should report degraded status so load balancers and orchestrators react appropriately.

  5. Not having a fallback Strategy -- Opening the circuit without a fallback means users see errors. Always provide a cached response, default value, or degraded experience.

Practice Questions

  1. What is the recommended reset timeout range for API circuit breakers? 15-30 seconds. Long enough for transient issues to clear, short enough to minimize downtime.

  2. Why should client errors (4xx) not open the circuit? Client errors indicate a problem with the request, not the service. Opening the circuit doesn't fix bad requests and masks the real issue.

  3. What should you do when the circuit opens? Log the transition, trigger an alert, mark the health check as degraded, serve fallback responses, and investigate the downstream service.

  4. Challenge: Implement a circuit breaker that uses different thresholds for different error types.

class MultiThresholdCircuitBreaker {
  constructor(configs) {
    this.configs = configs;
    this.counts = {};
    this.state = "closed";
    for (const type of Object.keys(configs)) {
      this.counts[type] = 0;
    }
  }

  record(errorType) {
    if (!this.counts[errorType]) return;
    this.counts[errorType]++;
    const config = this.configs[errorType];
    if (this.counts[errorType] >= config.threshold) {
      this.state = "open";
      console.log("Circuit opened by", errorType, "errors");
    }
  }
}

const cb = new MultiThresholdCircuitBreaker({
  timeout: { threshold: 3 },
  connection: { threshold: 2 },
  serverError: { threshold: 5 }
});

cb.record("timeout");
cb.record("timeout");
cb.record("connection");
console.log("State:", cb.state);
cb.record("connection");
console.log("State:", cb.state);
// State: closed
// State: open

FAQ

How do I choose the initial threshold value?

Start with 5 failures in 30 seconds for APIs, 3 failures in 60 seconds for databases. Adjust based on observed failure rates in production.

Should circuit breakers be used for internal service calls?

Yes. Internal microservice calls benefit from circuit breakers just as much as external API calls. Internal services can fail too.

How do I handle authentication services with circuit breakers?

Auth services need special care. Opening the circuit to an auth service blocks all authenticated requests. Use a separate, more conservative circuit or a cached auth token fallback.

What metrics should I track for each circuit breaker?

Track: current state, failure count, request count, last transition time, total open duration, and fallback invocation count.

How often should I review circuit breaker configuration?

Review during every incident post-mortem and at least quarterly. Adjust thresholds based on observed behavior.

Mini Project

Build a circuit breaker configuration validator that checks for common misconfigurations and suggests optimal values based on the service type and historical data.

class ConfigValidator {
  static validate(config, serviceType) {
    const issues = [];

    if (config.failureThreshold < 2) {
      issues.push("Failure threshold too low: circuit opens too easily");
    }
    if (config.failureThreshold > 20) {
      issues.push("Failure threshold too high: circuit may never open");
    }
    if (config.resetTimeout < 10000) {
      issues.push("Reset timeout too short: risk of thrashing");
    }
    if (config.resetTimeout > 300000) {
      issues.push("Reset timeout too long: extended downtime");
    }
    if (!config.errorTypes || config.errorTypes.length === 0) {
      issues.push("No error type classification: may open on client errors");
    }

    return {
      valid: issues.length === 0,
      issues,
      recommendations: this.getRecommendations(serviceType)
    };
  }

  static getRecommendations(serviceType) {
    const recs = {
      api: { failureThreshold: 5, resetTimeout: 30000 },
      database: { failureThreshold: 3, resetTimeout: 60000 },
      "message-queue": { failureThreshold: 10, resetTimeout: 15000 }
    };
    return recs[serviceType] || recs.api;
  }
}

const result = ConfigValidator.validate(
  { failureThreshold: 25, resetTimeout: 5000, errorTypes: [] },
  "api"
);

console.log("Valid:", result.valid);
result.issues.forEach(i => console.log("-", i));
// Valid: false
// - Failure threshold too high: circuit may never open
// - Reset timeout too short: risk of thrashing
// - No error type classification: may open on client errors

What's Next

Now that you understand best practices, learn how to implement circuit breakers with Spring Boot using Resilience4j. Then build the complete circuit breaker project to apply everything you've learned.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro