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.
6b1dcda on 16 Oct 2026·Nightly properties 17 Oct 2026·Fuzzing 16 Oct 2026·Live network 16 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
- 75 ms
- Share of the 5 s budget
- 1.5%
- Each extra store
- +0.3 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.3 ms per store on top of a fixed 37 ms.
| Stores | Per block | Of budget | Slowest reply | Behind |
|---|---|---|---|---|
| 32 | 46 ms | 0.9% | 1.2 ms | 0 |
| 64 | 55 ms | 1.1% | 2.6 ms | 0 |
| 128 | 75 ms | 1.5% | 3.2 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
- 6 of 64
- 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
- 108 ms
- Stores behind
- 0
Weekly scale run
- 2,048 stores, one block
- 550 ms
- Share of the 5 s budget
- 11.0%
- Each extra store
- +0.3 ms
- Peak memory
- 29.1 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 6 ms.
| Stores | Per block | Of budget | Slowest reply | Behind |
|---|---|---|---|---|
| 512 | 142 ms | 2.8% | 5.9 ms | 0 |
| 1,024 | 265 ms | 5.3% | 6.5 ms | 0 |
| 2,048 | 550 ms | 11.0% | 11.9 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 121
- 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
- 227 ms
- Stores behind
- 0
Weekly scale run of 10 Oct 2026: the same test with far more stores, so the time per block shows how far one core can go.
Runner: AMD EPYC 7763 64-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.