More

Ephemeral Variables

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:

Define an actor vars as a constant value:

import { actor } from "rivetkit";

// Define vars as a constant
const counter = actor({
  state: { count: 0 },
  
  // Define ephemeral variables
  vars: { 
    lastAccessTime: 0,
    emitter: createNanoEvents()
  },
  
  actions: {
    // ...
  }
});
TypeScript

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

Using Variables

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

import { actor } from "rivetkit";
import { createNanoEvents } from "nanoevents";

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 = createNanoEvents();
    
    // 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;
    }
  }
});
TypeScript

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

Advanced

Accessing Driver Context

The createVars function receives a second parameter that provides access to driver-specific context. This allows you to access driver-specific functionality.

For example, the Redis driver exposes access to the Redis instance:

import { actor, CreateVarsContext } from "rivetkit";
import { DriverContext } from "@rivetkit/redis";

const myActor = actor({
  state: { count: 0 },

  // The second parameter provides driver-specific context
  createVars: (ctx: CreateVarsContext, driver: DriverContext) => ({ driver }),
  
  actions: {
    accessDriverFeatures: (c) => {
      // Access Redis
      const redis = c.vars.driver.redis;
	  const keyPrefix = c.vars.driver.keyPrefix;
      // ...etc...
    }
  }
});
TypeScript

Consult the documentation for each driver to learn more about their respective DriverContext types.

Suggest changes to this page