Thursday, September 18, 2014

A Response to the Reactive Manifesto

The Reactive Manifesto published by Typesafe is getting a great deal of attention in the Scala community.  A new version was posted yesterday and I could not help but reply with criticism that has been bothering me for some time.  The Reactive Manifesto appears to be a thinly veiled way to back into Akka being the cure for all ills.  I think this is an irresponsible message especially from a company like Typesafe that is guiding a great number of people that are just venturing into Scala.  One sure way to hurt the Scala community is to offer the advice that one should adhere to a reference architecture that is best applied for only a certain set of problems.  My comment/reply to the Manifesto appears below in its entirety.  I hope that, at a minimum, it stimulates some thought for those that were intending to jump into the Akka pool without fully understanding why.

Jonas:

I am the VP of Engineering at LeadiD a tech startup based in Ambler, PA. We are building out a large, complex stack for servicing web transactions at scale. We already process billions of web service calls each month. We are gung-ho on Scala even though it’s new to us here. But I must confess that so far I’ve felt the Reactive Manifesto to be a bit, if you’ll forgive me, contrived. When I read it, it seems that we’ve all been suffering from ADD (Akka Deficit Disorder) and we just didn’t know it. But actors (which are at the heart of Akka) are not the cure for everything. They are a great solution for certain types of problems.

Allow me to comment on the system attributes in the Manifesto:

Responsive - An essential attribute. This is a function of proper provisioning. There are many ways to achieve this.

Resilient - An essential attribute. Most mission-critical systems ensure this using a load balancer and a cluster(s) of servers. Does not require the use of actors or supervision hierarchies.

Elastic - An essential attribute. Akka does have a sweet spot here. But can be achieved using elastic provisioning techniques by rolling your own in a DevOps manner or by using third party tools.

Message-Driven - This is not an essential attribute. You’ve fast-forwarded to a solution, here. It’s a means to an end and it basically describes actors. Increasing asynch is very important as a piece of the puzzle. But synchronous processing of a request that does not lend itself to being split up or parallelized still has its place.

There are some complexities with actors:
  • Actors are a mechanism to solve a distributed computing problem - that is, when a given request is best split up across a number of machines. When a given problem does not lend itself to distributed computing it’s not a great fit. Many CRUD functions (even at scale) out there are served best by a cluster of nearly identical, load-balanced app servers each of which is self-contained.
  • Unless you have a distributed computing problem location transparency is not a good thing. I want the caller to know he’s making a network call vs. an in memory lookup.
  • Given the buzz people will gravitate to actors because it appears to be the latest / greatest. But unless their problem merits it they’ve opened up new cans of worms. If the work can be handled in a single process actors might not be the right choice.
Rich Hickey says it best:

“I chose not to use the Erlang-style actor model for same-process state management in Clojure for several reasons:
  • It is a much more complex programming model, requiring 2-message conversations for the simplest data reads, and forcing the use of blocking message receives, which introduce the potential for deadlock. Programming for the failure modes of distribution means utilizing timeouts etc. It causes a bifurcation of the program protocols, some of which are represented by functions and others by the values of messages.
  • It doesn't let you fully leverage the efficiencies of being in the same process. It is quite possible to efficiently directly share a large immutable data structure between threads, but the actor model forces intervening conversations and, potentially, copying. Reads and writes get serialized and block each other, etc.
  • It reduces your flexibility in modeling - this is a world in which everyone sits in a windowless room and communicates only by mail. Programs are decomposed as piles of blocking switch statements. You can only handle messages you anticipated receiving. Coordinating activities involving multiple actors is very difficult. You can't observe anything without its cooperation/coordination - making ad-hoc reporting or analysis impossible, instead forcing every actor to participate in each protocol.
  • It is often the case that taking something that works well locally and transparently distributing it doesn't work out - the conversation granularity is too chatty or the message payloads are too large or the failure modes change the optimal work partitioning, i.e. transparent distribution isn't transparent and the code has to change anyway.”
And then there is Fowler’s First Law of Distributed Object Design: Don’t distribute your objects! (unless you must)

Typesafe is shepherding a great number of people in the Scala community on how to best use the language and its platform. By pushing Reactive (which basically equals Akka) on its front page as the cure for all ills it suggests that you must be missing something if you’re not doing it this way. But the way that’s been outlined is most appropriate in a distributed computing setup. And many distributed computing problems arising out of large datasets, for example, can be addressed using other techniques such as MapReduce.

While the Akka platform is very powerful I believe that the Scala community could use better education from Typesafe on when it is best used as well as when to consider alternative architectures. Balance will go a long way toward credibility. Thanks so much for the work. But please bear in mind that if Akka is a hammer that does not imply that everything is a nail.

Joe Lynch