> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goakt.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Grains

> Virtual actors with automatic activation and passivation.

## 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 the `Grain` interface:

```go theme={"theme":{"light":"github-light","dark":"dracula"}}
package actor

type Grain interface {
    OnActivate(ctx context.Context, props *GrainProps) error
    OnReceive(ctx *GrainContext)
    OnDeactivate(ctx context.Context, props *GrainProps) error
}
```

| Method           | When called                                          | Purpose                                                                            |
| ---------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
| **OnActivate**   | When the grain is loaded into memory (first message) | Initialize state or resources. Return error to prevent activation.                 |
| **OnReceive**    | For each message                                     | Handle messages. Use `ctx.Response(resp)` for Ask, `ctx.NoErr()` for Tell success. |
| **OnDeactivate** | Before the grain is removed (passivation)            | Persist state, release resources.                                                  |

## GrainContext

Inside `OnReceive`, `GrainContext` provides:

| Method                         | Purpose                               |
| ------------------------------ | ------------------------------------- |
| `Message()`                    | The message being processed           |
| `Self()`                       | Grain identity                        |
| `Response(resp)`               | Reply to an Ask                       |
| `NoErr()`                      | Signal success for Tell (no response) |
| `Err(err)`                     | Signal failure                        |
| `Unhandled()`                  | Mark message as unhandled             |
| `TellActor(name, msg)`         | Send to an actor by name              |
| `AskActor(name, msg, timeout)` | Ask an actor by name                  |
| `AskGrain(to, msg, timeout)`   | Ask another grain                     |

## Identity and messaging

Use the generic `actor.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.

```go theme={"theme":{"light":"github-light","dark":"dracula"}}
identity, err := actor.GrainOf[*UserGrain](ctx, system, "user-123")
if err != nil {
    return err
}

response, err := system.AskGrain(ctx, identity, request, time.Second)
```

When activation is needed, the framework constructs the grain as a zero value of its struct type. Put initialization
logic in `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.

<Note>
  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`.
</Note>

<Warning>
  The factory-based `GrainIdentity(ctx, name, factory, opts...)` API is deprecated. It still works, but factories that
  capture dependencies in their closure only take effect on the local node; a grain recreated or relocated elsewhere is
  always built as a zero value. Migrate to `GrainOf` with `OnActivate`-based initialization.
</Warning>

## 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

1. First message arrives → framework activates the grain (calls `OnActivate`)
2. Messages are routed to the grain's `OnReceive`
3. After idle timeout (passivation) → grain is deactivated (`OnDeactivate`)
4. 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](/actor/passivation) — Grains use passivation for idle-based deactivation
* [Actor Model](/actor/actor-model) — When to use actors vs grains
