The Verdict
Neither Typed nor Classic actors inherently minimize latency for blocking workloads. Because both APIs run on the same underlying actor runtime and scheduling machinery, the choice between Typed and Classic has a negligible impact on per-message overhead and runtime latency.
The Root Cause of Latency
In Scala actor systems, latency in blocking workloads is almost always a function of dispatcher configuration rather than the actor API. When an actor performs a blocking operation (such as a JDBC call or synchronous HTTP request) on the default dispatcher, it occupies a thread that cannot be used by other actors. Under high concurrency, this leads to thread starvation, which spikes p99 latency for all actors sharing that dispatcher.
Confirmed Technical Facts
- Shared Runtime: Typed actors are a wrapper around the same core actor system used by Classic actors; they do not use a different scheduling engine.
- Dispatcher Dominance: The dispatcher manages the thread pool. If a blocking call is made, the thread is held regardless of whether the actor is Typed or Classic.
- Isolation: The only way to prevent blocking calls from inflating system-wide latency is to isolate them on a dedicated dispatcher.
Implementation Steps for Blocking Workloads
To minimize latency, follow these steps regardless of the actor model chosen:
- Define a Dedicated Dispatcher: Create a separate thread-pool dispatcher in your configuration (e.g.,
application.conf) specifically for blocking tasks.
- Assign the Dispatcher: Assign the actor performing the blocking work to this specific dispatcher. In Typed actors, this is typically done during actor creation via the
ActorContext or system configuration.
- Cap the Pool Size: Size the dispatcher pool to match the limits of the downstream resource (e.g., the maximum size of your database connection pool) to avoid memory exhaustion.
- Verify Isolation: Use thread dumps during load tests to ensure that blocking threads are confined to the dedicated pool and are not leaking into the default dispatcher.
Assumptions and Uncertainty
This analysis assumes the use of standard Akka/Pekko runtimes. While Typed actors provide better compile-time safety—which may indirectly reduce latency by making blocking patterns easier to spot and refactor—there is no evidence that the Typed API provides a runtime performance advantage for blocking I/O.
Missing Diagnostic: To provide a more specific recommendation, it is necessary to know the nature of the blocking call (e.g., CPU-bound vs. I/O-bound), as this determines whether a ThreadPoolExecutor or a ForkJoinPool is the optimal dispatcher type.