# Ephemeral Variables

> Source: `src/content/docs/actors/ephemeral-variables.mdx`
> Canonical URL: https://rivet.dev/docs/actors/ephemeral-variables
> Description: In addition to persisted state, Rivet provides a way to store ephemeral data that is not saved to permanent storage using `vars`. This is useful for temporary data that only needs to exist while the actor is running or data that cannot be serialized.

---

`vars` is designed to complement `state`, not replace it. Most actors should use both: `state` for critical business data and `vars` for ephemeral or non-serializable data.

## Initializing Variables

There are two ways to define an actor's initial vars:

### Static Initial Variables

Define an actor vars as a constant value:

```typescript
import { actor } from "rivetkit";

// Mock event emitter for demonstration
interface EventEmitter {
  on: (event: string, callback: (data: unknown) => void) => void;
  emit: (event: string, data: unknown) => void;
}

function createEventEmitter(): EventEmitter {
  const listeners: Record<string, ((data: unknown) => void)[]> = {};
  return {
    on: (event, callback) => {
      listeners[event] = listeners[event] || [];
      listeners[event].push(callback);
    },
    emit: (event, data) => {
      listeners[event]?.forEach(cb => cb(data));
    },
  };
}

// Define vars as a constant
const counter = actor({
  state: { count: 0 },

  // Define ephemeral variables
  vars: {
    lastAccessTime: 0,
    emitter: createEventEmitter(),
  },

  actions: {
    increment: c => ++c.state.count,
  },
});
```

This value will be cloned for every new actor using `structuredClone`.

### Dynamic Initial Variables

Create actor state dynamically on each actors' start:

```typescript
import { actor } from "rivetkit";

// Mock event emitter for demonstration
interface EventEmitter {
  on: (event: string, callback: (data: unknown) => void) => void;
  emit: (event: string, data: unknown) => void;
}

function createEventEmitter(): EventEmitter {
  const listeners: Record<string, ((data: unknown) => void)[]> = {};
  return {
    on: (event, callback) => {
      listeners[event] = listeners[event] || [];
      listeners[event].push(callback);
    },
    emit: (event, data) => {
      listeners[event]?.forEach(cb => cb(data));
    },
  };
}

// Define vars with initialization logic
const counter = actor({
  state: { count: 0 },

  // Define vars using a creation function
  createVars: () => {
    return {
      lastAccessTime: Date.now(),
      emitter: createEventEmitter(),
    };
  },

  actions: {
    increment: c => ++c.state.count,
  },
});
```

If accepting arguments to `createVars`, you **must** define the types: `createVars(c: CreateVarsContext, driver: any)`

Otherwise, the return type will not be inferred and `c.vars` will be of type `unknown`.

## Using Variables

Vars can be accessed and modified through the context object with `c.vars`:

```typescript
import { actor } from "rivetkit";

// Mock event emitter for demonstration
interface EventEmitter {
  on: (event: string, callback: (data: number) => void) => void;
  emit: (event: string, data: number) => void;
}

function createEventEmitter(): EventEmitter {
  const listeners: Record<string, ((data: number) => void)[]> = {};
  return {
    on: (event, callback) => {
      listeners[event] = listeners[event] || [];
      listeners[event].push(callback);
    },
    emit: (event, data) => {
      listeners[event]?.forEach(cb => cb(data));
    },
  };
}

const counter = actor({
  // Persistent state - saved to storage
  state: { count: 0 },

  // Create ephemeral objects that won't be serialized
  createVars: () => {
    // Create an event emitter (can't be serialized)
    const emitter = createEventEmitter();

    // Set up event listener directly in createVars
    emitter.on("count-changed", newCount => {
      console.log(`Count changed to: ${newCount}`);
    });

    return { emitter };
  },

  actions: {
    increment: c => {
      // Update persistent state
      c.state.count += 1;

      // Use non-serializable emitter
      c.vars.emitter.emit("count-changed", c.state.count);

      return c.state.count;
    },
  },
});
```

## When to Use `vars` vs `state`

In practice, most actors will use both: `state` for critical business data and `vars` for ephemeral or non-serializable data.

Use `vars` when:

- You need to store temporary data that doesn't need to survive restarts
- You need to maintain runtime-only references that can't be serialized (database connections, event emitters, class instances, etc.)

Use `state` when:

- The data must be preserved across actor sleeps, restarts, updates, or crashes
- The information is essential to the actor's core functionality and business logic

_Source doc path: /docs/actors/ephemeral-variables_
