Akka anti-patterns: stateless actors

Published on 30 May 2018 , last updated on 30 May 2018

Actors are object-orientation done right (as opposed to say, objects in Java): their state is not visible from the outside and they communicate via messages. There’s no way to break encapsulation because you can’t peek into an actor’s state while it is running. That’s the entire point of actors: they provide you with the illusion of a safe space in which things are executed sequentially, one message after the other, allowing you to use mutable state inside of your actor without having to worry about race conditions (well, almost: don’t leak the state).

Which is why using actors that don’t have state is somewhat odd, to say the least. With the exception of actors that handle supervision for larger parts of your actor system hierarchy (setting up back-off supervisors, for example), actors are really meant to deal with long-lasting computation that holds state. With long-lasting I mean to say that the actor will have multiple interactions in its lifetime, producing different results depending on its state, as opposed to one-shot computations. For those, Futures are an excellent abstraction: they allow asynchronous code exection, ideal for cases of network and disk related computation (or really intensive CPU tasks), are composable and have a failure-handling mechanism. They also integrate well with Akka actors (using the pipe pattern).

So: don’t use actors if you don’t have state – that’s not what they’re meant for.

Thanks to Heiko for the discussion on this topic in the cab to that fancy vegan restaurant during the last Scala Days in Berlin


Liked this post? Subscribe to the mailing list to get regular updates on similar topics.

5 Comments

  1. Hi Manuel, thanks for your posting! I was wondering whether for example the pipe and filter pattern is an anti-pattern or not, since it does not really hold any state, I mean, mutable variables or so, it usually receives something, do some work and pipe it to the next actor.
    I would like to see some code examples because after this post, I was wondering how many anti-patterns I’ve been writing the last years using Akka 🙂
    Thanks

    • I’d say that if none of the filter actors have any mutable state (i.e. the ability to alter the filter criterion) then I’m not sure of the advantage of using actors over simply chaining futures with a for comprehension – unless there’s the danger of one step failing, in which case error handling in actors is easier to handle than with Futures (with a for-comprehension you don’t necessarily know which step has failed, unless you explicitly make this a part of the data being processed).

      • Hmm, I see and makes sense. I have one big system here written using the pipe and filter pattern and they have some logical inside for success or failure, so yes, I agree it’s easier to handle than using future with for comprehension. Thank you.

  2. Hello Manuel,
    I am somewhat confused with your assertion of stateless actors, being agents of Anti-Patterns. I understand why think so, and what you suggest as alternatives, but while trying to implement a small Rule Engine using Actors, I am facing situations where an Actor simply takes a decision based on the input data and possibly, the Context data, both of which are passed to it. In order to generalize such Actors, I have to allow for situations where a (rule-executing) Actor may or may not have its own state. If it is so, then I am adopting an anti-pattern.
    Is my line of thinking correct? Perhaps, I am missing something. Please help me in catching that.

    • Hi! I can see how in this case you’d have a need for stateless actors in order not to have to mix two paradigms and keep doing everything with actors. Though I do have to wonder why you’d implement the rule engine with actors in the first place? Is it a rule engine that spans across several machines because the data to operate on is large? If the computation takes place locally, on one computer, my gut feeling would otherwise be that there wouldn’t necessarily be that much performance gain from performing each step of the rule computation in its own actor, as that would potentially result in having quite a few actors who’d have to interact, leading to context switching. Or have you found a way to split the computation across a small number of actors that doesn’t exceed the amount of CPU cores? That could work well with e.g. the thread affinity dispatcher.

Leave a Reply