testing local-first datastores
localstress#
Benchmark suite for comparing local datastore performance in Node.js.
Quick Start#
npm install
npm run generate # Generate ~1GB test data (takes a few minutes)
npm run bench # Run benchmarks on all stores
Datastores Tested#
Node.js Datastores#
- TinyBase - Reactive data store for local-first apps
- LevelGraph - Graph database built on LevelDB
- SQLite - Embedded SQL database (via better-sqlite3)
Browser Datastores#
- PGLite - PostgreSQL compiled to WebAssembly
- PouchDB - Sync-enabled NoSQL database for browsers
- IndexedDB - Browser's native structured storage (key-value + indexes)
- LocalStorage - Browser's simple key-value storage (limited to ~5-10MB)
Methodology#
Each benchmark is run 10 times per datastore. The highest and lowest scores are discarded, and the median of the remaining 8 runs is reported. This reduces the impact of outliers from system variability.
Test Dataset#
Target ~1GB total:
- 10,000 URLs with metadata
- 1,000 PNG images (~900MB)
- 1,000 text documents (~50MB)
- 100,000 metadata rows
Benchmarks#
Init
- Store initialization time
Writes
- Add all URLs
- Add all metadata rows
- Add all images
- Add all documents
Reads
- Get 100 most recent URLs
- Get 10 random images
- Get 1000 random documents
Disk
- Total storage space used
Commands#
# Node.js benchmarks
npm run generate # Generate test data to test-data/
npm run bench # Benchmark all Node.js stores (10 iterations each)
npm run bench:store tinybase # Benchmark single store
npm run bench:store levelgraph
npm run bench:store sqlite
# Browser benchmarks
npm run bench:browser # Benchmark browser stores (PGLite, PouchDB) in multiple browsers
# Results
npm run charts # Regenerate charts from latest results
Browser Benchmarking#
Browser benchmarks test in-browser datastores across multiple browsers (Chromium, Firefox, WebKit):
npm run bench:browser
This launches browser instances (Chromium, Firefox, WebKit), runs benchmarks for each datastore, and measures storage usage via the Storage Estimation API.
Benchmarks:
- IndexedDB - Transactional object store with indexes ✓
- LocalStorage - Key-value storage (limited capacity) ✓
- PouchDB - Document database (interactive UI only)
- PGLite - PostgreSQL in WASM (interactive UI only)
Interactive Browser Testing#
The HTML harness (src/browser/harness.html) provides an interactive UI for manual testing:
# In one terminal, start a local server:
python3 -m http.server 8000 --directory src/browser
# Open in browser:
# http://localhost:8000/harness.html
Then select a datastore and click "Start Benchmark".
Adding a New Datastore#
Node.js Datastores#
- Create
src/stores/yourstore.tsimplementingDatastoreAdapterfromsrc/harness/types.ts - Register in
src/stores/index.ts
Browser Datastores#
- Create
src/browser/adapters/yourstore.tsimplementingBrowserDatastoreAdapterfromsrc/harness/browser-types.ts - Add to the
storesarray insrc/browser/runner.ts
Project Structure#
src/
generator/ # Test data generation
harness/ # Benchmark infrastructure (types, runner, reporter)
stores/ # Node.js datastore adapters
browser/ # Browser benchmark infrastructure
adapters/ # In-browser datastore adapters (PGLite, PouchDB)
harness.html # Browser-based benchmark UI
harness.ts # Browser benchmark runner
runner.ts # Playwright automation for browser testing
runner.ts # CLI entry point for Node.js benchmarks
test-data/ # Generated test data (gitignored)
results/ # Benchmark results JSON (gitignored)