Akka anti-patterns: Java serialization

Published on 20 July 2018 , last updated on 20 July 2018

Akka makes use of serialization when messages leave the JVM boundaries. This can happen in mainly two scenarios: sending messages over the network when using Akka Cluster (do not use Akka Remote directly) or using Akka Persistence.

Now here’s the catch: the default serialization technology configured in Akka is nothing but the infamous Java serialization, which Mark Reinhold called a “horrible mistake” and which Oracle plans to dump in the near future anyway.

When using Java serialization, you get warning messages in your logs:

That’s nice, but it’s not enough – they are, after all, easy to ignore (and the warnings can be turned off – which can be tempting).

The Akka documentation discourages the use of Java serialization – there’s a note in the serialization documentation that mainly points out the performance issue:

Now, performance is one reason to not use Java serialization – but there are stronger reasons to not engage with it, especially in the context of Akka:

What to do instead?

When starting a new project, the first thing you should do is to disable Java serialization by adding this line to application.conf:

Next, you will need a binary serialization protocol. You really don’t want to use JSON, unless you are the type of person who enjoys load-testing their garbage collector as Martin Thompson puts it. There are quite a few around by now:

Martin Kleppmann wrote a nice comparison of Avro, Protocol Buffers and Thirft with a focus on message evolution. There are different approaches in binary protocols, the ones that use a per-field approach and the ones that go for a full schema – both approaches have their pros and cons and really need to be evaluated in the light of your project and organizational structure.

Akka uses Protocol Buffers internally, which has the advantage that integrating those is quite straightforward. For example, if you use ScalaPB to generate case classes from the Protocol Buffer definitions you only need the following configuration to get things to work:

One more thing: with the rise of Akka Typed, the best practice of defining one protocol per actor (instead of sharing messages) becomes even the more relevant. As such, one approach I’ve used successfully in a number of projects now uses the following pattern (in combination with ScalaPB):

For example, the SomeActorProtoco.proto file would look as follows:

That’s it! If you realize now that you’ve been doing it all wrong and are likely going to run into trouble with Java serialization, I invite you to check out the Akka anti-patterns overview. Chances are that this won’t lift your mood, but you might find out one useful thing or two.

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

One Comment

  1. I’m curious how you do your serialization of the typed ActorRef. You have defined the sealed traits in the preamble so it seems like you are skipping creating a serializer using something like SerializerWithStringManifest and using the generated case classes from scalapb directly throughout your actors. Is that correct? If so, how do you going about unmarshaling the resulting typed ActorRef since it’s a String in the protobuf message?

Leave a Reply