Benchmarks
Methodology and published results for Wolbarg v0.4.0 — dual-backend v4 stress, embedding cache, multi-process concurrency, and how to reproduce locally.
What is it?
How Wolbarg v0.4.0 measures startup, batch/bulk insert, recall latency, embedding-cache behavior, upsert/dedupe correctness, subscribe() delivery, and concurrency on SQLite and PostgreSQL.
Two embedding modes — do not mix them:
| Suite | Embeddings | What it measures |
|---|---|---|
| Storage / stress (mock) | Local mock OpenAI-compatible server | SDK + database ceiling (I/O, indexes, concurrency, cache hits with instant embeds) |
| LIVE | Real providers (OpenAI, etc.) | End-to-end latency including network + provider time |
Interactive charts: /benchmarks.
Published 0.4 artifacts
| Artifact | Contents |
|---|---|
version-0.4.0-sqlite-benchmark.json · .md | Full v4 stress suite on SQLite |
version-0.4.0-postgres-benchmark.json · .md | Full v4 stress suite on Postgres |
embedding-cache.json | Provider-call reduction microbench |
multiprocess-concurrency.json | Multi-process SQLite writers (2–20) |
benchmark.json · benchmark.md | Prior dual-backend quick suite (historical) |
Public suite repo: wolbarg-benchmarks.
Why it exists
Vendor graphs without methodology mislead. These docs explain what was measured so you can compare fairly and reproduce locally — especially the difference between mock stress and live API spots, and between same-process vs multi-process concurrency.
Headlines — v0.4.0 (2026-07-18)
Environment: Node v24.13.1 · win32/arm64 · 8 CPUs · mock embeddings · suite v4-stress.
| Metric | SQLite | PostgreSQL |
|---|---|---|
Cold ready() | 16.18 ms | 91.39 ms |
| Warm reopen | 1.87 ms | 59.89 ms |
rememberBatch 200 | 5,795 ops/s | 2,795 ops/s |
| Bulk insert 2k | 7,509 ops/s | 4,085 ops/s |
| Recall p50 @ 2k | 4.12 ms | 23.29 ms |
| Recall p95 @ 2k | 4.83 ms | 141.5 ms |
| Cache speedup (spot) | 1.47× | 1.18× |
| Concurrency 8 writers | 6,084 ops/s · p95 3.05 ms | 2,555 ops/s · p95 8.51 ms |
| Concurrency 16 writers | 8,660 ops/s · p95 2.46 ms | 3,335 ops/s · p95 9.48 ms |
| Concurrency 32 writers | 6,798 ops/s · p95 22.94 ms | 3,802 ops/s · p95 14.77 ms |
| Mixed read/write storm | 0 failures | 0 failures |
| Suite result | 25 pass / 0 fail | 21 pass / 0 fail / 4 skip* |
*Postgres skips SQLite-only checks (schema meta table probe, SQLite EventDatabase telemetry file, file checkpoints, export/import bundles).
Embedding cache microbench
| Metric | Value |
|---|---|
| Workload | 100 chunks · 20 unique · 2 passes |
| Uncached provider calls | 100 |
| Cached provider calls | 20 |
| Call reduction | 90% |
| Hits / misses | 180 / 20 |
Source: embedding-cache.json · runner benchmark/embedding-cache-bench.ts.
Multi-process SQLite concurrency
Shared file, separate OS processes, BEGIN IMMEDIATE + busy retry (v0.4):
| Writers | Throughput (ops/s) | p50 (ms) | p95 (ms) | p99 (ms) | Error rate | Integrity |
|---|---|---|---|---|---|---|
| 2 | 123 | 0.77 | 3.17 | 9.66 | 0% | OK |
| 5 | 221 | 0.78 | 6.09 | 43.94 | 0% | OK |
| 10 | 246 | 0.81 | 15.48 | 52.66 | 0% | OK |
| 20 | 245 | 0.79 | 77.77 | 319.74 | 0% | OK |
Source: multiprocess-concurrency.json · runner benchmark/multiprocess-levels.ts.
Feature coverage in the v4 suite
Beyond raw speed, the 0.4 suite asserts product correctness:
| Area | Cases |
|---|---|
| Startup / schema | Cold + warm ready(), schema version |
| Batch throughput | rememberBatch ops/sec |
| Embedding cache | Cold vs hot embed latency / speedup |
| Dedupe | Exact upsert + metadata merge; dedupe-off still duplicates |
| Subscribe | remember / update / forget delivery; throwing subscriber isolaton |
| Telemetry / checkpoint / transfer | SQLite paths for observability snapshots |
| Edge | Org/agent isolation, unicode metadata, filters, hybrid+compress, forget integrity |
| Concurrency | 8 / 16 / 32 writers, mixed R/W storm, concurrent exact-dedupe uniqueness |
Methodology
Mock vs LIVE (read this)
Primary stress and push-to-failure concurrency use a local mock OpenAI-compatible embedding/LLM server. Live OpenAI is not used for failure ramps because API rate limits and quota errors would dominate long before SQLite or PostgreSQL contention, masking true Wolbarg/storage breaking points.
A separate LIVE spot suite (npm run benchmark:live) reports real-network latency for representative paths. It does not ramp concurrency to failure.
Failure criteria (breaking ramps)
When using breaking / brutal modes, a concurrency level fails when:
errorRate > 1%, orp95 latency > 5s, or- a hard integrity/exception failure (duplicate IDs, crash, etc.)
Reports record lastHealthyLevel and breakingLevel with reason (error_rate | p95_sla | exception | integrity | cap).
Storage matrix
| Backend | Notes |
|---|---|
| SQLite | Local file + WAL + BEGIN IMMEDIATE (0.4) |
| PostgreSQL | Local native Postgres only (pgvector). Docker Compose paths/ports are rejected. Hosted Neon/Supabase/Railway URLs measure network RTT, not Wolbarg. |
cd benchmark
npm run postgres:up
npx tsx v4-stress.ts # or your package script wrapping it
npx tsx embedding-cache-bench.ts
npx tsx multiprocess-levels.tsVector backend caveat: benchmarks assume pgvector/HNSW is enabled for Postgres and sqlite-vec is available for SQLite. When extensions are missing/unloadable, Wolbarg falls back to exact cosine scanning, which can change recall latency substantially.
Commands (legacy + 0.4 runners)
| Command | Mode | Notes |
|---|---|---|
npm run benchmark | mock | Full dual-backend historical suite |
npm run benchmark:quick | mock | Quick scale (100 / 1k) |
npm run benchmark:brutal | mock | Failure ramps (up to 4096) |
npm run benchmark:live | live | Spot only — no failure ramp |
npx tsx v4-stress.ts | mock | 0.4 feature + stress suite |
npx tsx embedding-cache-bench.ts | mock | Cache call-reduction |
npx tsx multiprocess-levels.ts | mock | Multi-process SQLite levels |
Metrics glossary
| Benchmark | What it means |
|---|---|
| Startup cold/warm | Time to ready() + reopen |
| Batch / bulk insert ops/sec | Sustained remember / rememberBatch throughput |
| Recall p50/p95 | Semantic search latency at corpus size |
| Cache speedup | Hot vs cold embed path |
| Concurrency N writers | Fixed writer count throughput + p95 |
| Multiprocess levels | Separate OS processes vs shared SQLite file |
| Compression % | Active-set reduction after compress (legacy suite) |
| DB size / memory | On-disk and heap/RSS (legacy suite) |
Hardware
Always read the environment block in the artifact you cite (Node, CPU, RAM, mode, backends, dims). The 0.4 publish used Node v24.13.1 · win32/arm64 · 8 CPUs.
Dataset
Synthetic memories with fixed templates. Mock dims typically 384; live typically 1536 (text-embedding-3-small). Labels (100, 1k, 2k) are memory counts.
Reproducibility
cd benchmark
npm install
cp .env.example .env # DATABASE_URL for postgres; API keys for --live
npx tsx v4-stress.ts
npx tsx embedding-cache-bench.ts
npx tsx multiprocess-levels.tsPrefer recording: date, SDK version (wolbarg@0.4.0), Node version, CPU/RAM, mode (mock/live), backends, and git SHA.
Interpretation
- Startup ms — agents open memory without multi-second cold starts
- Bulk insert vs recall — know when Postgres/pgvector or sharding strategies matter (Postgres recall p95 in this run is network/engine dominated vs SQLite in-process)
- Same-process vs multi-process — multi-process SQLite serializes; throughput plateaus while p95 climbs (expected)
- Cache reduction — measure provider calls, not only ms, when arguing cost
- Mock ≠ hosted SaaS — do not compare mock embed timings to managed GPU indexes
- Storage (mock) ≠ LIVE — never mix the two suites in one comparison cell
- Competitor accuracy evals ≠ storage ops/sec — see the policy on /benchmarks