Storage
Choose the right Crux storage capability for records, retrieval search, and workspace files.
You are wiring up memory, retrieval, a workspace, or flow state, and the feature asks for a store. Crux splits storage into three capabilities so each feature can ask for exactly what it needs. Most production apps compose all three: a RecordStore for records, a SearchStore for retrieval, and an AssetStore for large files. For Convex-specific wiring, see the Convex guide.
Which One Do I Need?
Use RecordStore for structured Crux records: memory records, flow state, eval reports, workspace file metadata, cache entries, and any Crux state that needs get, put, create, delete, and prefix list:
workspace({ id: "files", namespace, records });Use SearchStore when a feature needs dense, sparse, or lexical retrieval search, such as indexing and retrieval:
retriever({
id: "docs",
records,
search,
dense,
sparse,
});Use AssetStore when workspace content is binary or large: PDFs, images, CSVs, generated files, uploads, and oversized text:
await files.write("/outputs/report.pdf", pdfBytes, {
mimeType: "application/pdf",
});Small text and JSON can live inline in RecordStore. Binary and oversized payloads go to AssetStore. If binary data is written without an asset store, Crux throws a clear error.
Bundled Storage
| Package | Capability | Use for |
|---|---|---|
@use-crux/core/storage | inMemoryRecordStore() | Tests, local demos, non-durable JSON records |
@use-crux/core/storage | inMemorySearchStore() | Tests and local dense/sparse search |
@use-crux/core/storage | inMemoryAssetStore() | Tests and demos that need asset behavior |
@use-crux/core/storage | inMemoryStorage() | Complete in-memory { records, search, assets } bundle |
@use-crux/convex | convexRecordStore() | Durable Convex-backed JSON records |
@use-crux/convex | convexAssetStore() | Workspace binary/large files in Convex file storage |
@use-crux/upstash | upstashRedisRecordStore() | Durable Redis-backed records with native TTL |
@use-crux/upstash | upstashSearchStore() | Upstash Vector dense search by default, sparse/RRF when configured |
@use-crux/postgres | postgresSearchStore() | PostgreSQL dense, sparse, lexical, and fused retrieval search |
Bundle capabilities with storage():
import { storage } from "@use-crux/core/storage";
const appStorage = storage({
records,
search,
assets,
});Use storage.scope() when a user, tenant, session, or workspace should get isolated keys:
const userStorage = storage.scope(appStorage, `user:${userId}`);Why Three Capabilities?
The split keeps the API honest. A Redis adapter can be a RecordStore without pretending to be asset storage. Upstash Vector can be a SearchStore without owning JSON records. Convex can implement records and assets without claiming retrieval-index support.
Where To Go Next
RecordStore
JSON record storage, TTL, filters, watches, bundled adapters, and custom database implementations.
SearchStore
Dense, sparse, lexical search, capability checks, and adapter expectations.
AssetStore
Binary files, generated outputs, S3/R2/GCS-style implementations, and workspace integration.
Postgres RecordStore
Cookbook example for implementing durable JSON record storage on Postgres.
Workspace files
Use a workspace for notes, generated outputs, and approval-gated writes.
Adapter references stay under Convex storage and Upstash storage.