Skip to content

Actor Mailbox Loop

Concurrency method — instantiates Message-Mediated State Coordination

Gives each actor private state and a personal mailbox it drains one message at a time, so cross-actor effects happen only through addressed messages and never through shared memory.

An actor is a unit of computation that owns private state, answers to an address, and runs a single loop forever: take the next message from its mailbox, process it to completion — updating its own state and perhaps sending messages to other actors' addresses — then take the next. The one idea that makes it this mechanism and not its siblings: because one actor processes its own mailbox strictly one message at a time, its state is never touched by two things at once, so concurrency safety comes from serialization inside the boundary rather than from locks around shared data. No other component can reach in; the only way to affect an actor is to send its address a message and wait your turn in its queue.

Example

A multiplayer game server models every player, monster, and room as its own actor with private state — health, position, inventory. During a raid, effects for one boss actor arrive near-simultaneously: three players land hits, a healer's spell lands, and the boss's own AI tick fires. Nothing locks the boss's health field. Each effect is a message dropped into the boss actor's mailbox, and the boss's loop applies them in arrival order, one at a time: hit (−40), hit (−35), heal (+50), then the AI tick decides to enrage. Because no two updates ever run concurrently, health can never be corrupted by a lost update, and there is no lock to deadlock. When the boss needs to affect a player it does not read the player's health — it sends that player actor a message at their address. The outcome: tens of thousands of entities update in parallel across CPU cores, yet each individual entity stays internally consistent because its own loop is single-threaded.

How it works

  • One mailbox, one consumer. Each actor has exactly one mailbox and exactly one loop draining it; messages from many senders are merged into a single stream the actor consumes at its own pace.
  • Process to completion. A message is handled fully before the next is taken, so an actor never observes its own state mid-update from another message.
  • Address, don't reach. Actors hold each other's addresses, never references to each other's state; the only verb across the boundary is "send," which makes participants relocatable and location-transparent.
  • Behaviour can swap. After a message an actor may change how it will handle the next one (become) — same address, new behaviour — without exposing any of that to the outside.

Tuning parameters

  • Mailbox discipline — strict FIFO versus priority or selective receive. Priority lets urgent messages jump the line but can starve ordinary ones and complicates causal ordering.
  • Actor granularity — one actor per entity versus one per aggregate. Fine granularity maximizes parallelism but multiplies message traffic and scheduling overhead.
  • Supervision strategy — what happens when a handler throws: restart the actor (fresh or with recovered state), stop it, or escalate to a parent. This governs how a fault in one boundary is contained.
  • Blocking stance — whether a handler may block on I/O inside the loop. Blocking stalls the whole mailbox, so the discipline is non-blocking handlers that send themselves a message when slow work returns.

When it helps, and when it misleads

Its strength is that it makes data races structurally impossible within an actor, turns "who holds the lock" into "who has the address," and gives a natural unit of failure and restart. It scales because millions of tiny single-threaded loops can be scheduled across cores without shared-memory contention.

Its failure modes follow from the same design. The mailbox is a queue, so a slow or blocked handler grows an unbounded backlog unless the mailbox is capped — and capping it is Bounded Mailbox or Queue's job, not this one. Serialization inside one actor is also a throughput ceiling: a "hot" actor that every message must pass through becomes the bottleneck the whole system waits on. And the model tempts a classic misuse — recreating shared memory by making one actor a global store everyone queries synchronously, which reintroduces exactly the coupling the boundary was meant to remove. The discipline is to keep actors small, handlers non-blocking, and cross-actor reads rare, and to remember the isolation only holds if nothing smuggles a shared mutable reference inside a message.[n1]

How it implements the components

  • participant_state_boundary — the actor is the boundary: private in-memory state that no other party can read or mutate except by sending a message.
  • address_or_endpoint_namespace — every actor has a stable address, and sending to that address is the sole way to reach it, which is what makes participants addressable and relocatable.
  • ordering_and_concurrency_policy — the single-consumer loop is the concurrency policy: per-actor serialization, arrival-order processing, no locks.

It does not define message shapes or their evolution (message_contract, schema_version_negotiation — see Message Schema Registry), cap the mailbox against overload (backpressure_and_capacity_rule — see Bounded Mailbox or Queue), or decide what a given message means and whether to honour it (message_intent_taxonomy, receiver_handler_rule — see Command Message Handler).

Editorial Notes

Form Classification

Form family: Control, Automation & Runtime

Rationale: Each actor executes a live loop that drains addressed messages serially, processes one to completion, updates private state, and may change subsequent behavior, so its operative form is runtime execution and control.

Nearest alternative: Structure, Architecture & Configuration — Private state and one mailbox per actor define the topology, but the serial drain-and-handle loop is the mechanism that enforces isolation and ordering during operation.

Review outcome: Adjudicated after independent review; high confidence.

Origin Attribution

Primary origin: Computer Science & Software Engineering

Origin pattern: Single lineage

Present-day reach: Specialized

Rationale: Actors with private state, addresses, one-message-at-a-time mailboxes, behavior switching, and supervision are canonical concurrent and distributed-computing constructs.

Review resolution: The actor mailbox is a canonical specialized computer-science mechanism. Cybernetic analogy is useful background but does not constitute a materially independent origin, so the more conservative no-alternate classification is retained.

Review outcome: Reconciled after independent review; high confidence.

Notes

The mailbox in this mechanism is assumed unbounded and in-memory; a real system always makes it finite — a separate decision handed to Bounded Mailbox or Queue — and often makes it survive a crash, handed to Durable Queue with Acknowledgement. Keeping those orthogonal is deliberate: this loop defines isolation and ordering; capacity and durability are policies layered onto its mailbox.

[n1] The share-nothing principle — participants share no mutable memory and communicate only by copying data into messages. The actor model's guarantees collapse if a message carries a reference to mutable state both sender and receiver can then touch, so payloads must be immutable or copied.