Tell, Ask, or a remote send) enqueue concurrently, and the actor’s dispatcher is the single consumer that dequeues in the mailbox’s order. This is what gives each actor its single-threaded processing guarantee.
Control-plane messages such as PoisonPill travel on a separate system mailbox and always take priority, so a custom mailbox only ever handles user messages.
Setting a mailbox
PassWithMailbox as a SpawnOption:
WithMailbox, the actor uses UnboundedMailbox, a lock-free FIFO queue.
Built-in mailboxes
Unbounded FIFO
UnboundedMailboxis the default: a lock-free multi-producer, single-consumer queue with no capacity limit. It never blocks and never drops. Use it unless you have a reason not to.UnboundedSegmentedMailboxstores messages in pooled, fixed-size array segments. It keeps the unbounded, never-drop behavior but improves cache locality and holds steady-state allocations near zero, which helps actors under sustained high throughput.UnboundedFairMailboxgives each sender its own sub-queue and drains them round-robin, so a chatty sender cannot starve quieter ones. Messages from the same sender stay FIFO. Use it for multi-tenant actors or protocol handlers serving many clients.
Bounded FIFO
BoundedMailboxhas a fixed capacity and applies blocking backpressure: when full,Enqueueblocks the producer until space frees.NonBlockingBoundedMailboxhas a fixed capacity and never blocks. Its capacity is rounded up to the next power of two. When full,EnqueuereturnsErrMailboxFulland the runtime routes the excess message to the dead-letter stream.
Priority
Priority mailboxes take aPriorityFunc and dequeue the highest-priority message first:
true when msg1 should be processed before msg2. The stable variants additionally keep messages of equal priority in arrival order; the plain variants leave that order unspecified.
UnboundedPriorityMailBoxandUnboundedStablePriorityMailboxare unbounded; the stable one preserves arrival order among equal priorities.BoundedPriorityMailboxandBoundedStablePriorityMailboxadd a fixed capacity. When full,EnqueuereturnsErrMailboxFulland the excess message is dead-lettered instead of blocking the producer.
Enqueue never contends with the consumer.
When a bounded mailbox drops a message, the message is delivered to the dead-letter stream, where it can be observed. See Event Streams for how to subscribe to
Deadletter events.Choosing a mailbox
- Default to
UnboundedMailbox; move toUnboundedSegmentedMailboxfor throughput-heavy actors. - Need a memory ceiling? Use
NonBlockingBoundedMailbox(drop to dead letters) orBoundedMailbox(block the producer). - Need fairness across senders? Use
UnboundedFairMailbox. - Need priority ordering? Use a priority mailbox; pick a stable variant when equal-priority messages must keep arrival order, and a bounded variant when you also need a capacity ceiling.
Writing a custom mailbox
Implement theMailbox interface and pass it with WithMailbox:
Enqueue routes the message to the dead-letter stream. Use the built-in mailboxes in actor/ as a reference.