The old config-generation subsystem (src/config/ + autoConfiguration.ts) was
superseded during the 8.0 rework and never wired into init(): it emitted settings
for a partitioning subsystem that no longer exists and probed deleted cloud env
vars. The live zero-config path is inline — recall preset → HNSW knobs, storage
auto-detect, auto persistMode, container-memory-aware cache sizing.
The storage progressive-init / cloud-detection cluster was equally dead after the
cloud adapters were dropped: isCloudStorage() is permanently false (no overriders),
scheduleBackgroundInit/runBackgroundInit were never called (the latter an empty
body), initMode was never assigned, and Brainy.isFullyInitialized()/
awaitBackgroundInit() were always-trivial with zero callers. scheduleCountPersist()
collapses to its only-ever-taken immediate write-through path.
Removed:
- src/config/{index,zeroConfig,storageAutoConfig,modelAutoConfig,sharedConfigManager}.ts
- src/utils/autoConfiguration.ts + the inert BrainyZeroConfig export
- Brainy.isFullyInitialized()/awaitBackgroundInit() (+ BrainyInterface decls)
- InitMode type, isCloudStorage/detectCloudEnvironment/resolveInitMode,
scheduleBackgroundInit/runBackgroundInit/ensureValidatedForWrite and their state
- Dead cloud env-var probes (K_SERVICE/K_REVISION/AWS_LAMBDA_FUNCTION_NAME/
FUNCTIONS_TARGET/AZURE_FUNCTIONS_ENVIRONMENT)
Kept (verified live): production-detection logging (environment.ts), container-
memory cache sizing (memoryDetection/paramValidation), on-disk hash bucketing
(sharding.ts).
Docs: scrubbed deleted-subsystem references (JS quantization knobs, cloud/OPFS
adapters, partitioning, old zero-config API) across 14 files; deleted two wholly-
obsolete feature docs (complete-feature-list, v3-features); rewrote
architecture/zero-config for 8.0.
~3,700 LOC removed. Build clean; 1392 unit + 24 db-mvcc green.
197 lines
5.9 KiB
Markdown
197 lines
5.9 KiB
Markdown
# Brainy Scaling Guide
|
|
|
|
> **One Line Summary**: Single-node by design — Brainy scales by getting the most out of one machine plus operator-layer backup.
|
|
|
|
## Table of Contents
|
|
- [Quick Start](#quick-start)
|
|
- [How Brainy Scales](#how-brainy-scales)
|
|
- [Storage Configurations](#storage-configurations)
|
|
- [Scaling Patterns](#scaling-patterns)
|
|
- [Real World Examples](#real-world-examples)
|
|
|
|
## Quick Start
|
|
|
|
### In-Memory
|
|
```typescript
|
|
import Brainy from '@soulcraft/brainy'
|
|
const brain = new Brainy({ storage: { type: 'memory' } })
|
|
```
|
|
|
|
### On-Disk (Default for Node)
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'filesystem', rootDirectory: './brainy-data' }
|
|
})
|
|
```
|
|
|
|
## How Brainy Scales
|
|
|
|
Brainy 8.0 is a **single-node library**. There is no cluster, no peer discovery, no S3 coordination. Scaling means:
|
|
|
|
- **Up**: give the process more RAM, CPU, and IOPS
|
|
- **Out**: stand up multiple independent Brainy instances behind your own service layer
|
|
- **Cold storage**: snapshot the on-disk artifact off-site so you can rehydrate elsewhere
|
|
|
|
The three knobs that matter most:
|
|
|
|
1. **`config.vector.recall`** — `'fast'`, `'balanced'`, or `'accurate'` (default `'balanced'`)
|
|
2. **`config.vector.persistMode`** — `'immediate'` for durability, `'deferred'` for throughput
|
|
|
|
The native vector provider (via the optional `@soulcraft/cortex` package) extends this with a higher-performing index — and its own at-scale acceleration such as on-disk compressed indexing — when installed.
|
|
|
|
## Storage Configurations
|
|
|
|
### Filesystem (Recommended for Production)
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: {
|
|
type: 'filesystem',
|
|
rootDirectory: '/var/lib/brainy'
|
|
}
|
|
})
|
|
```
|
|
- Stores everything in a sharded JSON tree under `rootDirectory`
|
|
- Atomic writes via rename
|
|
- Survives process restarts
|
|
- Snapshot it off-site with `gsutil rsync`, `aws s3 sync`, `rclone`, or `tar` from your scheduler
|
|
|
|
### Memory
|
|
```typescript
|
|
const brain = new Brainy({ storage: { type: 'memory' } })
|
|
```
|
|
- Zero I/O, fastest possible
|
|
- No persistence — process exit discards everything
|
|
- Use for tests and ephemeral caches
|
|
|
|
### Auto
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'auto', rootDirectory: './data' }
|
|
})
|
|
```
|
|
- Picks `filesystem` when running on Node with a writable `rootDirectory`
|
|
- Falls back to `memory` otherwise
|
|
|
|
## Scaling Patterns
|
|
|
|
### Stage 1: Prototype (Memory)
|
|
```typescript
|
|
const brain = new Brainy({ storage: { type: 'memory' } })
|
|
// Development, tests, <100K items
|
|
```
|
|
|
|
### Stage 2: Production (Filesystem)
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' }
|
|
})
|
|
// Most production workloads up to ~10M entities on a single host
|
|
```
|
|
|
|
### Stage 3: Higher Throughput (Tune the Vector Index)
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' },
|
|
vector: {
|
|
recall: 'fast', // Trade recall for latency
|
|
persistMode: 'deferred' // Batch persistence
|
|
}
|
|
})
|
|
```
|
|
|
|
### Stage 4: Multi-Instance (Operator-Layer)
|
|
Run multiple Brainy processes behind your own routing/service layer. Each process owns its own `rootDirectory`. Sync each artifact off-site independently. Brainy itself does not coordinate between processes.
|
|
|
|
## Real World Examples
|
|
|
|
### Example 1: Single-Node App With Backup
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' }
|
|
})
|
|
```
|
|
Schedule (cron / systemd timer):
|
|
```bash
|
|
*/15 * * * * rclone sync /var/lib/brainy remote:brainy-backup
|
|
```
|
|
|
|
### Example 2: Tests
|
|
```typescript
|
|
const brain = new Brainy({ storage: { type: 'memory' } })
|
|
// Fast, no cleanup needed between runs
|
|
```
|
|
|
|
### Example 3: Multi-Tenant Service
|
|
Spin up one Brainy instance per tenant, each in its own directory:
|
|
```typescript
|
|
function brainForTenant(tenantId: string) {
|
|
return new Brainy({
|
|
storage: {
|
|
type: 'filesystem',
|
|
rootDirectory: `/var/lib/brainy/${tenantId}`
|
|
}
|
|
})
|
|
}
|
|
```
|
|
Your service layer handles routing and isolation; Brainy stays simple.
|
|
|
|
### Example 4: Higher Recall at Scale
|
|
```typescript
|
|
const brain = new Brainy({
|
|
storage: { type: 'filesystem', rootDirectory: '/var/lib/brainy' },
|
|
vector: {
|
|
recall: 'accurate'
|
|
}
|
|
})
|
|
```
|
|
|
|
## Tuning Knobs Summary
|
|
|
|
| Setting | Values | When to change |
|
|
|---------|--------|----------------|
|
|
| `vector.recall` | `'fast'` / `'balanced'` / `'accurate'` | Trade recall for latency |
|
|
| `vector.persistMode` | `'immediate'` / `'deferred'` | Throughput vs. durability |
|
|
| `storage.cache.maxSize` | integer | Hot-path read cache size |
|
|
| `storage.cache.ttl` | ms | Cache freshness |
|
|
|
|
## Monitoring & Observability
|
|
|
|
```typescript
|
|
const stats = await brain.stats()
|
|
// {
|
|
// nounCount: 50000,
|
|
// verbCount: 80000,
|
|
// vectorIndex: { ... },
|
|
// storage: { used: '45GB' }
|
|
// }
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
### Issue: Slow queries
|
|
1. Switch to `vector.recall: 'fast'`
|
|
2. Increase the read cache (`storage.cache.maxSize`)
|
|
3. Consider the optional native vector provider via `@soulcraft/cortex`
|
|
|
|
### Issue: Memory pressure
|
|
1. Reduce `storage.cache.maxSize`
|
|
2. Move to `vector.persistMode: 'deferred'` to batch writes
|
|
3. Consider the optional native vector provider via `@soulcraft/cortex` for at-scale index acceleration
|
|
|
|
### Issue: Slow startup after a crash
|
|
1. Use `vector.persistMode: 'immediate'` so the index file stays in sync with storage
|
|
2. Verify backup integrity periodically
|
|
|
|
## Best Practices
|
|
|
|
1. **One process = one `rootDirectory`** — never share a directory between processes
|
|
2. **Snapshot from your scheduler** — Brainy doesn't ship cloud SDKs; use `rclone` / `aws s3 sync` / `gsutil`
|
|
3. **Profile before tuning** — `recall: 'balanced'` is right for most workloads
|
|
4. **Install the native vector provider only when measured profiling shows it pays off**
|
|
|
|
## Summary
|
|
|
|
- Brainy 8.0 is a **library**, not a cluster
|
|
- Storage adapters: `filesystem`, `memory`, `auto`
|
|
- Vector tuning: `recall`, `persistMode`
|
|
- Backup is an operator-layer concern — snapshot `rootDirectory`
|