Concept
A router is an actor that fans out messages to a pool of routees using a routing strategy. You send messages to the router; it forwards them to one or more routees according to the configured strategy. Routers are not cluster-relocatable. If the host node leaves or crashes, the router and its routees are not automatically re-spawned elsewhere.Sending messages
Messages to a router must be wrapped in aBroadcast envelope. Use Tell to send:
Sending Messages
Routing strategies
Standard strategies (fire-and-forget)
These strategies never wait for replies. They are fire-and-forget; routees process messages asynchronously.- RoundRobin: Rotate through routees in a fixed order (spawn order), cycling back to the first after the last.
- Random: Pick a random routee.
- FanOut: Send a copy to every routee (default). Each routee receives the copies in the order the router handled the broadcasts.
- ConsistentHash: Route messages with the same key to the same routee (sticky sessions).
Reply-based strategies
When you need the router to observe replies and relay the first successful response back to the sender, use one of these. Outcomes are delivered asynchronously to the sender as ordinary messages (not viaAsk). The router does
not wait for the routees itself: each request is gathered on its own goroutine, so a request that nobody answers does
not delay the requests queued behind it.
- Scatter-Gather First: Sends the request to all routees concurrently. The first successful reply within the time
budget is forwarded to the original sender. Late replies are ignored. If no routee replies in time, the sender
receives a
StatusFailure. - Tail-Chopping: Probes one routee at a time (in random order). If no response arrives before the interval, sends to
the next routee. Repeats until a routee replies, all routees are tried, or the global deadline expires. First success
wins; otherwise the sender receives a
StatusFailure.
Spawning a router
UseSpawnRouter on the actor system:
Spawning a Router
- name: Router actor name
- poolSize: Number of routees to spawn (must be > 0)
- routeesKind: Actor type for routees (a pointer to a struct implementing
Actor) - opts: Router options (see below)
Router options
- WithRoutingStrategy: Set RoundRobin, Random, FanOut, or ConsistentHash. Default is FanOut.
- WithConsistentHashRouter: Use consistent-hash routing.
extractoris aMessageRoutingKeyExtractor(func(msg any) string). Messages with the same key go to the same routee. Returns empty string to fall back to random. - WithConsistentHashVirtualNodes: Virtual nodes per routee for the hash ring (default 150). Only with
WithConsistentHashRouter. - WithConsistentHashHasher: Custom hash function for the ring (default xxh3). Only with
WithConsistentHashRouter. - AsScatterGatherFirst: Use scatter-gather-first.
withinis the total time budget for any reply. - AsTailChopping: Use tail-chopping.
withinis the global deadline;intervalis the delay between successive attempts. Requiresinterval> 0 andwithin> 0; typicallyinterval<within. - WithRestartRouteeOnFailure: On routee panic: restart the routee (up to
maxRetriesattempts,timeoutapart). - WithStopRouteeOnFailure: On routee panic: stop and remove the routee from the pool. Default..
- WithResumeRouteeOnFailure: On routee panic: resume the routee (keep state, continue processing).
Examples
Examples
Control messages
Routers accept these control messages viaTell or Ask:
- GetRoutees: Usage: Query current routee names. Response:
Routees(useAsk). - AdjustRouterPoolSize: Usage: Scale pool at runtime. Response: None (fire-and-forget).
GetRoutees
GetRoutees
AdjustRouterPoolSize
- poolSize > 0: Add that many routees
- poolSize < 0: Remove that many routees
- poolSize == 0: No-op
AdjustRouterPoolSize
Handling replies (scatter-gather / tail-chopping)
For reply-based strategies, the sender receives either:- The first successful reply from a routee (as a normal message)
- A
StatusFailureif the deadline expires or all routees fail
Receive:
Handling Replies (Scatter-Gather / Tail-Chopping)
When to use
- Load balancing: RoundRobin or Random across a pool of workers
- Sticky sessions / partition affinity: ConsistentHash when messages with the same key (e.g. order ID, customer ID) must always go to the same routee
- Parallel processing: FanOut for pub/sub, cache invalidation, multi-sink processing
- Fastest responder: Scatter-Gather First when you want the first successful reply
- Controlled probing: Tail-Chopping when you prefer sequential probing with bounded fan-out
Routee supervision
When a routee panics, the router receives aPanicSignal and applies the configured directive:
- Stop (default): Terminate the routee and remove it from the pool
- Restart: Restart the routee (with retry limits)
- Resume: Keep the routee and continue processing
ctx.Shutdown()) is removed from the pool the next time the
router routes a message; no message is sent to it. When a Broadcast finds no live routee, whether the routees were
removed by the Stop directive, by scaling down or because they stopped on their own, that message goes to the
deadletter and the router shuts down.
Scaling the pool up after routees were removed always adds the requested number of routees; the new routees get fresh
names, so they never collide with the routees still in the pool.