How Monokulo is tested
Monokulo handles other people’s money, so it gets tested hard. Every change runs more than 2,600 automatic tests. Every night, two kinds of robot tester invent thousands of strange situations and check that no payment goes missing. This page rebuilds itself from those runs. Open any section to see the details.
4176f6b on 18 Oct 2026·Nightly properties 23 Oct 2026·Fuzzing 23 Oct 2026·Live network 22 Oct 2026Scale
Could Monokulo keep up on a small computer? This test pins it to a single CPU core, gives it lots of stores at once, and keeps other work competing with it: reading the database, answering status requests, saving settings. A new block arrives every 5 seconds, and every store’s payments have to be checked before the next one lands.
- 128 stores, one block
- 58 ms
- Share of the 5 s budget
- 1.2%
- Each extra store
- +0.2 ms
- Peak memory
- 16.1 MB
Time to scan one block for every store
Average of 4 measured blocks after warm-up. The cost grows by about 0.2 ms per store on top of a fixed 36 ms.
| Stores | Per block | Of budget | Slowest reply | Behind |
|---|---|---|---|---|
| 32 | 41 ms | 0.8% | 2.6 ms | 0 |
| 64 | 47 ms | 0.9% | 1.3 ms | 0 |
| 128 | 58 ms | 1.2% | 1.5 ms | 0 |
Pass conditions: no store more than 3 blocks behind, status replies under 250 ms. All 3 passed.
Recovering from faults
Each run breaks one thing on purpose for 2 blocks, then gives the engine 6 blocks to recover. Each bar is how long one block took; orange bars are the broken ones. In all three, no store fell behind.
Node errors
Every node request slowed by 2 ms, and every third request failed until block 2.
- Stores
- 16
- Requests failed
- 3 of 57
- Stores behind
- 0
Database locked
Another writer held the database lock for 1.5 s during each of the first 2 blocks.
- Stores
- 16
- Lock held
- 1.5 s × 2 blocks
- Stores behind
- 0
Key custody slow
Key custody limited to 1 scan at a time, each taking an extra 5 ms.
- Stores
- 16
- Custody scans
- 128
- Longest wait
- 103 ms
- Stores behind
- 0
Weekly scale run
- 2,048 stores, one block
- 585 ms
- Share of the 5 s budget
- 11.7%
- Each extra store
- +0.3 ms
- Peak memory
- 24.3 MB
Time to scan one block for every store
Average of 4 measured blocks after warm-up. The cost grows by about 0.3 ms per store on top of a fixed 0 ms.
| Stores | Per block | Of budget | Slowest reply | Behind |
|---|---|---|---|---|
| 512 | 145 ms | 2.9% | 5.1 ms | 0 |
| 1,024 | 273 ms | 5.5% | 4.6 ms | 0 |
| 2,048 | 585 ms | 11.7% | 10.8 ms | 0 |
Pass conditions: no store more than 3 blocks behind, status replies under 250 ms. All 3 passed.
Recovering from faults
Each run breaks one thing on purpose for 2 blocks, then gives the engine 8 blocks to recover. Each bar is how long one block took; orange bars are the broken ones. In all three, no store fell behind.
Node errors
Every node request slowed by 2 ms, and every third request failed until block 2.
- Stores
- 256
- Requests failed
- 10 of 120
- Stores behind
- 0
Database locked
Another writer held the database lock for 1.5 s during each of the first 2 blocks.
- Stores
- 256
- Lock held
- 1.5 s × 2 blocks
- Stores behind
- 0
Key custody slow
Key custody limited to 1 scan at a time, each taking an extra 5 ms.
- Stores
- 256
- Custody scans
- 2,560
- Longest wait
- 233 ms
- Stores behind
- 0
Weekly scale run of 17 Oct 2026: the same test with far more stores, so the time per block shows how far one core can go.
Runner: AMD EPYC 9V45 96-Core Processor, pinned to one of 4 cores, SQLite 3.53.2. Absolute times vary between runners; the pass condition is that every store keeps up. Full stress report.