Skip to content

Storage

Rudder provides two key-value storages:

  • Player storage — per-player records, read and written by the owning player through the SDK. Use it for save games, settings, and client-side progress.
  • Project storage — project-global records shared by all players. It is available to module functions, the dashboard and the /game/v1 admin API, not to game clients.

Both stores are simple key-value: the key is called type (max 128 characters) and the value is data, an opaque string (max 64 KB) that is JSON by convention. Writes are upserts: writing an existing type replaces the whole data payload and increments a per-key version counter.

Each player can store up to 1000 keys, one item per type. Every SDK call requires a signed-in player.

import { createClient } from '@rudder/sdk';
const client = createClient({ projectKey: 'your-project-key' });
await client.auth.loginWithDevice();
// Write (upsert) a key
await client.storage.save('settings', JSON.stringify({ music: true, volume: 0.8 }));
await client.storage.save('checkpoint', JSON.stringify({ level: 4, score: 12500 }));
// Read: storage is a state object; load() fetches once, value holds the result
await client.storage.load();
const settings = client.storage.value?.items?.find((item) => item.type === 'settings');
// Subscribe to changes (fires immediately with the current snapshot)
const unsubscribe = client.storage.onChange(({ status, value }) => {
if (status === 'ready') console.log('storage items:', value?.items);
});
// Delete a key
await client.storage.delete('checkpoint');

Notes:

  • Writes refresh the storage state immediately; changes made elsewhere (modules, the admin API) arrive through the revision poll.
  • The TypeScript state loads the first 100 items; the C# state follows the cursor and holds all items.
  • The SDK write takes only type and data; clients cannot set an expiration. TTLs on player storage keys can only be set through the admin API.

Project storage holds records that belong to the game, not to a player: global event state, server-tuned tables, module bookkeeping (the leaderboards module keeps its last resets there). Game clients cannot read or write it. For game-facing configuration use a module such as remote_config, or expose the data through your own module’s client function.

Where it is available:

  • Module functions — the kernel API ProjectStorage.Get / Set (see Functions runtime).
  • DashboardUsers & Config → Storage: create, edit and delete keys with a JSON payload and an optional Expires At.
  • Admin API/game/v1/project-storage with the environment’s admin key.

Items carry version (incremented on every overwrite), size, updatedAt and expiresAt. Expired keys disappear from reads immediately and are deleted later by a cleanup worker.

  • Key count: 1000 keys per player, 1000 keys per project. Exceeding the cap fails the write.
  • Payload size: data is limited to 64 KB per key; type to 128 characters.
  • Overwrite semantics: an upsert replaces the entire data string — there is no partial update or merge. Read-modify-write flows should check version themselves; the server does not enforce it.
  • Expiration: expired keys are hidden from all reads and deleted later by a cleanup worker; do not rely on the exact deletion time.
  • Batch admin operations: server-side management (TTL, writing player storage, deletes) goes through the batch-only /game/v1 admin API: PUT/DELETE on /game/v1/players/storage and /game/v1/project-storage take batches of up to 100 items in one transaction.