There are a lot of questions around what/how/what is the best Execution Context
to
Ideally with only non-blocking code you would just use the frameworks execution context. Play Frameworks or Akka's.
But sometimes you have to use blocking API's. In one Play Framework and JDBC project, we followed their recommendation [1] and set the execution context to have 100 threads, and just used the default everywhere. That system was very fast for its usage and needs.
In a different Akka project where we had a mix of blocking and non-blocking code we had seperate dispatchers configured for the different features. Like "blocking-dispatcher", "important-feature-dispatcher" and "default-dispatcher". This performed fine, but was more complex than having 1 dispatcher, we had to know/guess/monitor how much each needed. We load tested it and found that at 1 thread it was too slow, if we had 5 threads it was better but after 10 threads it didnt get any faster. So we left it at 10 threads. Eventually we refactored away our blocking code and moved everything to the default.
But each use case is different, you need to profile and monitor your system to know whats right for you. If you have all non blocking code its easy, it should be 1 thread per CPU core.
[1] https://www.playframework.com/documentation/2.5.x/ThreadPools#Highly-synchronous