What is handle_info in Elixir?

Overview

Before diving into the details of handle_info in Elixir, we’ll talk about its preliminaries:

GenServer

For asynchronous code execution, keeping state, and tracing and reporting errors in Elixir, we can use a generic server process, GenServer. Not only can it fit into a supervision tree, but also has many standard interface functions for a more abstract codebase.

Callbacks

While using GenServer, we only need to write callbacksThe number after the backslash is the number of parameters they take. and functionality they want to add. handle_call/3 and init/1 are two examples of them.

These callbacks allow us to add our logic to the GenServer process. Next, we’ll see the callback, handle_info.

The handle_info callback

Messages that do not come from GenServer.call/2 or GenServer.cast/2 are handled by the handle_info/2 callback. It can also be used to handle monitor DOWN messages sent by Process.monitor/1.

Another example can be a message sent from Process.send_after/4.

Syntax

handle_info(msg, state)

Parameters

handle_info/2 takes two parameters, depending on the functionality.

  • msg: This is the message.

  • state: This is the state of the GenServer.

  • The message is timeout whenever a timeout occurs.

handle_info(msg :: :timeout | term(), state :: term()) ::
{:noreply, new_state}
| {:noreply, new_state, timeout() | :hibernate | {:continue, term()}}
| {:stop, reason :: term(), new_state}
# when new_state: term()

Return value

  1. To continue the loop with new state, it returns {:noreply, new_state}.

  2. To also set a timeout, it returns {:noreply, new_state, timeout}.

  3. To hibernate the process before continuing, it returns {:noreply, new_state, :hibernate}.

  4. To immediately invoke handle_continue/2 with the value of continue as the first argument, it returns {:noreply, new_state, {:continue, continue}}.

  5. To stop the loop and terminate/2 with the reason reason and state new_state, it returns {:stop, reason, new_state}. It will also exit the process with reason reason.

Code example

In the widget’s terminal below, we execute the following function:

Period.start_link({})

This would start the init/1 function, which would start the schedule_work() function. The schedule_work() would then trigger the handle_info/2 callback using the send_after/4.

We’ll be printing "work completed" every 5 seconds to the terminal.

defmodule Chat.MixProject do
  use Mix.Project

  def project do
    [
      app: :chat,
      version: "0.1.0",
      elixir: "~> 1.13",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end

Free Resources

Copyright ©2025 Educative, Inc. All rights reserved