Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions content/docs/data-modeling/drivers.mdx
Original file line numberDiff line numberDiff line change
Expand Up@@ -353,20 +353,34 @@ equivalent age-based reap.
## Memory Driver

The in-memory driver keeps records in plain in-process objects (queried via
[`mingo`](https://github.com/kofrasa/mingo)). Data is lost when the process exits.
[`mingo`](https://github.com/kofrasa/mingo)).
It is the **last-resort fallback** in dev mode: `objectstack dev` prefers native
SQLite (`better-sqlite3`), falls back to the pure-JS WASM SQLite driver if the
native binary is unavailable, and only drops to the in-memory driver if WASM also
fails to load. Set `OS_DATABASE_DRIVER=memory` to select it explicitly.

**Whether data survives the process depends on how the driver is built** (#4083):

| How it is built | Persistence |
| :--- | :--- |
| A **declared datasource** — `{ driver: 'memory' }` in a stack/app config | **Ephemeral.** Nothing is written to disk unless the declaration sets `config.persistence` — and when it does, the destination is scoped per datasource, so two memory datasources never share one file. |
| `new InMemoryDriver()` **constructed directly** | `persistence: 'auto'` — under Node that means a JSON file at `.objectstack/data/memory-driver.json`, relative to the process's working directory, reloaded on the next boot. |

Pass `persistence: false` for a driver you construct yourself and want purely in
memory — a test, for instance, which should neither depend on nor leave behind
state in the working directory. Two directly-constructed `'auto'` drivers in one
process still share that single default path.

```typescript
import { InMemoryDriver } from '@objectstack/driver-memory';

new InMemoryDriver();
new InMemoryDriver({ persistence: false }); // pure memory
new InMemoryDriver(); // 'auto' — file-backed under Node
```

<Callout type="tip">
Use the memory driver for unit tests. It requires no setup and runs instantly.
Use the memory driver for unit tests. It requires no setup and runs instantly —
with `persistence: false`, so one run cannot see what an earlier run left behind.
</Callout>

## Local Environment Runtime
Expand Down
13 changes: 12 additions & 1 deletion packages/spec/src/data/driver/memory.zod.ts
Original file line numberDiff line numberDiff line change
Expand Up@@ -216,8 +216,19 @@ export const MemoryConfigSchema = lazySchema(() => z.object({
* new InMemoryDriver({ persistence: false })
* // Custom adapter for serverless
* new InMemoryDriver({ persistence: { adapter: upstashAdapter } })
*
* **A datasource declared with `driver: 'memory'` is ephemeral unless this
* key is set (#4083).** `'auto'` is the default only for a driver you
* construct yourself. The shared datasource factory
* (`createDefaultDatasourceDriverFactory`) passes `false` when the
* declaration says nothing, so a declared memory datasource cannot silently
* become a file-backed store in the process's working directory — matching
* `objectstack dev`, which already reads an explicit memory driver as the
* user opting out of persistence. Set this key to opt back in; when you do
* without naming a `path`/`key`, the factory scopes the destination per
* datasource, so two memory datasources never share one file.
*/
persistence: MemoryPersistenceConfigSchema.or(z.literal(false)).default('auto').describe('Persistence configuration (defaults to auto-detect)'),
persistence: MemoryPersistenceConfigSchema.or(z.literal(false)).default('auto').describe('Persistence configuration (auto-detect by default; a declared memory datasource is ephemeral unless set)'),

/**
* Fields to index for faster lookups.
Expand Down
Loading