Reentrancy
Overview
Reentrancy is the ability of an actor to process new messages while it is waiting for a response from another actor. In the default, non-reentrant model, an actor handles one message at a time: if it sends a request and waits for a reply, its mailbox is effectively blocked until that reply arrives. With reentrancy enabled, the actor can keep processing other messages and handle the reply later via a continuation (callback), so the mailbox stays responsive.
The default: one message at a time
In the actor model, each actor has a mailbox and processes messages sequentially. That gives you a simple mental model and avoids races on the actorβs state. As long as the handler runs to completion without waiting on external replies, this works well. The problem appears when an actor needs to ask another actor for something: if it blocks until the response comes back, it cannot process any other message in the meantime. The actor (and its mailbox) is stuck until the response arrives or times out.
What reentrancy changes
When reentrancy is enabled, the actor can issue an async request to another actor and register a continuation. The runtime does not block the actorβs message loop: as soon as the request is sent, the actor can move on to the next message. When the response (or error) arrives, the runtime invokes the continuation with that result. So the actor can have multiple requests in flight and still process new messages; responses are handled by their continuations, not by blocking in the middle of a handler.
In other words
With reentrancy, an actor can:
Send async requests to other actors (
RequestorRequestName)Continue processing new messages while waiting for responses
Handle responses via continuations (callbacks) when they arrive
Avoid blocking the mailbox on requestβresponse round-trips
Without reentrancy, the actor processes messages strictly one at a time; if it waits for a reply, nothing else is processed until that reply (or timeout). With reentrancy, multiple pending requests can be outstanding and the actor remains responsive to new work.
Trade-off
Reentrancy trades strict single-threaded-by-message safety for better concurrency and responsiveness. While a continuation is running, the actorβs state may have changed because other messages were processed in between. You must design your continuations with that in mind (e.g. avoid assuming state that might be stale, or use request correlation ids to match responses to the right logical operation). When used carefully, reentrancy lets you build responsive actors that coordinate with others without blocking the mailbox.
Importance
Traditional actor model (no reentrancy):
With reentrancy:
Benefits:
Higher throughput: Don't block on async operations
Better resource utilization: Process messages while waiting
Responsive actors: Handle new messages immediately
Concurrent workflows: Multiple requests in flight
Modes
GoAkt provides three reentrancy modes:
Off (Default)
No reentrancy support. Async requests not allowed.
AllowAll
Allow concurrent request handling. New messages processed while requests pending.
Behavior:
Multiple async requests can be in flight
New messages processed immediately
Continuations run when responses arrive
No ordering guarantees for completion
Use when:
Order of completion doesn't matter
Higher throughput needed
Independent requests
Stateless operations
StashNonReentrant
Behavior:
One request at a time
New messages stashed until request completes
Continuations run when response arrives
Sequential processing maintained
Use when:
Order matters
Stateful operations
Need sequential consistency
Avoid race conditions
Get Started
Reentrancy is enabled for actor during their creation using the WithReentrancy SpawnOption.
Once the reentrancy option is properly configured, the feature can be used through the following methods available on the ReceiveContext:
Request: A non-blocking counterpart ofAsk. This method can only be used locally or within a single-node actor system.RequestName: Similar toRequest, but location-transparent.
Example
Request Options
Timeout
This help to set timeout for individual requests:
Reentrancy Mode
This helps override reentrancy mode for specific requests:
Cancellation
Inflight reentrant requests can be cancelled:
Best Practices
Handle errors in continuations
Set request timeouts
Cancel requests when no longer needed
Use appropriate reentrancy mode
Keep continuations short
Don't block in continuations
Don't forget error handling
Don't use without timeouts
Don't access actor state unsafely
Don't leak request handles
Common Pitfalls
Reentrancy often causes bugs that are:
Hard to reproduce
Sensitive to timing
Mistaken for βdistributed system issuesβ
Typical mistakes include:
Assuming state is unchanged after an await
Updating shared state in multiple message handlers
Performing multi-step workflows without protection
These bugs are logical, not technical β the system is doing exactly what it was told.
Last updated