Problems occur when you take things for granted. You cannot assume the network never fails. Sometimes there are latencies and crashes.
Even cloud-based systems can fail.
You often make remote calls to get data from reusable APIs nowadays. This non-monolithic architecture has become very popular.
It's a better experience for front-end developers. They don't have to dive into a particular CMS or any backend framework, they can focus on the front end!
However, this is extra cool as long as it works. Remote calls just fail sometimes. You need a mechanism to handle failures.
If we look beyond, what happens if, for some reason, one or several services (dependencies) fail? How do you handle timeouts?
If you don't use a circuit breaker, any network or service failure will cascade to other services resulting in a massive crash.
Instead, you'd rather detect consecutive failures and cut the power if a critical amount is reached.
This would prevent the application from trying to perform actions that are doomed to fail.
Besides, a circuit breaker automatically turns the power back when the situation is back to normal.
A circuit breaker is pretty handy to handle exceptions raised by your internal logic. It's especially useful to avoid bad contagion.
If your application has interdependent services, which is likely, it's easy to get DoS attacks. Having a circuit breaker will make sure the cascading effect cannot happen.
At the end of the day, your code is meant for business and customers. When there's a crash in production, your business stops generating value. You need your services to be available all the time.
The more dependencies your system has, the more likely it will fail. Nowadays, even very simple applications have multiple components: database, web server, caches, etc. So many things that can break...
Your application is resilient when it remains functional from the customer perspective even when a failure occurs in your components or their dependencies.
The circuit breaker pattern is different than the retry pattern. It prevents unnecessary retries because we know it will fail for sure.
It's different from the fallback pattern too. In case of failing, it does not continue to another service, because we know it's critical and we cannot use default rules.
The circuit breaker pattern is not the same as the timeout pattern. HTTP clients use this pattern to make sure requests fail if no response is received within the timeout period.
Dealing with timeouts can be tricky. Maybe some service has gone but the purchase succeeded. In this case, the customer receives an error while he's charged.
Combining all these patterns with a circuit breaker might cover the vast majority of situations.
The circuit breaker pattern prevents the domino effect. It works as a proxy you will use in your interdependent services to prevent bad contagion if any of them stops working properly.
Nevertheless, the perfect pattern does not exist. It might be hard to determine which metrics can be used for a general threshold.