Scala
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented Scala
-
Section 4: Functional Scala
-
Section 5: Collections in Depth
-
Section 6: Type System
-
Section 7: Concurrency and Ecosystem
-
Section 8: Practical Projects
-
Section 9: Interview Practice
-
Section 10: Data Structures and Algorithms in Scala
-
Section 11: More Practice Exercises
-
Section 12: Advanced Functional Patterns
-
Section 13: More Ecosystem
-
Section 14: Scala Collections Library Deep Dive
-
Section 15: Scala Standard Library Deep Dive
-
Section 16: Akka Ecosystem Deep Dive
-
Section 17: Cats and Cats Effect Deep Dive
-
Section 18: Play Framework Deep Dive
-
Section 19: Apache Spark with Scala Deep Dive
-
Section 20: Scala Build Tools Deep Dive
-
Section 21: Scala 3 Specific Features
-
90: Union and Intersection Types
-
Section 22: Scala Testing Deep Dive
-
Section 23: Functional Domain Modeling
-
Section 24: More Data Structures and Algorithms in Scala
-
Section 25: Scala for Data Engineering
-
Section 26: More Practical Projects
-
Section 27: More Interview and Review
-
Section 28: ZIO Ecosystem Deep Dive
-
Section 29: Scala for Machine Learning
-
Section 30: Scala Microservices Architecture
-
Section 31: Scala Type System Deep Dive
-
Section 32: More Practice and Drills
-
Section 33: Scala Performance Deep Dive
-
Section 34: Scala Ecosystem Tooling
-
Section 35: Scala for Reactive Systems
-
Section 36: More Real-World Case Studies
-
Section 37: Scala for Financial Systems
-
Section 38: Scala GraphQL and gRPC
-
Section 39: More Final Projects
-
Section 40: More Interview and Final Review
-
Section 41: Scala for Streaming Data
-
Section 42: Scala Security Practices
-
Section 43: More Language Deep Dive
-
Section 44: Scala Command-Line Tools
-
Section 45: Scala Documentation and Style
-
Section 46: Scala Dependency Management
-
Section 47: More Practical Backend Patterns
-
Section 48: Scala for Event-Driven Architecture
-
Section 49: More Practice Drills Round 2
-
Section 50: Scala Compiler Deep Dive
-
Section 51: Scala for Web Frontends
-
Section 52: More Data Engineering Practice
-
Section 53: Scala Observability
-
Section 54: More Advanced Practice Projects
-
Section 55: Scala for Legacy Java Integration
-
Section 56: More Testing Practice
-
Section 57: Final Mastery Review
-
Section 58: Scala History and Ecosystem Context
-
Section 59: More Concurrency Patterns
-
Section 60: Scala for Configuration Management
-
Section 61: More Domain Modeling Practice
128: Circuit Breakers with Akka
A few years ago, I was on a team maintaining a checkout pipeline that relied on a legacy third-party tax calculation API. One Tuesday afternoon, that API started lagging. It didn't crash—which would have been easier to handle—it just started taking 25 seconds to respond instead of 200 milliseconds. Because we were using a standard Akka actor to wrap these calls, our mailbox started filling up. Every request waited for that 25-second timeout, tying up a thread and consuming memory. Within twenty minutes, the "laggy" tax service had effectively DDoSed our own checkout service, bringing the entire site down. We weren't failing because the tax service was dead; we were failing because we kept trying to use it.
This is exactly why we use Circuit Breakers. The goal isn't to fix the downstream service—you can't control someone else's API—but to protect your own system from the fallout. A Circuit Breaker acts as a proxy that monitors for failures. When the failure rate hits a certain threshold, the breaker "trips" and enters an Open state. In this state, every subsequent call fails immediately without even attempting to hit the remote service. This gives the struggling downstream system room to breathe and prevents your own resources from being exhausted by endless waiting.
The Mechanics of the Trip
In Akka, the CircuitBreaker is provided as a pattern that wraps a Future-returning call. It operates like a state machine. When it's Closed, everything is normal; requests flow through. If the number of consecutive failures exceeds a limit you've set, it flips to Open. While Open, the breaker immediately returns a CircuitBreakerOpenException. After a cooldown period (the reset timeout), it enters the Half-Open state, allowing a single "test" request through. If that request succeeds, the circuit closes and we're back in business. If it fails, it flips right back to Open.
Here is how you actually set one up in your actor or service layer:
import akka.pattern.{CircuitBreaker}
import scala.concurrent.duration._
import scala.concurrent.{ExecutionContext, Future}
class TaxServiceProxy(implicit ec: ExecutionContext) {
private val breaker = new CircuitBreaker(
system,
maxFailures = 5,
callTimeout = 2.seconds,
resetTimeout = 10.seconds
)
def getTaxRate(zipCode: String): Future[Double] = {
breaker.withCircuitBreaker {
// This is where the actual risky network call happens
callLegacyTaxApi(zipCode)
}
}
private def callLegacyTaxApi(zipCode: String): Future[Double] = {
// Simulated API call
Future {
// Logic that might time out or throw an exception
1.05
}
}
}
Managing the Reset Window
I've seen developers make the mistake of setting the resetTimeout too low. If you set it to 1 second, but the downstream service needs 30 seconds to reboot, you're just hammering it with "test" requests every second, potentially extending its outage. You have to align your breaker settings with the reality of the service you're calling. If it's a database that might be failing over to a replica, a 30-second window is more realistic.
You also need to decide how to handle the CircuitBreakerOpenException. You shouldn't just let it bubble up to the user as a 500 error. Instead, use this as a signal to provide a fallback. For my tax API disaster, the fallback was simple: use a cached average tax rate for that region. It wasn't 100% accurate, but the customer could still complete their purchase, and the site stayed online.
- maxFailures: How many times the service can fail in a row before we give up.
- callTimeout: The maximum time we're willing to wait for a single response before counting it as a failure.
- resetTimeout: How long we wait in the Open state before trying again.
📋 Practical Task
Build a Resilient Weather Dashboard Proxy
You are building a weather dashboard that aggregates data from a notoriously unstable external Weather API. Your task is to implement a proxy service that prevents the dashboard from freezing when the Weather API becomes unresponsive.
Requirements:
- Create a
WeatherProxyclass that uses an AkkaCircuitBreaker. - Configure the breaker with a
maxFailuresof 3, acallTimeoutof 1 second, and aresetTimeoutof 5 seconds. - Implement a method
getCurrentTemperature(city: String): Future[Double]. - Inside
getCurrentTemperature, wrap the API call in the circuit breaker. - Implement a fallback mechanism: if the circuit is Open or the call fails, the method should return a
Future.successful(0.0)(a default "safe" value) instead of throwing an exception. - Simulate the "flaky" API by creating a helper method that randomly throws an exception or delays for 2 seconds to trigger the timeout.
There are no comments for now.