Truke KF runs as a single self-contained process. The two components that drive hardware sizing are the database (SQLite) and the web server (Go HTTP).
KF stores all items, relationships, and documents in a single SQLite file. The following settings are applied at startup and shape the memory and I/O profile:
| Setting | Value | Effect |
|---|---|---|
journal_mode | WAL | Concurrent reads while a write is in progress |
mmap_size | 1 GB | Maps the database into virtual address space; avoids system-call overhead on reads |
cache_size | 64 MB | In-process page cache |
page_size | 32 KB | Large pages reduce tree depth for big stores |
synchronous | NORMAL | Durable on power failure; faster than FULL |
Full-text search uses SQLite's FTS5 engine with BM25 ranking. Search index updates are written asynchronously (buffered queue of 4 096 entries), so heavy write bursts do not stall the UI.
Writes are serialised through a single mutex. Reads are concurrent and benefit directly from the memory-mapped I/O and the page cache.
| Items | Result | Test hardware |
|---|---|---|
| 100 000 | Fast — no perceptible delay | i5-9400 @ 2.9 GHz, 32 GB RAM, NVMe SSD |
| 1 000 000 | Usable — some operations noticeably slow | same |
The 1 M-item slowdown is mainly in full-tree traversals and BM25 search over the full index. Item-level reads and writes remain fast at that scale.
The Go HTTP server spawns a goroutine (~4 KB stack) per request and keeps no per-request thread. The in-memory session store holds up to 10 000 sessions. A query result cache (up to 10 000 entries, 60-second TTL) shields the database from repeated identical reads.
For a knowledge-management product used by an engineering team, the workload is read-heavy: most users browse items and documents simultaneously, while writes (editing items, adding actions) are occasional. Under that profile the web server is not the bottleneck — SQLite's single-writer lock is the practical limit on write throughput.
A rough estimate of sustainable concurrent users on recommended hardware with a 100 K-item store:
| Workload | Concurrent users |
|---|---|
| Read-only (browsing, search) | 100 – 200 |
| Mixed read/write (active editing) | 20 – 50 |
These are order-of-magnitude estimates. Actual figures depend on item size, document length, and search query frequency.
| Scenario | CPU | RAM | Storage |
|---|---|---|---|
| Evaluation / small team (≤ 10 K items) | Any dual-core | 4 GB | Any SSD |
| Production team (≤ 100 K items, ≤ 50 users) | 4-core, 2.5 GHz+ | 8 GB | SSD |
| Large store (≤ 500 K items, ≤ 100 users) | 8-core | 16 GB | NVMe SSD |
| Very large store (≥ 1 M items) | 8-core+ | 32 GB | NVMe SSD |
RAM is the most important dimension. The 1 GB mmap_size window means that a store up to ~1 GB fits entirely in virtual memory; more RAM allows the OS to keep those pages warm and avoids re-reading from disk. For stores larger than available RAM, a fast NVMe drive becomes critical.
CPU matters for BM25 search at large scale and for concurrent request handling, but it is rarely the first bottleneck.
Storage should always be an SSD. KF's WAL mode issues frequent small writes (WAL frame appends and periodic checkpoints); spinning disks introduce latency that directly affects write response time.
KF runs on Linux, Windows, and macOS. For production deployments, Linux is recommended: SQLite's mmap performance is best on Linux, and process isolation and monitoring tooling (systemd, cgroups) are more mature.