Measured, not claimed
Validation engines compared
24 validation engines check the same 722 e-invoices from the Beleggo data kit — XRechnung, ZUGFeRD / Factur-X, Peppol BIS 3 and national CIUS, valid and defective — on the same machine, one document at a time. The official KoSIT validator runs alongside as the reference. Mustangproject and phive, the most widely used open-source validators, then stand next to Beleggo in detail.
Measured on 30 September 2026 on linux x64, Intel(R) Xeon(R) Processor @ 2.10GHz × 4, 16 GiB, Node v22.22.2
| Engine | Runtime | Licence | Profiles | Correct | False alarms | Missed | Rule named | Median | Memory |
|---|---|---|---|---|---|---|---|---|---|
| Beleggoartefacts 2026-08-31 | JavaScript | proprietary | all | 100%722 documents | 0 | 0 | 338 | 5 ms | 329 MB |
| dealerweb/einvoice1.1.0 | PHP 8 | MIT | 7 / 11 | 98.7%697 documents | 1 | 8 | 289 | 46 ms | 149 MB |
| EU ITB eInvoicing validator1.14.0-SNAPSHOT (2026-09-25) · CEN 1.3.16 | Java 17+ | EUPL-1.2 | 1 / 11 | 98%449 documents | 0 | 9 | 273 | 92 ms | 682 MB |
| KoSIT Validator1.6.3 · Validator Configuration XRechnung 3.0.2 2026-09-02 · reference | Java 11+ | Apache-2.0 | 1 / 11 | 97.9%187 documents | 0 | 0 | 282 | 11 ms | 1,021 MB |
| verifaktura0.1.8 | Node.js | Apache-2.0 | 2 / 11 | 97.6%455 documents | 0 | 11 | 251 | 52 ms | 392 MB |
| einvoice-kit0.1.3 | Node.js | MIT | 1 / 11 | 97.3%449 documents | 0 | 12 | 230 | 1.2 ms | 100 MB |
| phive4.6.0 | Java 17+ | Apache-2.0 | all | 96.7%722 documents | 0 | 22 | 311 | 7.4 ms | 867 MB |
| en16931 (npm)0.1.0 | Node.js | MIT AND EUPL-1.2 | 1 / 11 | 96.7%449 documents | 1 | 11 | 255 | 55 ms | 239 MB |
| Klarfakt1.0.0-preview.2 | .NET 10 | BUSL-1.1 (free for evaluation; Apache-2.0 after four years) | 3 / 11 | 96.4%687 documents | 8 | 17 | 278 | 11 ms | 463 MB |
| @kontor-mcp/core1.0.4 | Node.js | Apache-2.0 | 2 / 11 | 95.9%636 documents | 0 | 19 | 277 | 195 ms | 507 MB |
| Mustangproject2.26.0 | Java 11+ | Apache-2.0 | 6 / 11 | 95.4%646 documents | 7 | 23 | 281 | 44 ms | 955 MB |
| @aifind/mustangjs0.4.0 | Node.js | Apache-2.0 | 2 / 11 | 94%636 documents | 8 | 24 | 265 | 73 ms | 407 MB |
| core-invoice (Rust CLI)2.0.3 | Rust | MIT OR Apache-2.0 | 2 / 11 | 94%500 documents | 10 | 20 | 218 | 2.7 ms | 10 MB |
| verifyhash-einvoice0.2.9 | Python 3 | Apache-2.0 | 2 / 11 | 93.6%636 documents | 4 | 37 | 252 | 2.1 ms | 28 MB |
| International.EInvoicing (.NET CLI)1.1.0 | .NET 8+ | MIT | 2 / 11 | 93.4%636 documents | 4 | 31 | 259 | 320 ms | 193 MB |
| john-wink/en16931-php0.3.0 | PHP 8 | MIT | 2 / 11 | 93.1%636 documents | 1 | 43 | 242 | 36 ms | 51 MB |
| @attestwire/en169310.14.0 | Node.js | MIT | 3 / 11 | 90.5%687 documents | 7 | 58 | 228 | 2.3 ms | 110 MB |
| en16931 (Dart)0.1.4 | Dart, AOT-compiled | MIT | 7 / 11 | 89%697 documents | 20 | 57 | 226 | 1 ms | 48 MB |
| speedata/einvoicev0.0.22 | Go | BSD-3-Clause | 3 / 11 | 88.9%687 documents | 15 | 61 | 208 | 7.4 ms | 17 MB |
| stampbench (@stampbench/core)0.1.1 | Node.js | MIT | 2 / 11 | 84.9%636 documents | 8 | 88 | 154 | 1.5 ms | 83 MB |
| en16931 (Rust CLI)0.6.0 | Rust | MIT OR Apache-2.0 | 3 / 11 | 76.4%687 documents | 116 | 46 | 194 | 3.1 ms | 10 MB |
| @fin.cx/einvoice11.1.1 | Node.js | MIT | 2 / 11 | 69.5%636 documents | 14 | 180 | 57 | 9.4 ms | 161 MB |
| KoSIT Validator + ZUGFeRD configuration1.6.3 · Validator Configuration ZUGFeRD 2.5.2 2026-06-11 · reference | Java 11+ | Apache-2.0 | 4 / 11 | 50%10 documents | 0 | 5 | 31 | 5.7 ms | 831 MB |
| factur-x (akretion)6.8 | Python 3 | BSD-2-Clause | 4 / 11 | 50%10 documents | 0 | 5 | 14 | 0.4 ms | 45 MB |
“Profiles”: how many of the kit’s 11 profiles the engine itself claims to check. “Correct”: the share of documents in those profiles whose verdict (valid or defective) matches the expected one; a document the engine cannot judge counts as wrong. As every engine covers different profiles, the percentages rest on different numbers of documents. The KoSIT validator is the official reference for XRechnung. Measured 25 – 30 September 2026.
“Rule named”: of the 338 defective samples across the kit, how many the engine rejects while naming the broken rule. “Median”: time per document after warm-up; “Memory”: peak of the whole process.
| Measure | Beleggo | Mustangproject | phive | Ahead |
|---|---|---|---|---|
| Correct verdicts, every documentagainst each sample’s expected verdict | 722 / 722 (100%) | 668 / 722 (92.5%) | 698 / 722 (96.7%) | Beleggo |
| Correct verdicts in Mustang’s profilesonly the profiles Mustang itself checks | 646 / 646 (100%) | 616 / 646 (95.4%) | 623 / 646 (96.4%) | Beleggo |
| Agreement with the KoSIT validatoron every XRechnung document — the scope the official validator is responsible for | 183 / 183 (100%) | 167 / 183 (91.3%) | 175 / 183 (95.6%) | Beleggo |
| Defects named with the right rulenot just rejected, but the broken rule reported | 338 / 338 (100%) | 281 / 338 (83.1%) | 311 / 338 (92%) | Beleggo |
| Profiles in the kit it checksformats whose own rules the engine knows | 11 / 11 | 6 / 11 | 11 / 11 | Beleggo · phive |
| Measure | Beleggo | Mustangproject | phive | Ahead |
|---|---|---|---|---|
| Time per document (median)after warm-up | 5 ms | 44 ms | 7.4 ms | Beleggo |
| Time per document (95th percentile)the slow documents | 20 ms | 88 ms | 25 ms | Beleggo |
| Documents per secondone document at a time | 112 | 17.2 | 56.8 | Beleggo |
| CPU time per documentall threads together | 13 ms | 118 ms | 48 ms | Beleggo |
| One-shot call (start + first document)what a command-line call costs | 345 ms | 3,822 ms | 5,325 ms | Beleggo |
| Memory (peak)of the whole process | 329 MB | 955 MB | 867 MB | Beleggo |
| Install sizerules and runtime, without Node.js or Java | 15 MB | 56 MB | 58 MB | Beleggo |
Beleggo runs the official Schematron rules as code translated to JavaScript, read from the same stylesheets Saxon-JS runs and checked against Saxon-JS as the reference on every test corpus: the same findings, the same text, the same order. A document the translated rules cannot judge exactly goes to Saxon-JS. CPU time is above the time per document because Node.js collects garbage on threads of its own. The same engine runs in the browser.
| Beleggo | Mustangproject | phive | |
|---|---|---|---|
| EN 16931 (UBL and CII) | yes | yes | yes |
| XRechnung 3 with the official KoSIT severities | yes | partly | partly |
| Peppol BIS 3 and Peppol country rules | yes | no | yes |
| NLCIUS, CIUS-RO, HR-CIUS, CIUS-PT | yes | no | yes |
| Factur-X / ZUGFeRD profiles (XSD and Schematron) | yes | yes | yes |
| Visible PDF page checked against the XML | yes | no | no |
| Check digits (IBAN, VAT id, Leitweg-ID, tax number …) | yes | no | no |
| Runs in the browser, no upload, no server | yes | no | no |
| Full PDF/A-3 validation (every rule of the veraPDF profiles) | yes | yes | no |
| ZUGFeRD 1.0 and Order-X | yes | yes | no |
| French CTC rules (BR-FR Flux 2) as errors, in UBL and CII | yes | partly | yes |
| XRechnung Schematron, current edition (2.6.0) | yes | partly | yes |
| Peppol BIS 3 in CII | yes | no | no |
| EXTENDED-CTC-FR and Flux 10 e-reporting (France) | yes | partly | yes |
| Every line recomputed (quantity × price) | yes | yes | no |
| Warnings already announced as future errors | yes | no | no |
| Peppol PINT (EU, A-NZ, SG, JP, MY, AE, OM) — Beleggo in its CLI and MCP server, rules fetched from OpenPeppol | yes | no | yes |
| Peppol Invoice Response and Message Level Status | yes | no | yes |
Mustang departs from the expected verdict on 54 of 722 documents, 24 of them in profiles it does not check at all. The rest have five causes:
| Profile | Documents | Beleggo | Mustangproject | phive |
|---|---|---|---|---|
en16931 · cii | 49 | 49 | 44 | 45 |
en16931 · ubl | 264 | 264 | 260 | 259 |
en16931 · zugferd | 136 | 136 | 136 | 135 |
hr-cius · ubl | 6 | 6 | 2 | 6 |
nlcius · ubl | 5 | 5 | 4 | 5 |
peppol-bis3 · cii | 1 | 1 | 1 | 1 |
peppol-bis3 · ubl | 49 | 49 | 37 | 48 |
peppol-bis3 · zugferd | 1 | 1 | 1 | 1 |
pt-cius · ubl | 5 | 5 | 3 | 5 |
ro-cius · ubl | 9 | 9 | 4 | 9 |
xrechnung · cii | 126 | 126 | 114 | 119 |
xrechnung · ubl | 47 | 47 | 43 | 46 |
xrechnung · zugferd | 14 | 14 | 14 | 14 |
zugferd-basic · cii | 1 | 1 | 1 | 1 |
zugferd-basic · zugferd | 2 | 2 | 2 | 2 |
zugferd-basicwl · cii | 1 | 1 | 0 | 0 |
zugferd-basicwl · zugferd | 1 | 1 | 0 | 0 |
zugferd-extended · cii | 1 | 1 | 1 | 1 |
zugferd-extended · zugferd | 1 | 1 | 1 | 1 |
zugferd-minimum · cii | 1 | 1 | 0 | 0 |
zugferd-minimum · zugferd | 2 | 2 | 0 | 0 |
Data kit 0.1.0 (969f6f3ec8fdccbc), 722 documents, judged against each sample’s expected verdict. That verdict comes from the Beleggo project; so that it confirms more than Beleggo, every Mustang disagreement was checked by hand against the specifications, and the official KoSIT validator runs alongside as an independent reference. Where it judges differently from Beleggo, it lacks the rule: the French CTC rules and one Factur-X code list.
Beleggo artefacts 2026-08-31, Mustangproject 2.26.0, phive 4.6.0 (with every phive-rules module; phive's own document detection picks the ruleset), KoSIT validator 1.6.3 · Validator Configuration XRechnung 3.0.2 2026-09-02. Each engine runs in its own process that lives for the whole measurement — so the times measure the engine, not a Java VM starting up.