2026-06-11 08:37:26 -07:00
---
title: Transactions & Atomicity
slug: guides/transactions
public: true
category: guides
template: guide
order: 10
description: How Brainy keeps every write atomic — automatic per-operation transactions with rollback, and brain.transact() for atomic multi-write batches with compare-and-swap.
next:
- concepts/consistency-model
- guides/optimistic-concurrency
---
2025-11-14 10:26:23 -08:00
# Transaction System
2026-01-27 15:38:21 -08:00
**Status:** ✅ Production Ready
2025-11-14 10:26:23 -08:00
## Overview
Brainy's transaction system provides **atomic operations** with automatic rollback on failure. All operations within a transaction either succeed completely or fail completely - there are no partial failures.
### Key Benefits
- **Atomicity**: All operations succeed or all rollback
- **Consistency**: Indexes and storage remain consistent
2026-06-11 14:51:00 -07:00
- **Automatic**: Transparently used by all `brain.add()` , `brain.update()` , `brain.remove()` , and `brain.relate()` operations
2026-06-11 08:37:26 -07:00
- **Composable**: `brain.transact()` runs a multi-write batch through the same machinery as exactly one atomic commit
2025-11-14 10:26:23 -08:00
## Architecture
```
2026-06-11 08:37:26 -07:00
User Code (brain.add(), brain.update(), brain.transact(), etc.)
2026-01-27 15:38:21 -08:00
↓
2025-11-14 10:26:23 -08:00
Transaction Manager (orchestration)
2026-01-27 15:38:21 -08:00
↓
2025-11-14 10:26:23 -08:00
Operations (SaveNounMetadataOperation, SaveNounOperation, etc.)
2026-01-27 15:38:21 -08:00
↓
2026-06-11 08:37:26 -07:00
Storage Adapter (sharding, ID-first routing)
2025-11-14 10:26:23 -08:00
```
### How It Works
Every write operation in Brainy automatically uses transactions:
```typescript
// Internally, this uses a transaction
const id = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Alice', role: 'Engineer' },
type: NounType.Person
2025-11-14 10:26:23 -08:00
})
```
**Transaction Flow:**
1. **Begin Transaction** : TransactionManager creates new transaction
2. **Add Operations** : Operations added to transaction (SaveNounMetadataOperation, SaveNounOperation)
3. **Execute** : Each operation executes in sequence
4. **Commit** : All operations succeeded → changes persist
5. **Rollback** : Any operation failed → all changes reverted
### Rollback Mechanism
Each operation implements both **execute** and **undo** :
```typescript
class SaveNounMetadataOperation {
2026-01-27 15:38:21 -08:00
async execute(): Promise< void > {
// Save new metadata
await this.storage.saveNounMetadata(this.id, this.metadata)
}
async undo(): Promise< void > {
// Restore previous metadata (or delete if new entity)
if (this.previousMetadata) {
await this.storage.saveNounMetadata(this.id, this.previousMetadata)
} else {
await this.storage.deleteNounMetadata(this.id)
}
}
2025-11-14 10:26:23 -08:00
}
```
**On failure:**
- Operations rolled back in **reverse order**
- Previous state fully restored
- Indexes updated to reflect rollback
## Compatibility with Advanced Features
2026-06-11 08:37:26 -07:00
### Multi-Write Batches: `brain.transact()`
2025-11-14 10:26:23 -08:00
2026-06-11 08:37:26 -07:00
✅ **The 8.0 path for atomic multi-entity writes**
2025-11-14 10:26:23 -08:00
2026-06-11 08:37:26 -07:00
Single-operation methods each commit their own transaction. When several
writes must succeed or fail **together** , use `brain.transact()` — a
declarative batch that commits as exactly one generation, with optional
whole-store compare-and-swap and durable transaction metadata:
2025-11-14 10:26:23 -08:00
```typescript
2026-06-11 08:37:26 -07:00
const db = await brain.transact([
{ op: 'add', id: orderId, type: NounType.Document, subtype: 'order', data: 'Order #1042 ' },
{ op: 'update', id: customerId, metadata: { lastOrderAt: Date.now() }, ifRev: customer._rev },
{ op: 'relate', from: customerId, to: orderId, type: VerbType.Creates, subtype: 'purchase' }
], { meta: { author: 'order-service' } })
2025-11-14 10:26:23 -08:00
2026-06-11 08:37:26 -07:00
db.receipt.ids // resolved id per operation, in input order
2025-11-14 10:26:23 -08:00
```
**How It Works:**
2026-06-11 08:37:26 -07:00
- The batch executes through the same TransactionManager as single
operations, wrapped in the generational commit protocol: before-images are
staged and fsynced first, and the atomic manifest rename is the commit
point — a crash anywhere before it rolls back to the exact
pre-transaction bytes.
- Per-entity `ifRev` and whole-store `ifAtGeneration` provide
compare-and-swap at two granularities; any conflict rejects the entire
batch before anything is staged.
- The returned `Db` is a pinned, snapshot-isolated view of the committed
state.
See the ** [consistency model ](concepts/consistency-model.md )** for the
full guarantees (snapshot isolation, time travel, snapshots) and
**[Snapshots & Time Travel ](guides/snapshots-and-time-travel.md )** for
recipes.
2025-11-14 10:26:23 -08:00
### Sharding
✅ **Fully Compatible**
Transactions work across multiple shards:
```typescript
// Entities with different UUID prefixes go to different shards
const id1 = 'aaa00000-1111-4111-8111-111111111111' // Shard: aaa
const id2 = 'bbb00000-2222-4222-8222-222222222222' // Shard: bbb
await brain.add({ id: id1, data: { name: 'Entity A' }, type: NounType.Thing })
await brain.relate({ from: id1, to: id2, type: VerbType.RelatesTo })
// Transaction handles cross-shard atomicity automatically
```
**How It Works:**
- Sharding is transparent to transactions
- `analyzeKey()` method routes to correct shard based on UUID
- Transaction operations don't need to know about shards
- Rollback works across all shards involved
2026-01-27 15:38:21 -08:00
### ID-First Storage
2025-11-14 10:26:23 -08:00
✅ **Fully Compatible**
feat: ID-first storage architecture + remove memory-unsafe APIs (v6.0.0)
BREAKING CHANGES:
**ID-First Storage Paths**
- Direct O(1) entity access without type lookups
- Before: entities/nouns/{TYPE}/metadata/{SHARD}/{ID}.json
- After: entities/nouns/{SHARD}/{ID}/metadata.json
- Migration handled automatically on first init()
**Removed Memory-Unsafe APIs**
- Removed brain.merge() - loaded all entities into memory
- Removed brain.diff() - loaded all entities into memory
- Removed brain.data().backup() - loaded all entities into memory
- Removed brain.data().restore() - depended on backup()
- Removed CLI commands: backup, restore, cow merge
**Migration Paths**
- merge() → Use checkout() or manually copy entities with pagination
- diff() → Use asOf() with manual paginated comparison
- backup() → Use fork() for instant COW snapshots
- restore() → Use checkout() to switch to snapshot branch
Core Improvements:
- ✅ All 8 storage adapters properly call super.init()
- ✅ GraphAdjacencyIndex integration in BaseStorage.init()
- ✅ Fixed ID-first path bugs (vector.json → vectors.json)
- ✅ Fixed MemoryStorage.initializeCounts() for ID-first paths
- ✅ New VFS APIs: du(), access(), find()
- ✅ Comprehensive documentation with migration guides
Storage Adapters Fixed:
- MemoryStorage, FileSystemStorage, AzureBlobStorage
- GCSStorage, R2Storage, S3CompatibleStorage
- OPFSStorage, HistoricalStorageAdapter
Files Changed: 28 files, +1,075/-1,933 lines (net -858)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:46:11 -08:00
Transactions work with direct ID-first paths - no type routing needed!
2025-11-14 10:26:23 -08:00
```typescript
feat: ID-first storage architecture + remove memory-unsafe APIs (v6.0.0)
BREAKING CHANGES:
**ID-First Storage Paths**
- Direct O(1) entity access without type lookups
- Before: entities/nouns/{TYPE}/metadata/{SHARD}/{ID}.json
- After: entities/nouns/{SHARD}/{ID}/metadata.json
- Migration handled automatically on first init()
**Removed Memory-Unsafe APIs**
- Removed brain.merge() - loaded all entities into memory
- Removed brain.diff() - loaded all entities into memory
- Removed brain.data().backup() - loaded all entities into memory
- Removed brain.data().restore() - depended on backup()
- Removed CLI commands: backup, restore, cow merge
**Migration Paths**
- merge() → Use checkout() or manually copy entities with pagination
- diff() → Use asOf() with manual paginated comparison
- backup() → Use fork() for instant COW snapshots
- restore() → Use checkout() to switch to snapshot branch
Core Improvements:
- ✅ All 8 storage adapters properly call super.init()
- ✅ GraphAdjacencyIndex integration in BaseStorage.init()
- ✅ Fixed ID-first path bugs (vector.json → vectors.json)
- ✅ Fixed MemoryStorage.initializeCounts() for ID-first paths
- ✅ New VFS APIs: du(), access(), find()
- ✅ Comprehensive documentation with migration guides
Storage Adapters Fixed:
- MemoryStorage, FileSystemStorage, AzureBlobStorage
- GCSStorage, R2Storage, S3CompatibleStorage
- OPFSStorage, HistoricalStorageAdapter
Files Changed: 28 files, +1,075/-1,933 lines (net -858)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:46:11 -08:00
// Entities stored with direct ID-first paths
2025-11-14 10:26:23 -08:00
const personId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'John Doe' },
type: NounType.Person // → entities/nouns/{shard}/{id}/metadata.json
2025-11-14 10:26:23 -08:00
})
const orgId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Acme Corp' },
type: NounType.Organization // → entities/nouns/{shard}/{id}/metadata.json
2025-11-14 10:26:23 -08:00
})
feat: ID-first storage architecture + remove memory-unsafe APIs (v6.0.0)
BREAKING CHANGES:
**ID-First Storage Paths**
- Direct O(1) entity access without type lookups
- Before: entities/nouns/{TYPE}/metadata/{SHARD}/{ID}.json
- After: entities/nouns/{SHARD}/{ID}/metadata.json
- Migration handled automatically on first init()
**Removed Memory-Unsafe APIs**
- Removed brain.merge() - loaded all entities into memory
- Removed brain.diff() - loaded all entities into memory
- Removed brain.data().backup() - loaded all entities into memory
- Removed brain.data().restore() - depended on backup()
- Removed CLI commands: backup, restore, cow merge
**Migration Paths**
- merge() → Use checkout() or manually copy entities with pagination
- diff() → Use asOf() with manual paginated comparison
- backup() → Use fork() for instant COW snapshots
- restore() → Use checkout() to switch to snapshot branch
Core Improvements:
- ✅ All 8 storage adapters properly call super.init()
- ✅ GraphAdjacencyIndex integration in BaseStorage.init()
- ✅ Fixed ID-first path bugs (vector.json → vectors.json)
- ✅ Fixed MemoryStorage.initializeCounts() for ID-first paths
- ✅ New VFS APIs: du(), access(), find()
- ✅ Comprehensive documentation with migration guides
Storage Adapters Fixed:
- MemoryStorage, FileSystemStorage, AzureBlobStorage
- GCSStorage, R2Storage, S3CompatibleStorage
- OPFSStorage, HistoricalStorageAdapter
Files Changed: 28 files, +1,075/-1,933 lines (net -858)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:46:11 -08:00
// Type changes handled atomically (type is just metadata)
2025-11-14 10:26:23 -08:00
await brain.update({
2026-01-27 15:38:21 -08:00
id: personId,
type: NounType.Organization, // Type change
data: { name: 'Doe Corp' }
2025-11-14 10:26:23 -08:00
})
```
**How It Works:**
feat: ID-first storage architecture + remove memory-unsafe APIs (v6.0.0)
BREAKING CHANGES:
**ID-First Storage Paths**
- Direct O(1) entity access without type lookups
- Before: entities/nouns/{TYPE}/metadata/{SHARD}/{ID}.json
- After: entities/nouns/{SHARD}/{ID}/metadata.json
- Migration handled automatically on first init()
**Removed Memory-Unsafe APIs**
- Removed brain.merge() - loaded all entities into memory
- Removed brain.diff() - loaded all entities into memory
- Removed brain.data().backup() - loaded all entities into memory
- Removed brain.data().restore() - depended on backup()
- Removed CLI commands: backup, restore, cow merge
**Migration Paths**
- merge() → Use checkout() or manually copy entities with pagination
- diff() → Use asOf() with manual paginated comparison
- backup() → Use fork() for instant COW snapshots
- restore() → Use checkout() to switch to snapshot branch
Core Improvements:
- ✅ All 8 storage adapters properly call super.init()
- ✅ GraphAdjacencyIndex integration in BaseStorage.init()
- ✅ Fixed ID-first path bugs (vector.json → vectors.json)
- ✅ Fixed MemoryStorage.initializeCounts() for ID-first paths
- ✅ New VFS APIs: du(), access(), find()
- ✅ Comprehensive documentation with migration guides
Storage Adapters Fixed:
- MemoryStorage, FileSystemStorage, AzureBlobStorage
- GCSStorage, R2Storage, S3CompatibleStorage
- OPFSStorage, HistoricalStorageAdapter
Files Changed: 28 files, +1,075/-1,933 lines (net -858)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 16:46:11 -08:00
- Type information stored in metadata.noun field
- Storage layer uses O(1) ID-first path construction
2026-01-27 15:38:21 -08:00
- No type cache needed (removed in a previous version)
2025-11-14 10:26:23 -08:00
- Type counters adjusted on commit/rollback
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
- 40x faster path lookups (eliminates 42-type search)
2025-11-14 10:26:23 -08:00
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
### Storage Adapter Interface
2025-11-14 10:26:23 -08:00
✅ **Fully Compatible**
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
Transactions go through the `StorageAdapter` interface, so both shipped adapters (filesystem, memory) and any custom plugin adapter inherit the same atomicity guarantees:
2025-11-14 10:26:23 -08:00
```typescript
const brain = new Brainy({
feat(8.0): API simplification — remove neural()/Db.search, one storage `path` key, integration→0
8.0 RC cleanup toward "one place per thing, zero-config, no deprecation":
- Remove the `brain.neural()` clustering namespace (ImprovedNeuralAPI + the dead
legacy NeuralAPI + the neural CLI + neural-only types). Similarity is `find({vector})`
/ `similar({to})`; attribute grouping is the aggregation `GROUP BY` engine. The separate
entity-extraction / smart-import feature (NeuralImport, NeuralEntityExtractor, SmartExtractor,
NaturalLanguageProcessor, `brain.extract()`/`brain.nlp()`) is kept.
- Remove `Db.search()`; `find()` is the one query verb (accepts a bare string or FindParams).
Fix the bundled MCP client, which called a non-existent `brain.search(query, limit)` →
now `find({ query, limit })`.
- Storage config: collapse to one canonical top-level `path` key. The pre-8.0 aliases
(`rootDirectory`, `options.*`, `fileSystemStorage.*`) are removed and now THROW with the
exact rename instead of silently defaulting to `./brainy-data` on upgrade. A single resolver
feeds createStorage, the 7.x→8.0 migration probe, and the plugin-factory handoff, so a native
storage provider resolves the identical root (no split-brain).
- Fix `similar({ threshold })`: the min-similarity filter was silently dropped; it is now
applied as a post-filter on `result.score` (the documented way to bound semantic results).
- Fix `vfs.rename()` on a directory: child path updates spread the entity vector into `update()`
and failed dimension validation; they are metadata-only updates now.
- Fix `vfs.move()`: copy+delete orphaned the content-addressed content blob (the destination
shared the source hash, then unlink removed it). `move()` now delegates to `rename()` — an
in-place path change that preserves the blob and the entity id, for files and directories.
- Fix streaming import: the bulk fast path never flushed mid-import nor signalled queryability.
Entity writes are now chunked by a progressive flush interval (100 → 1000 → 5000); each chunk
flushes and emits `progress.queryable`, so imported data is queryable during the import.
- Sweep all docs, comments, and JSDoc for the removed/changed APIs.
Integration suite: 49 files / 588 passed / 0 failed. Unit: 80 files / 1456 passed, no type errors.
2026-06-20 13:31:11 -07:00
storage: { type: 'filesystem', path: './data' }
2025-11-14 10:26:23 -08:00
})
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
await brain.add({ data: { name: 'Entity' }, type: NounType.Thing })
2025-11-14 10:26:23 -08:00
```
**How It Works:**
- Transactions operate through `StorageAdapter` interface
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
- Custom adapters registered via the plugin system implement the same interface
- Atomicity guaranteed at the write-coordinator level
- Read-after-write consistency maintained inside a single Brainy process
2025-11-14 10:26:23 -08:00
## Examples
### Basic Add Operation
```typescript
import { Brainy } from '@soulcraft/brainy '
import { NounType } from '@soulcraft/brainy/types '
const brain = new Brainy()
await brain.init()
// Automatically uses transaction
const id = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Alice', role: 'Engineer' },
type: NounType.Person
2025-11-14 10:26:23 -08:00
})
// If add fails, all changes rolled back automatically
```
### Update with Type Change
```typescript
// Original entity
const id = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'John Smith', category: 'individual' },
type: NounType.Person
2025-11-14 10:26:23 -08:00
})
// Update with type change (atomic)
await brain.update({
2026-01-27 15:38:21 -08:00
id,
type: NounType.Organization, // Type change
data: { name: 'Smith Corp', category: 'business' }
2025-11-14 10:26:23 -08:00
})
// If update fails, original type and data restored
```
### Creating Relationships
```typescript
const personId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Alice' },
type: NounType.Person
2025-11-14 10:26:23 -08:00
})
const projectId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Project X' },
type: NounType.Thing
2025-11-14 10:26:23 -08:00
})
// Create relationship (atomic)
await brain.relate({
2026-01-27 15:38:21 -08:00
from: personId,
to: projectId,
type: VerbType.WorksOn
2025-11-14 10:26:23 -08:00
})
// If relate fails, no partial relationship created
```
### Batch Operations
```typescript
// Multiple operations, all atomic
for (let i = 0; i < 100 ; i + + ) {
2026-01-27 15:38:21 -08:00
await brain.add({
data: { name: `Entity ${i}` , index: i },
type: NounType.Thing
})
2025-11-14 10:26:23 -08:00
}
// Each add() is a separate transaction
// If any add fails, only that specific add is rolled back
```
### Delete with Cascade
```typescript
const personId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Bob' },
type: NounType.Person
2025-11-14 10:26:23 -08:00
})
const projectId = await brain.add({
2026-01-27 15:38:21 -08:00
data: { name: 'Project Y' },
type: NounType.Thing
2025-11-14 10:26:23 -08:00
})
await brain.relate({
2026-01-27 15:38:21 -08:00
from: personId,
to: projectId,
type: VerbType.WorksOn
2025-11-14 10:26:23 -08:00
})
// Delete person (atomic - deletes entity + relationships)
2026-06-11 14:51:00 -07:00
await brain.remove(personId)
2025-11-14 10:26:23 -08:00
// If delete fails, both entity and relationships remain
```
## Error Handling
Transactions automatically handle errors and rollback:
```typescript
try {
2026-01-27 15:38:21 -08:00
await brain.add({
data: { name: 'Test Entity' },
type: NounType.Thing,
vector: [1, 2, 3] // Wrong dimension → error
})
2025-11-14 10:26:23 -08:00
} catch (error) {
2026-01-27 15:38:21 -08:00
// Transaction automatically rolled back
// No partial data in storage or indexes
console.error('Add failed:', error.message)
2025-11-14 10:26:23 -08:00
}
```
**Common Error Scenarios:**
- **Invalid vector dimension**: Automatic rollback
- **Type validation failure**: Automatic rollback
- **Storage write failure**: Automatic rollback
- **Index update failure**: Automatic rollback
## Performance Considerations
### Transaction Overhead
2026-06-11 08:37:26 -07:00
**What a transaction costs:**
- A typical single-operation write wraps 2-8 operations (metadata + data + indexes) in one transaction
- The overhead is bookkeeping (operation objects + undo state), not extra I/O on the success path
- Rollback cost is proportional to the operations already applied (each is undone in reverse order)
2025-11-14 10:26:23 -08:00
**Optimization:**
- Operations executed sequentially (not parallel) for consistency
- Rollback only happens on failure (success path is fast)
- Index updates batched within transaction
2026-06-11 08:37:26 -07:00
### Auditing Committed Batches
Every committed `brain.transact()` batch is recorded in the transaction
log, newest first:
2025-11-14 10:26:23 -08:00
```typescript
2026-06-11 08:37:26 -07:00
await brain.transact(ops, { meta: { author: 'import-job' } })
const entries = await brain.transactionLog({ limit: 10 })
// [{ generation: 1042, timestamp: 1765432100000, meta: { author: 'import-job' } }]
2025-11-14 10:26:23 -08:00
```
2026-06-11 08:37:26 -07:00
Single-operation writes advance the generation counter but do not append
log entries — see the [consistency model ](concepts/consistency-model.md )
for the history-granularity contract.
2025-11-14 10:26:23 -08:00
## Best Practices
### 1. Let Brainy Handle Transactions
```typescript
// ✅ Recommended: Use Brainy's API (transactions automatic)
await brain.add({ data, type })
await brain.update({ id, data })
2026-06-11 14:51:00 -07:00
await brain.remove(id)
2025-11-14 10:26:23 -08:00
// ❌ Avoid: Direct storage access bypasses transactions
2026-01-27 15:38:21 -08:00
await brain.storage.saveNoun(noun) // No transaction protection
2025-11-14 10:26:23 -08:00
```
### 2. Handle Errors Gracefully
```typescript
// ✅ Recommended: Catch errors, transaction rolls back automatically
try {
2026-01-27 15:38:21 -08:00
const id = await brain.add({ data, type })
return id
2025-11-14 10:26:23 -08:00
} catch (error) {
2026-01-27 15:38:21 -08:00
console.error('Add failed, rolled back:', error)
// Decide how to handle (retry, log, alert user)
2025-11-14 10:26:23 -08:00
}
```
### 3. Validate Before Operations
```typescript
// ✅ Recommended: Validate early to avoid unnecessary rollbacks
if (!isValidVector(vector, brain.dimension)) {
2026-01-27 15:38:21 -08:00
throw new Error(`Vector must have ${brain.dimension} dimensions` )
2025-11-14 10:26:23 -08:00
}
await brain.add({ data, type, vector })
```
2026-06-11 08:37:26 -07:00
### 4. Batch Related Writes with `transact()`
2025-11-14 10:26:23 -08:00
```typescript
2026-06-11 08:37:26 -07:00
// ✅ Recommended: writes that must land together go in one batch
await brain.transact([
{ op: 'add', id: orderId, type: NounType.Document, subtype: 'order', data: 'Order #1042 ' },
{ op: 'relate', from: customerId, to: orderId, type: VerbType.Creates, subtype: 'purchase' }
])
// ❌ Avoid: sequential single operations when partial application is unacceptable
const id = await brain.add({ ... }) // commits alone
await brain.relate({ ... }) // a crash here leaves the entity unlinked
2025-11-14 10:26:23 -08:00
```
### 5. Understand Atomicity Guarantees
**What Transactions GUARANTEE:**
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
- ✅ Atomicity within a single Brainy process
2025-11-14 10:26:23 -08:00
- ✅ Consistent state across all indexes
- ✅ Automatic rollback on failure
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
- ✅ Works with all storage adapters (filesystem, memory, custom plugin adapters)
2025-11-14 10:26:23 -08:00
**What Transactions DON'T Provide:**
- ❌ Two-phase commit across multiple Brainy instances
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
- ❌ Distributed locking across processes
2025-11-14 10:26:23 -08:00
- ❌ Cross-datacenter ACID guarantees
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
**Design:** Transactions ensure atomicity at the **write-coordinator level** inside one process. Cross-instance coordination, if you need it, lives in your service layer.
2025-11-14 10:26:23 -08:00
## Testing Transactions
### Unit Tests
```typescript
import { describe, it, expect } from 'vitest'
import { Brainy } from '@soulcraft/brainy '
describe('Transaction Tests', () => {
2026-01-27 15:38:21 -08:00
it('should rollback on failure', async () => {
const brain = new Brainy()
await brain.init()
const id1 = await brain.add({ data: { name: 'Entity 1' }, type: NounType.Thing })
try {
await brain.add({
data: null as any, // Invalid - will fail
type: NounType.Thing
})
} catch (e) {
// Expected failure
}
// First entity should still exist (rollback didn't affect it)
const entity1 = await brain.get(id1)
expect(entity1).toBeTruthy()
})
2025-11-14 10:26:23 -08:00
})
```
### Integration Tests
See `tests/transaction/integration/` for comprehensive integration tests covering:
- Sharding integration (`sharding-transactions.test.ts` )
2026-06-11 08:37:26 -07:00
- Type-aware integration (`typeaware-transactions.test.ts` )
The atomicity guarantees of `brain.transact()` — including crash recovery
through the real recovery path — are proven in
`tests/integration/db-mvcc.test.ts` .
2025-11-14 10:26:23 -08:00
## Troubleshooting
### High Rollback Rate
2026-06-11 08:37:26 -07:00
**Symptom:** a high share of writes throw and roll back
2025-11-14 10:26:23 -08:00
**Possible Causes:**
1. Invalid vector dimensions
2. Type validation errors
3. Storage write failures (disk full, network issues)
4. Index corruption
**Solutions:**
- Validate data before operations
- Check storage adapter health
- Monitor disk space and network connectivity
- Review error logs for patterns
### Slow Transaction Performance
**Symptom:** Operations take > 100ms per transaction
**Possible Causes:**
1. Large metadata objects
2. Remote storage latency
3. Many indexes enabled
4. Disk I/O bottleneck
**Solutions:**
- Optimize metadata size
- Use local caching for remote storage
- Disable unused indexes
- Use SSD storage
## Architecture Details
### Transaction Lifecycle
```
1. BEGIN
2026-01-27 15:38:21 -08:00
↓
2025-11-14 10:26:23 -08:00
2. ADD OPERATIONS
2026-01-27 15:38:21 -08:00
- SaveNounMetadataOperation
- SaveNounOperation
- UpdateGraphIndexOperation
↓
2025-11-14 10:26:23 -08:00
3. EXECUTE (sequential)
2026-01-27 15:38:21 -08:00
- Execute operation 1 → Success
- Execute operation 2 → Success
- Execute operation 3 → FAILURE
↓
2025-11-14 10:26:23 -08:00
4. ROLLBACK (reverse order)
2026-01-27 15:38:21 -08:00
- Undo operation 2
- Undo operation 1
↓
2025-11-14 10:26:23 -08:00
5. THROW ERROR
```
### Operation Types
| Operation | Description | Undo Behavior |
|-----------|-------------|---------------|
| `SaveNounMetadataOperation` | Save entity metadata | Restore previous metadata or delete if new |
| `SaveNounOperation` | Save entity data | Restore previous data or delete if new |
| `UpdateGraphIndexOperation` | Update graph index | Restore previous index state |
| `SaveVerbMetadataOperation` | Save relationship metadata | Restore previous metadata or delete if new |
| `SaveVerbOperation` | Save relationship data | Restore previous data or delete if new |
### Storage Adapter Integration
Transactions use the `StorageAdapter` interface:
```typescript
interface StorageAdapter {
2026-01-27 15:38:21 -08:00
saveNounMetadata(id: string, metadata: NounMetadata): Promise< void >
saveNoun(noun: Noun): Promise< void >
deleteNounMetadata(id: string): Promise< void >
deleteNoun(id: string): Promise< void >
// ... other methods
2025-11-14 10:26:23 -08:00
}
```
docs(8.0): Phase F — deep clean across 21 docs
Aligned every public doc to the 8.0 contract: filesystem + memory adapters
only, vector index provider terminology (config.vector with recall +
quantization + persistMode knobs), no cloud storage adapters, no closed-
source product names.
Tier 1 — heavier rewrites:
- docs/architecture/storage-architecture.md
- docs/architecture/data-storage-architecture.md
- docs/architecture/distributed-storage.md DELETED — content was 100%
cloud-coordination examples with no 8.0 substance.
- docs/guides/distributed-system.md DELETED — same reason; no inbound refs.
- docs/SCALING.md rewritten for single-node guidance.
- docs/PLUGINS.md, docs/augmentations/{COMPLETE-REFERENCE,README}.md:
HnswProvider→VectorIndexProvider, hnsw→vector key.
- docs/PERFORMANCE.md, docs/BATCHING.md cloud-detection + sharding
sections replaced with single-node vector tuning + filesystem framing.
Tier 2 — surgical renames + cloud-section deletions:
- architecture/{index,initialization-and-rebuild,overview}.md
- transactions.md, DEVELOPER_LEARNING_PATH.md
- vfs/{VFS_API_GUIDE,COMMON_PATTERNS}.md
- api/README.md, guides/{inspection,import-flow}.md
Tier 3 — light edits:
- docs/README.md, architecture/augmentation-system-audit.md
MIGRATION-V3-TO-V4.md untouched (internal migration doc, no stale terms).
2026-06-09 16:13:35 -07:00
**Key Insight:** Both shipped storage adapters (filesystem, memory) — and any custom plugin adapter — implement this interface. Transactions work with **any** storage adapter automatically.
2025-11-14 10:26:23 -08:00
## Additional Resources
2026-06-11 08:37:26 -07:00
- **Unit Tests:** `tests/transaction/Transaction.test.ts` , `tests/transaction/TransactionManager.test.ts`
- **Integration Tests:** `tests/transaction/integration/`
- **MVCC Proofs:** `tests/integration/db-mvcc.test.ts` (atomicity, CAS, crash recovery for `brain.transact()` )
- **Consistency Model:** [docs/concepts/consistency-model.md ](concepts/consistency-model.md )
2025-11-14 10:26:23 -08:00
## Summary
2026-06-11 08:37:26 -07:00
Brainy's transaction system provides **production-ready atomic operations** with automatic rollback. Every single-operation write is transactional out of the box, and `brain.transact()` extends the same guarantee to multi-write batches — one atomic commit, with compare-and-swap and durable transaction metadata.
2025-11-14 10:26:23 -08:00
**Key Takeaways:**
2026-06-11 08:37:26 -07:00
- ✅ **Automatic** : No manual transaction management needed for single operations
- ✅ **Atomic** : All operations succeed or all rollback — per operation and per `transact()` batch
2025-11-14 10:26:23 -08:00
- ✅ **Compatible** : Works with all storage adapters and features
2026-06-11 08:37:26 -07:00
- ✅ **Coordinated** : Per-entity `ifRev` and whole-store `ifAtGeneration` CAS reject conflicting batches before anything is staged
2025-11-14 10:26:23 -08:00
2026-06-11 14:51:00 -07:00
Start using transactions today - they're already built into `brain.add()` , `brain.update()` , `brain.remove()` , and `brain.relate()` — and reach for `brain.transact()` whenever several writes must land together.