Skip to main content
Lifecycle & Config

Destroying Actors

Permanently destroy Rivet Actors and their stored state, use lifecycle cleanup hooks, and choose safe deletion patterns.

  • User account deletion
  • Ending a user session
  • Closing a room or game
  • Cleaning up temporary resources
  • GDPR/compliance data removal

Actors sleep when idle, so destruction is only needed to permanently remove data; not to save compute.

Destroying An Actor

Destroy via Action

To destroy an actor, use c.destroy() like this:

import { actor } from "rivetkit";
import { db } from "rivetkit/db";

interface UserInput {
  email: string;
  name: string;
}

const userActor = actor({
  db: db({
    onMigrate: async (db) => {
      await db.execute(`
        CREATE TABLE IF NOT EXISTS profile (
          id INTEGER PRIMARY KEY CHECK (id = 1),
          email TEXT NOT NULL,
          name TEXT NOT NULL
        );
      `);
    },
  }),
  onCreate: async (c, input: UserInput) => {
    await c.db.execute(
      "INSERT INTO profile (id, email, name) VALUES (1, ?, ?)",
      input.email,
      input.name,
    );
  },
  actions: {
    deleteAccount: (c) => {
      c.destroy();
    },
  },
});

Destroy via HTTP

Send a DELETE request to your control plane to destroy an actor. Authenticate with your Rivet token.

To find the actor ID, list the actors with that name first:

curl "https://rivet.example.com/actors?namespace={namespace}&name={actor-name}" \
  -H "Authorization: Bearer {token}"

Lifecycle Hook

Once destroyed, the onDestroy hook will be called. This can be used to clean up resources related to the actor. For example:

import { actor } from "rivetkit";
import { db } from "rivetkit/db";

interface UserInput {
  email: string;
  name: string;
}

// Example email service interface
const emailService = {
  send: async (options: { from: string; to: string; subject: string; text: string }) => {},
};

const userActor = actor({
  db: db({
    onMigrate: async (db) => {
      await db.execute(`
        CREATE TABLE IF NOT EXISTS profile (
          id INTEGER PRIMARY KEY CHECK (id = 1),
          email TEXT NOT NULL,
          name TEXT NOT NULL
        );
      `);
    },
  }),
  onCreate: async (c, input: UserInput) => {
    await c.db.execute(
      "INSERT INTO profile (id, email, name) VALUES (1, ?, ?)",
      input.email,
      input.name,
    );
  },
  onDestroy: async (c) => {
    const rows = (await c.db.execute(
      "SELECT email, name FROM profile WHERE id = 1",
    )) as { email: string; name: string }[];
    const user = rows[0];

    await emailService.send({
      from: "noreply@example.com",
      to: user.email,
      subject: "Account Deleted",
      text: `Goodbye ${user.name}, your account has been deleted.`,
    });
  },
  actions: {
    deleteAccount: (c) => {
      c.destroy();
    },
  },
});

Accessing Actor After Destroy

Once an actor is destroyed, any subsequent requests to it will fail with an actor.not_found error ({ group: "actor", code: "not_found" }). The actor’s data, including its SQLite database, is permanently deleted.

Edit this page Last updated November 10, 2026