Scalable & responsive.
Resilient & fault-tolerant.
Event-driven & asynchronuous.
The benefits of RAs are well and commonly known (if you're not up-to-date, make sure you get yourself familiar with Reactive Manifesto: start with the following link), but it's not the benefits I'd like to write about specifically today:
- What about the real cost?
- What about the effort?
- In a typical scenario, when a company needs an enterprise-ready solution to fullfill its functional needs - does it make sense to go for a reactive application?
Not now, not here
Obviously, there are some circumstances when going reactive doesn't make any sense:
- when you have to wait for the response anyway (synchronuous request-response)
- or the communication just doesn't fit the 'event-driven' paradigm (reasons may vary) in general
But shouldn't we (in such case) just re-engineer the particular case towards asynchrony and event-driveness? Unfortunately (or fortunately) we can't and (what is more) we shouldn't - these are just different communication patterns and each of those has its use in different scenarios.
But even if we can (in this particular case) refactor the application in that way - should we pursuit the opportunity? What's the additional cost and how does it compare to the potential benefits?
Reactive programming is asynchronuous; asynchronuous programming is more complex:
- in terms of dealing with the results (for instance: Futures & Promises)
- in terms of error-handling - because you can't just snap a try-catch block around
If processing your event has failed, you don't know that immediately, so you need to set up a separate flow / procedure to deal with messages that caused trouble (for instance Dead Letter queues).
If there's any response to be provided, both communication sides should have the receiving and dispatching logic implemented. In simple synchronuous scenarios server side implementation is trivial (unless you have to go full duplex which is quite rare).
What's the purpose in having a responsible client if server has died anyway (for instance: all actors are overflooded with events they can't serve)? I mean - does it really make any difference?
Modern day's computing power & I/O efficiency are that top notch that properly designed synchronuous OLTP will last milliseconds even under heavy load. Unless you're Twitter or Facebook - do you really need anything more than a load balancer and a farm of homogenous nodes with lightweight synchronuous services instances that use a shared DB?
Asynchronuous applications are much harder to troubleshoot, debug, unit-test...
Before we go flaming around...
Personally, I think that reactive programming is awesome. I'm fascinated with Rx, I love the Erlang concurrency model (even if it's still half-magic for me) & I'm crazy about how it's got replicated in Akka. But still, I want to remain pragmatic and reasonable:
IMHO, in 99% of cases:
- when my load is predictable (may be high, but it's sustained - no massive peaks)
- if I use the suitable data model & access layer (so I don't need additional, expensive operations to gather up & pre-process the data before sending the response back to the caller)
- with short time-out values set up for communication
there's no real reason to go for the reactive approach.
In theory, reactive approach is safer, more efficient, more scalable & may result in better user experience, but if you take under consideration all the 'mehs' above, can you really recommend an average enterprise that develops some applications for its own use to switch to reactive application style?
This is not the end...
I'll be carefully watching what happens next:
- Will Akka get a wider adoption?
- How will modern IDEs support reactive style of programming?
- Will there be a new wave of reactive programming frameworks?
For now, I treat Akka as a special task tool - tool for people who:
- precisely know what they want to achieve and why they want to use Akka
- are fully committed to embrace it and are absolutely aware what does it mean in practice
- have a real need of out-scalable application that deals with frequently & rapidly changing loads
- integrate very different and very independent services that may have a very different response times (and the likelihood of partial fail is for real)