Call over Cast

Take a look at why calls should be preferred over casts in relieving the burden on the Elixir logger.

Reviewing our decisions

Now that the service layer is in, let’s review some of the significant decisions we made.

You might have noticed that we used call several times when we returned an :ok value. You might be wondering why we chose not to use cast messages instead. The answer is not as simple as it may seem on the surface. Let’s find out why.

Why using casts isn’t preferred?

Intuitively, you might think that it’s best to use the one-way handle_cast to send messages that don’t need responses. For example, here are some features of the :add_template message:

  • It doesn’t need a response.

  • We trust that the template was added successfully.

  • If it’s not, something has gone wrong.

  • There’s nothing we can do beyond crashing the server and reporting the reasons for the crash back to the user.

Interestingly, handle_cast is rarely the best option for sending messages. In this lesson, we’ll look at two of the reasons why— serializability and back pressure.

Message queues in Elixir

As we know, each Elixir process has a message queue. We’ll call it the mailbox. Unlike a physical mailbox, Elixir processes only receive messages from it and don’t send from the mailbox. Like an actual mailbox, if the receiving process for a given message is struggling, the mailbox can overflow, often leading to severe problems that are hard to debug.

A good example is the Elixir logger. Our production code might be sending log messages quicker than the logger can handle them. This could be due to one of two reasons:

  • The sender is logging too many log requests.

  • The logger’s disk I/O is somehow compromised.

In both cases, we don’t want the logger to stop logging messages immediately.

Using back pressure to assist the logger

The Elixir logger has an excellent solution for this problem. It’s called selective back-pressure. That means that when the logger gets into trouble, it will detect this problem and start slowing the clients down by switching from cast to call. Here’s how this will help:

  • Making the logger’s client wait for every request to finish before sending the next one relieves the pressure on the logger itself by slowing down the flow of messages.

  • If the logger still can’t keep up, it announces this failure as a log message and begins to discard messages until the logger gets to a more manageable threshold.


Get hands-on with 1200+ tech skills courses.