reqmd is fast enough to run on every commit, every save, and every pull request — without anyone noticing the wait. This page shows the real numbers and explains what drives them.
The headline#
The tool’s own spec — 249 requirements across 6 document directories — validates in 16 milliseconds. That’s faster than a page load. For context, a typical project spec is in the hundreds, not the thousands.
How it scales at large sizes#
To find the ceiling, a synthetic spec tree was generated by replicating the real spec across 36 document directories at four sizes: 71k, 180k, 360k, and 720k requirements. The numbers below are wall-clock time (how long the command takes to finish), the median across 5 runs on an 8-core / 16-thread desktop CPU.
The scaling is linear: double the requirements, double the time. There is no exponential blowup, no cliff, no surprise. The check time is predictable from the requirement count alone. For reference, the same benchmark on a 12-core laptop (Intel i5-1245U, 2 performance + 8 efficiency cores) runs ~2.7× slower — 1.9 s for 71k, 4.8 s for 180k, 9.4 s for 360k. The desktop numbers below are the ones to expect on typical CI or developer hardware.
What this means in practice#
All times below are reqmd check on the 8-core / 16-thread desktop (AMD Ryzen 7 5800X):
| Your spec size | reqmd check takes | Good for CI? |
|---|---|---|
| ~100 requirements | ~5 ms | instant |
| ~1,000 requirements | ~16 ms | instant |
| ~10,000 requirements | ~100 ms | instant |
| ~71,712 requirements | ~0.7 s | yes |
| ~180,774 requirements | ~1.7 s | yes |
| ~363,042 requirements | ~3.5 s | yes |
| ~727,578 requirements | ~7.2 s | yes |
Most project specs are in the hundreds to low thousands. Even a large, multi-team spec with 180,000 requirements finishes in under 2 seconds. The 720k case is an extreme stress test — more requirements than most teams will produce in a decade — and it still finishes in 7 seconds.
Other commands#
The check command is the heaviest one. The other commands are faster because they skip the trace-graph pass:
| Command | What it does | 71k reqs | 720k reqs |
|---|---|---|---|
reqmd check | Validate + trace checks | 0.7 s | 7.2 s |
reqmd check --json | Same, with JSON output | 0.7 s | 7.6 s |
reqmd ls | List all requirements | 0.4 s | 3.4 s |
reqmd stats | Stats per document | 0.3 s | 2.8 s |
reqmd export html | Full HTML export | 1.4 s | 15.0 s |
The JSON output adds 5–10% overhead. The HTML export is the slowest because it renders every requirement as a standalone page with trace links — but even at 720k requirements it finishes in 15 seconds.
Memory usage#
Memory grows linearly with the spec size, same as time. The 720k spec uses about 5.4 GB for check and 6.2 GB for ls. For typical specs (hundreds to low thousands of requirements), memory is negligible — under 100 MB.
What makes it fast#
Three things, in plain terms:
Parallel reading. reqmd reads all document directories at the same time, using every CPU core. On a 16-thread machine, up to 16 directories are parsed simultaneously. The more cores you have, the faster this goes — a server CPU with 32+ threads would parse proportionally faster.
No database. The trace graph is built in memory on every run, then thrown away. There is no database to query, no cache to maintain, no incremental state to manage. Starting from scratch every time is faster than maintaining a complex cache — because the total time is so small.
Single pass. Once the files are read, every trace check — broken references, cycles, missing coverage, version pins — runs in a single pass over the requirements. No multiple queries, no back-and-forth.
How the numbers were measured#
The numbers come from a real run of two bundled tools: reqmd-bench-gen (generates a synthetic spec tree by replicating the real spec) and reqmd-bench-run (runs the benchmarks and reports the numbers).
The spec tree was generated by copying the real 6-directory spec 6 times (36 directories total) and then replicating each document’s content to reach a target requirement count. The trace graph stays connected — every link is rewritten deterministically. The result looks like a multi-team spec repo where several teams independently authored requirements against the same template.
To reproduce:
# Build the bench tools
go build -o reqmd-bench-gen ./cmd/reqmd-bench-gen
go build -o reqmd-bench-run ./cmd/reqmd-bench-run
# Run the full benchmark (baseline + 4 scales, 5 runs each)
./bench.sh
# Or invoke the runner directly
./reqmd-bench-run -src spec/ \
-gen ./reqmd-bench-gen \
-reqmd ./reqmd \
-work /tmp/reqmd-bench \
-out /tmp/reqmd-bench-results.jsonThe full run takes about 6 minutes on the desktop at all four scales. Results are saved as JSON with hardware metadata (CPU model, core count, Go version, kernel) for reproducibility.
Hardware: AMD Ryzen 7 5800X (8 cores / 16 threads), Linux 7.1.3, Go 1.26.5. This is a mainstream desktop CPU from 2020. A modern desktop or server CPU with more performance cores would be faster; the numbers on this page are a conservative baseline. For reference, the same benchmark on a 12-core laptop (Intel i5-1245U, 2 performance + 8 efficiency cores) runs ~2.7× slower.
When it gets slow#
Past about 500,000 requirements, the parallel reader starts to lose efficiency and the markdown parser becomes the bottleneck. Two practical workarounds:
- Run
reqmd checkon a smaller subtree (e.g. only the documents that changed). - Use
--jsonoutput and cache the result keyed on the spec-tree hash.
These are edge cases. Most teams will never hit them.
See also#
- Quickstart — try
reqmd checkon the bundled 249-requirement spec. - Use cases — including CI integration patterns.
reqmd-bench-gensource — the synthetic corpus generator.reqmd-bench-runsource — the benchmark runner that produced these numbers.