Actor Model
- In Turkish
- Aktör Modeli
- Pronunciation
- AK-ter MOD-ul
In short
The actor model builds concurrent systems from actors: independent units with private state that communicate only by sending each other asynchronous messages.
What is the actor model?
The actor model structures a program as many small, independent actors. Each actor has its own private state and a mailbox, and the only way to interact with it is to send it a message. While handling a message, an actor can do three things: send messages to actors it knows, create new actors, and decide how to handle the next message, for example by updating its state. Carl Hewitt, Peter Bishop and Richard Steiger introduced the model in 1973.
An actor handles one message at a time, so its state is never touched by two threads at once and needs no locks. Messages are asynchronous: the sender drops one in the mailbox and carries on without waiting. Sending a message looks the same whether the receiving actor is in the same process or on another machine, so the model stretches naturally from one computer to a cluster, and many frameworks add supervision, where a parent actor restarts a child that has crashed.
Processes in Erlang and Elixir work as actors, which is one reason those languages run telecom switches and chat backends. On the JVM, Akka and Apache Pekko, an open-source fork started after Akka moved to a source-available license in 2022, provide actors, Microsoft Orleans offers virtual actors for .NET, and Swift has an actor keyword that protects state from data races. The model resembles an office where everyone works only from their own inbox: nobody reaches into a colleague's desk, they leave notes, and each person handles one note at a time.
The actor model is often confused with plain threads and with message queues. Threads share memory and coordinate with locks, which invites race conditions and deadlocks; actors share nothing, and a scheduler runs thousands or millions of them on a few threads. A message broker such as RabbitMQ is infrastructure that carries messages between separate services, while in the actor model every actor has its own mailbox and is itself the unit that does the work.
Key takeaways
- An actor has private state and a mailbox and communicates only through messages.
- Each actor handles one message at a time, so its state needs no locks.
- Messages are asynchronous, and the same model works across machines.
- Erlang, Elixir, Akka, Apache Pekko and Microsoft Orleans are built around actors.
- Actors share nothing, while threads share memory and need locks.
Example
defmodule Counter do
def loop(count) do # count is private: no shared memory
receive do # take one message from the mailbox
:increment -> loop(count + 1)
{:get, from} ->
send(from, {:count, count})
loop(count)
end
end
end
counter = spawn(fn -> Counter.loop(0) end) # create an actor
for _ <- 1..3, do: send(counter, :increment) # asynchronous: send and carry on
send(counter, {:get, self()})
receive do {:count, n} -> IO.puts(n) end # prints 3Readers ask
Is an actor the same as a thread?
No. An actor is a lightweight object with a mailbox, not an operating system thread. A runtime schedules huge numbers of actors onto a small pool of threads, and an actor uses a thread only while it is handling a message.
What is the actor model used for?
Systems with many independent pieces of state that change concurrently: chat and messaging servers, multiplayer game servers, telecom switches, IoT platforms that model each device as an actor, and trading systems. Supervision and location-independent messaging also make it a good fit for fault-tolerant distributed systems.
What are the downsides of the actor model?
Asynchronous messages are harder to follow and debug than direct function calls, and a request that needs a reply takes extra plumbing. Delivery guarantees are limited too: across a network a message can be lost, so important messages need acknowledgments or retries.
See also
- ConcurrencyProgramming Fundamentals, p. 15Concurrency is a program's ability to make progress on several tasks in overlapping time periods, such as serving many users at once rather than one at a time.
- ErlangProgramming Languages, p. 10Erlang is a functional language created at Ericsson for telecom switches, designed for massive concurrency, fault tolerance and systems that must keep running.
- ElixirProgramming Languages, p. 9Elixir is a dynamic, functional language that runs on the Erlang virtual machine and is known for building fault-tolerant, highly concurrent systems.
- ThreadOperating Systems, p. 33A thread is the smallest unit of execution an operating system can schedule, running inside a process and sharing that process's memory with other threads.
- Message QueueBackend & APIs, p. 32A message queue is a component that stores messages from one service until another is ready to process them, so parts of a system can work asynchronously.
- Distributed SystemSoftware Architecture, p. 15A distributed system is a set of computers that work together over a network and appear to their users as a single system.
Sources
- Hewitt, Bishop and Steiger: A Universal Modular ACTOR Formalism for Artificial Intelligence (1973)ijcai.org(opens in a new tab)
- Akka documentation: How the Actor Model Meets the Needs of Modern, Distributed Systemsdoc.akka.io(opens in a new tab)
- Erlang documentation: Processeserlang.org(opens in a new tab)
Spotted a mistake or something missing on this page?Suggest an edit