How does Akka handle an actor's mailbox when a Kill message triggers a supervisor restart?
0 reputation · 26 Aug 2020, 00:50 UTC
0 reputation · 26 Aug 2020, 00:50 UTC
In an Akka system, an actor can be terminated by sending a Kill message, which throws an ActorKilledException and is processed by the actor's supervisor. Assuming the default supervisor strategy (which stops the actor and then restarts it), what happens to the messages that were already in the actor's mailbox at the moment the Kill was processed? Are those messages retained and available after the actor restarts, or are they discarded? Additionally, how does this behavior differ from using a Stop or PoisonPill signal, and what steps should be taken to verify that the mailbox persists across a restart when troubleshooting a failure?
26525 reputation · 26 Aug 2020, 01:10 UTC
When a Kill message is sent to an Akka actor, the actor throws an ActorKilledException. The default supervisor strategy treats this exception as a restart directive: it first stops the failing actor and then creates a new instance of the same actor.
Because the mailbox is tied to the specific actor instance, stopping the actor discards any messages that remain in its mailbox at the moment the Kill is processed. The restarted actor receives a fresh, empty mailbox; messages that were queued before the restart are not retained or replayed.
This behavior differs from other stop signals:
context.stop or a direct stop signal) – the actor stops immediately, and the entire mailbox (both preceding and following messages) is discarded.To verify that the mailbox does not persist across a Kill‑triggered restart, you can instrument the actor to log the size of its mailbox before and after handling a Kill message, and also log any messages that arrive after the restart.
preStart and postStop lifecycle hooks to record mailbox size (context.self.path and context.system.mailboxes can be used for inspection).Kill.postStop should reflect the number of messages still queued at the moment of the Kill, and the preStart log after the restart should show a mailbox size of zero.If you need to preserve certain messages across a restart, you must explicitly stash them (e.g., using Akka’s Stash trait) or forward them to a durable queue before the Kill is processed.
Use comments to ask for clarification. Post a solution as an answer.
26,525 reputation · 26 Aug 2020, 06:08 UTC
With Akka Classic the default OneForOneStrategy treats ActorKilledException as a failure, so the supervisor stops the current instance and then creates a new one. The stop operation discards the mailbox that belongs to the stopped instance; the new instance starts with a fresh mailbox. Messages that were already enqueued are not replayed unless the restart decision is made with restartMailbox = true, which is off by default.
Note that restartMailbox is a per-decision flag on the classic SupervisorStrategy and only applies to restart decisions, not to PoisonPill or explicit context.stop. It also only preserves a bounded tail of messages that were present before the stop, and requires a mailbox implementation that supports the feature. In Akka Typed the restart semantics differ and there is no equivalent mailbox carry-over.