Reference

Evaluation harness

This document covers the browser harness, sample store, local provider, and storage-layout benchmark.

Run the browser harness

npm install
npm run dev

Open http://127.0.0.1:5173.

Configure Entra or a generic OIDC provider, obtain an API access token through the provider’s application flow, select the provider in the harness, and exchange the token for a ThimbleDB session.

The Playwright suite includes a self-contained signed test provider:

npm run test:e2e

The UI can:

  • seed a deterministic online-store dataset
  • read one product through memory, IndexedDB, and object storage
  • switch between no cache, location-only cache, and full-content cache
  • run 100 hot reads or a collection scan
  • clear memory separately from persistent cache
  • mutate product stock through the authority
  • delete and restore retained documents
  • link external identities and use administrator controls
  • compare trie and snapshot collection behaviour
  • display remote reads, transferred bytes, cache hits, ETag 304 responses, offline fallbacks, and retained memory

For a compiled local run:

npm run build
$env:THIMBLE_ALLOWED_ORIGIN = "http://127.0.0.1:8787"
npm run start:prod

Open http://127.0.0.1:8787.

Local durable objects are stored below .thimble-data. The adapter serialises access only inside one Node process.

Local encryption behaviour

Encrypted scope mode is the default.

On first local startup:

  1. The authority creates a local deployment master key under .thimble-data.
  2. It derives one scope encryption key and one node-address HMAC key.
  3. A validated external identity is mapped to a stable internal user UUID.
  4. The browser receives an HttpOnly opaque session cookie.
  5. The authorised key endpoint returns the scope key once.
  6. The browser imports it as a non-extractable memory-only CryptoKey.
  7. Persistent cache values are encrypted with a separate non-extractable browser device key.

Raw stored objects begin with the TDB1 envelope magic and do not contain plaintext JSON.

Browser cache policies

PolicyCached objectsPurpose
noneNothingCold process or cache-miss measurement
locationsHEAD plus root and branch routing nodesAvoid path discovery while loading current leaf content
contentAll fetched objectsWarm read-mostly application

Mutable HEAD uses a configurable TTL:

$env:THIMBLE_HEAD_TTL_MS = "1000"

Per-collection and per-object TTL policy is a future extension.

Sample application

The deterministic store contains:

  • products with categories, stock, descriptions, and prices
  • customers with addresses
  • orders with line items

The browser harness uses the same data generator as the storage-layout benchmark.

Use Azure in the harness

For a browser test against Azure:

$env:THIMBLE_PROVIDER = "azure"
$env:AZURE_STORAGE_CONNECTION_STRING = "<server-only connection string>"
$env:AZURE_STORAGE_CONTAINER = "thimbledb"
$env:AZURE_AUTH_STORAGE_CONTAINER = "thimbledb-auth"
$env:THIMBLE_PREFIX = "demo"
$env:THIMBLE_MASTER_KEY = "<base64-encoded 32-byte key>"
$env:THIMBLE_ALLOWED_ORIGIN = "http://127.0.0.1:5173"
$env:ENTRA_TENANT_ID = "<tenant-id>"
$env:ENTRA_AUDIENCE = "<api-audience>"
$env:ENTRA_REQUIRED_SCOPE = "thimble.access"
npm run dev

Private objects are read through the authenticated authority. The auth container is never exposed to the browser.

See Deploy to Azure for the complete path.

Storage-layout benchmark

The storage benchmark compares:

EngineStorage modelExpected strengthExpected weakness
Monolithic JSONOne mutable object per collectionMinimal requests and excellent scansRewrites the collection and has severe write contention
Append log + snapshotImmutable numbered log entries and periodic snapshotsEfficient append behaviourReads replay the uncompacted tail
Content-addressed trieImmutable two-level trie and CAS-updated rootSmall point-read payloads and structural sharingMore requests, root contention, and garbage collection

The log model is inspired by Baerly’s documented protocol but is not a compatibility implementation.

Workload

Each engine:

  1. seeds products, customers, and orders
  2. runs cold, location-cached, and content-cached point reads
  3. runs catalogue scans under each cache policy
  4. applies sequential updates
  5. races concurrent writes
  6. runs checkout-shaped reads and writes
  7. runs maintenance and verifies data afterwards

The harness records:

  • elapsed time and p50/p95 latency
  • GET, PUT, DELETE, and LIST operations
  • bytes read and written
  • cache hits and retained bytes
  • failed conditional writes and retries
  • final object count and stored bytes

Run locally

npm run benchmark:local
npm run benchmark -- --provider local --profile small --latency-ms 8

Run against S3 or R2 through the S3 API

$env:S3_BUCKET = "<bucket>"
$env:AWS_REGION = "us-east-1"
npm run benchmark -- --provider s3 --profile small

R2:

$env:S3_BUCKET = "<r2-bucket>"
$env:AWS_REGION = "auto"
$env:S3_ENDPOINT = "https://<account-id>.r2.cloudflarestorage.com"
npm run benchmark -- --provider s3 --profile small

The benchmark uses the normal AWS credential chain. Do not put credentials in command arguments or source files.

Published evidence

Published benchmark artifacts cover live multi-region browser runs against the Cloudflare/R2 reference deployment.

See Benchmarks for the measured table, interpretation, limitations, and layout decision thresholds.

Comparative application harness

The repository also contains one deterministic bounded-notes scenario:

npm run benchmark:compare:local

The checked-in smoke adapters use:

  • the local immutable snapshot engine
  • Node’s in-memory SQLite implementation

Raw JSON is written below the ignored benchmark-results directory. These local timings exercise different architectures and do not establish product performance or cost superiority.

Cloudflare D1 and Firestore comparisons require matched deployed resources, regions, datasets, warm-up policy, and evidence capture before their results can support a public claim.

What the harness does not model

The harness does not model:

  • production-scale authentication traffic
  • sustained multi-region write contention
  • cross-collection transactions
  • search or analytics
  • residential last-mile latency
  • cost or latency superiority over managed databases

This page is built from the repository source.

View or improve this page on GitHub