Twenty isolated databases, 200,000 rows, 2.24 million read/update operations, and a full destroy cycle — zero failures on a virtual machine with one CPU core and one gigabyte of RAM.
Two writers each created a workspace and ten databases, minted a per-database token, built a table, and inserted 10,000 rows in batches of 250 four-column rows. Every database responded with an exact COUNT(*) of 10,000 and a LIKE-scan check before being counted.
workspace stress-01 · 10 databases · 100,000 rows · 13.8s
workspace stress-02 · 10 databases · 100,000 rows · 13.9s
A third worker waited for all 200,000 rows, then ran eight rounds against every database: SELECT COUNT(*), UPDATE of every fifth row, a SELECT by updated value, a top-5 read, and the live /metrics endpoint. Each round touches all 20 databases — 280,100 operations per round.
| Round | Operations | Avg latency | p95 latency | Failures |
|---|---|---|---|---|
| 1 | 280,100 | 119.3 ms | 175 ms | 0 |
| 2 | 280,100 | 114.8 ms | 143 ms | 0 |
| 3 | 280,100 | 112.7 ms | 135 ms | 0 |
| 4 | 280,100 | 112.3 ms | 126 ms | 0 |
| 5 | 280,100 | 129.4 ms | 202 ms | 0 |
| 6 | 280,100 | 118.7 ms | 144 ms | 0 |
| 7 | 280,100 | 114.0 ms | 129 ms | 0 |
| 8 | 280,100 | 118.6 ms | 144 ms | 0 |
| Total | 2,240,800 | mean 117.5 ms | mean p95 150 ms | 0 |
Every database was deleted through the API, then the workspaces were removed. The control plane killed each sqld process, freed its port, removed its data directory and its per-database signing key, and cleaned now-empty parents — a gap found during this test and fixed in the same session.
Per-database keys removed from keys/, data directories gone from disk, API back to the pre-test workspace set. The empty-parent cleanup found in the test is now covered by unit tests (parents removed when empty, preserved when siblings remain). Destroy-phase figures here are from the run log; the headline totals are in the linked evidence file.
Three workers: two writers (10 databases each, batched 250-row multi-value inserts via @libsql/client over Hrana WebSocket) and one reader/verifier. Every insert batch verified with an exact COUNT(*). A 3-second host sampler recorded memory, process count, port latency, and database count throughout. The whole run fitted comfortably — ~580 MB was still free at the hottest instant, with no swap.
This is a single-node, single-CPU test on deliberately small hardware — a production box is bigger. Latencies include a Tailscale link, not pure loopback. The control plane has no login in v1: put it behind a firewall or authenticated reverse proxy on a real network. Database tokens are per-database and full-access; data access itself stayed isolated — a token for one database was rejected by every other (verified in this run).