Concept
Grains are virtual actors: identity-addressed and managed by the framework. They are activated on first message and deactivated when idle. You don’t spawn them explicitly; you send to an identity and the framework routes to the right instance.The Grain interface
Every grain must implement theGrain interface:
GrainContext
InsideOnReceive, GrainContext provides:
Identity and messaging
Use the genericactor.GrainOf function to obtain an identity. The type parameter must be a pointer to your grain
struct; the framework derives the grain kind from it, so no factory is required. Then use TellGrain or AskGrain
with that identity. The instance name (e.g., "user-123") uniquely identifies the grain within its kind.
OnActivate and supply external resources (database handles, clients, configuration) through
WithGrainDependencies; they are available from the GrainProps passed to OnActivate. This is the same construction
contract the cluster applies when it recreates or relocates a grain on another node.
Calling
GrainOf automatically registers the grain kind on the calling node. In cluster mode, nodes that can host a
grain without ever resolving it themselves (for example, targets of relocation or remote activation) must register the
kind at startup, either with RegisterGrainKind or through ClusterConfig.WithGrains.When to use grains
- Entity-per-identity patterns (users, sessions, devices)
- Large populations that are mostly idle
- When you want the framework to manage lifecycle and placement
When to use actors
- Long-lived services
- Explicit lifecycle control
- Infrastructure components
Grain lifecycle
- First message arrives → framework activates the grain (calls
OnActivate) - Messages are routed to the grain’s
OnReceive - After idle timeout (passivation) → grain is deactivated (
OnDeactivate) - Next message → grain is reactivated
Activation guarantee
In cluster mode, the system claims grain ownership in the cluster registry using an atomic put-if-absent operation before activating locally. If another node already owns the grain, requests are forwarded to that owner. If local activation fails after a successful claim, the claim is removed. When configured, the grain activation barrier delays grain activations until the cluster reaches the minimum peers quorum (or until the barrier timeout elapses).See also
- Passivation — Grains use passivation for idle-based deactivation
- Actor Model — When to use actors vs grains