When we think about modelling a certain concurrent problem in Scala, There are a lot of tools in terms of libraries and frameworks to choose over vs the type of concurrency Problem. As part of this blog, we will be talking about where these tools can be utilised at their best. On a broad level, we can classify the tools into categories. There are concurrency Frameworks such as Akka vs there are libraries or Concurrency Primitives built in as part of language features such as Scala Futures or Java Futures, Callables etc. As part of this blog, we will highlight the Framework part of it.
Akka Framework
Akka is perceived to be our first choice in the community when you have a use case where business transactions can scale in huge numbers and the business operations are fairly complex. It offers a range of tools to model various aspects of business requirements which are often needed to harness the “multicore” machines.
Why does Actor model sound cool!
Let me quote a line for Akka documentation. “At the core of Akka: A model for concurrency and distribution without all the pain of threading primitives”. The biggest ease we feel when we see that we do not have to touch the low-level thread details in order to achieve concurrency.
Actors are LightWeight compared to Java threads.
I came across a very good post over StackOverflow which describes how actors are lightweight. Overall, we can instantiate a lot of actors which might run over a pool of a very few threads.

Actors can be distributed across Machines
As mentioned earlier, Actors can scale in huge numbers, they can also be distributed remotely across clusters. This is a property needed to architecture business which might go up in disrupting figure or can decide to run on cluster mapped to a single JVM. Designing microservices with Actors is easier than other concurrency abstractions.
Lock-free concurrency
Each actor has a mailbox and they communicate using a message. The messages are sent asynchronously and the sending actor can continue to function without having to block for the reply. If you look through the default mailbox implementation, it is backed by java.util.concurrent.ConcurrentLinkedQueue, a thread safe Data structure. They state of an actor can never be touched directly by another thread. The messages are sent to actors using Actor references which makes it a powerfull tool.
Actor Model and Domain Drive Design (DDD)
Quoting from the Vaughn Vernon on the Actor Model and DDD talk” Why actors are so exceptionally well-suited for use with Domain-Driven Design, speaking the Ubiquitous Language of your core business domain?” If you are familiar with DDD, and terminlogoies, A business Entity called Aggregate can be easily be modelled using Actors since Aggregates are the basic element of transfer of data storage – you request to load or save whole aggregates. Transactions should not cross aggregate boundaries. So in one way, it simplifies modelling business problems based on DDD Architecture. Look for Customer and Cashier Actors in the below diagram from https://domainstorytelling.org/

Support for Event Sourcing and CQRS
Event sourcing not only saves us to resume operations quickly after failures but helps debugging critical business transaction with audit like facilities on persistency on Entities. Akka support of Event persistence and snapshotting makes it a tool of choice for event sourcing. The query side of CQRS can be implemented with Akka PersistentQuery abstraction.
Supervision and Monitoring
Akka actors are inherently supervised from birth to death by the parent actors. There are enough supervision strategies to resolve re-spawn the death of an actor. Since the state of the actor is persisted, restarting the dead never results in a state of inconsistency. At the core of each ActorSystem, there are at least three top level supervisors always present namely the “root guardian” at the top having “guardian” and “system guardian” as children. All the actors created by user goes under “user” guardian actor supervision. as indicated below in the image.

Having said all that use cases that a business case require to solve, the list of Akka usefulness goes on and on. For dig in further on the list, I recommend you to visit the use cases of Akka in the official documentation.
Where Akka is an Overkill?
When mapped in JVM, Akka ActoryStyem is a heavyweight structure. One should always realize its true potentials and at the beginning selecting any tools to model any concurrency Problems. Also, when it comes to implementation there are certain models (case classes and objects) you need to create to wrap your messages which can become an overkill if you problem doesn’t fit for tools like Akka. You should think about the below points.
Do you need a stateful Application?
Actors can be very easily maps to state and behaviors but when you do not need state at all and Actors the use case is as trivial as reading records from a database in a asynch manner, The other libraries might seem more useful than instantiating an ActorSystem for the same. Scala built-in Future or Monix would a good choice to go.
You need to execute some concurrent Task periodically
Often we start think about creating an actor when we want to run any piece of code as a separate thread periodically. Although Akka supports scheduling and You can schedule sending of messages to actors and execution of tasks (functions or Runnable), but unless you need some certain fault tolerance or other features that Akka offers, It is good to go for simple java.util.concurrent.ScheduledThreadPoolExecutor and your code can be as simple as:
val executor = new ScheduledThreadPoolExecutor(poolSize) executor.execute(() => new Thread { //your logic goes here. })
When your Application already uses an ExecutorService
If your Application already uses an ExecutorService backed by a pool of Threads and your task is as simple as it can be wrapped around a Runnable or a Callable, it is better to submit the task to the existing pool of threads and leave the thread management to a centralized place.
Type Saftey and Composibility
Classic Actors do not have a type safety and hence they were hard to test for their logic. The new Akka Typed released with enhanced type safety for Actors Behavior over classic Actors. Neverthless, we work with any Functional programming language or construct, Composibility becomes necessary in order to make pieces of logic reusable and testable. Akka yet does not offer much for this part. If you think the logic you are going to map inside Actor’s behavior is going to be reused often and often and need composibility on the processing side, choosing Future API over Akka is a good choice.
Alternatives Concurrent Libraries for Scala
Till this point, I’ve just gone through where does Akka fit and where we can do without it. There are other libraries as well which offers a lot for the need of concurrency and Performance, and I’ve referenced a few in this blog as well e.g. Monix which claims to be lighter than Scala Future but without having an example to compare it, it would be injustice for either of the libraries and framework. As part of the next blog, we will go through the detail of other libraries with an example. Stay tuned!!

References:
https://domainstorytelling.org/
the Vaughn Vernon on the Actor Model and DDD talk”