Measured, not claimed
Validation engines compared
19 validation engines check the same 1,665 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 22 October 2026 on linux x64, Intel(R) Core(TM) Ultra 9 185H × 22, 62 GiB, Node v24.22.1
| Engine | Runtime | Licence | Profiles | Correct | False alarms | Missed | Rule named | Median | Memory |
|---|---|---|---|---|---|---|---|---|---|
| Beleggoartefacts 2026-08-31 | JavaScript | proprietary | all | 100%1,655 documents | 0 | 0 | 1,086 | 5.7 ms | 962 MB |
| KoSIT Validator1.6.3 · Validator Configuration XRechnung 3.0.2 2026-09-02 · reference | Java 11+ | Apache-2.0 | 1 / 11 | 98.6%285 documents | 0 | 0 | 421 | 9.2 ms | 1,397 MB |
| core-invoice (Rust CLI)2.0.3 | Rust | MIT OR Apache-2.0 | 2 / 11 | 90.3%874 documents | 33 | 52 | 341 | 2.6 ms | 33 MB |
| phive4.6.0 | Java 17+ | Apache-2.0 | all | 89.8%1,655 documents | 0 | 160 | 915 | 8.2 ms | 1,099 MB |
| dealerweb/einvoice1.1.0 | PHP 8 | MIT | 7 / 11 | 88.3%1,176 documents | 3 | 135 | 479 | 28 ms | 152 MB |
| Mustangproject2.26.0 | Java 11+ | Apache-2.0 | 6 / 11 | 84.8%1,067 documents | 10 | 152 | 439 | 50 ms | 1,343 MB |
| en16931 (npm)0.1.0 | Node.js | MIT AND EUPL-1.2 | 1 / 11 | 84.6%765 documents | 2 | 113 | 399 | 77 ms | 361 MB |
| @kontor-mcp/core1.0.4 | Node.js | Apache-2.0 | 2 / 11 | 84.2%1,050 documents | 0 | 153 | 410 | 80 ms | 660 MB |
| verifyhash-einvoice0.2.9 | Python 3 | Apache-2.0 | 2 / 11 | 83.1%1,050 documents | 5 | 172 | 411 | 1.1 ms | 63 MB |
| verifaktura0.1.8 | Node.js | Apache-2.0 | 2 / 11 | 81.9%810 documents | 0 | 147 | 428 | 31 ms | 435 MB |
| EU ITB eInvoicing validator1.14.0-SNAPSHOT (2026-10-21) · CEN 1.3.16 | Java 17+ | EUPL-1.2 | 1 / 11 | 81.3%765 documents | 0 | 143 | 417 | 118 ms | 1,234 MB |
| @attestwire/en169310.14.0 | Node.js | MIT | 3 / 11 | 80.2%1,159 documents | 12 | 218 | 375 | 2 ms | 223 MB |
| einvoice-kit0.1.3 | Node.js | MIT | 1 / 11 | 80%765 documents | 1 | 152 | 363 | 0.3 ms | 189 MB |
| speedata/einvoicev0.0.22 | Go | BSD-3-Clause | 3 / 11 | 76.8%1,159 documents | 27 | 242 | 334 | 5 ms | 51 MB |
| stampbench (@stampbench/core)0.1.1 | Node.js | MIT | 2 / 11 | 71.8%1,050 documents | 13 | 283 | 211 | 0.7 ms | 407 MB |
| en16931 (Rust CLI)0.6.0 | Rust | MIT OR Apache-2.0 | 3 / 11 | 68.8%1,159 documents | 144 | 218 | 321 | 2.8 ms | 23 MB |
| @fin.cx/einvoice11.1.1 | Node.js | MIT | 2 / 11 | 59.9%1,050 documents | 25 | 396 | 106 | 5.1 ms | 383 MB |
| KoSIT Validator + ZUGFeRD configuration1.6.3 · Validator Configuration ZUGFeRD 2.5.2 2026-06-11 · reference | Java 11+ | Apache-2.0 | 4 / 11 | 52.9%17 documents | 0 | 8 | 63 | 4.7 ms | 975 MB |
| factur-x (akretion)6.8 | Python 3 | BSD-2-Clause | 4 / 11 | 52.9%17 documents | 0 | 8 | 14 | 0.5 ms | 69 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 22 – 23 October 2026.
“Rule named”: of the 1,086 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.
Not measured on the current kit, so not in the table: International.EInvoicing (.NET CLI): no .NET SDK on the machine that ran the bench (last measured 27 Sept 2026 over 722 documents); @aifind/mustangjs: no answer on a 1,000-line invoice (DK-790) within 15 minutes (last measured 27 Sept 2026 over 722 documents); Klarfakt: no .NET SDK on the machine that ran the bench (last measured 29 Sept 2026 over 722 documents); john-wink/en16931-php: its composer.lock does not install on the PHP of the machine that ran the bench (last measured 29 Sept 2026 over 722 documents); en16931 (Dart): no Dart SDK on the machine that ran the bench (last measured 29 Sept 2026 over 722 documents).
| Measure | Beleggo | Mustangproject | phive | Ahead |
|---|---|---|---|---|
| Correct verdicts, every documentagainst each sample’s expected verdict | 1,655 / 1,665 (99.4%) | 1,102 / 1,665 (66.2%) | 1,486 / 1,665 (89.2%) | Beleggo |
| Correct verdicts in Mustang’s profilesonly the profiles Mustang itself checks | 1,067 / 1,077 (99.1%) | 905 / 1,077 (84%) | 902 / 1,077 (83.8%) | Beleggo |
| Agreement with the KoSIT validatoron every XRechnung document — the scope the official validator is responsible for | 281 / 281 (100%) | 264 / 281 (94%) | 268 / 281 (95.4%) | Beleggo |
| Defects named with the right rulenot just rejected, but the broken rule reported | 1,086 / 1,086 (100%) | 439 / 1,086 (40.4%) | 915 / 1,086 (84.3%) | 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.7 ms | 50 ms | 8.2 ms | Beleggo |
| Time per document (95th percentile)the slow documents | 12 ms | 82 ms | 17 ms | Beleggo |
| Documents per secondone document at a time | 113.6 | 16 | 74.1 | Beleggo |
| CPU time per documentall threads together | 12 ms | 124 ms | 37 ms | Beleggo |
| One-shot call (start + first document)what a command-line call costs | 187 ms | 3,541 ms | 4,322 ms | Beleggo |
| Memory (peak)of the whole process | 962 MB | 1,343 MB | 1,099 MB | Beleggo |
| Install sizerules and runtime, without Node.js or Java | 56 MB | 56 MB | 58 MB | Beleggo · Mustangproject |
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 563 of 1,665 documents, 391 of them in profiles it does not check at all. The rest have five causes:
| Profile | Documents | Beleggo | Mustangproject | phive |
|---|---|---|---|---|
en16931 · cii | 184 | 184 | 126 | 121 |
en16931 · ubl | 419 | 419 | 340 | 339 |
en16931 · zugferd | 162 | 162 | 162 | 161 |
hr-cius · ubl | 45 | 45 | 5 | 45 |
nlcius · ubl | 20 | 20 | 9 | 19 |
peppol-bis3 · cii | 2 | 2 | 1 | 1 |
peppol-bis3 · ubl | 106 | 106 | 56 | 104 |
peppol-bis3 · zugferd | 1 | 1 | 1 | 1 |
pt-cius · ubl | 302 | 302 | 101 | 302 |
ro-cius · ubl | 112 | 112 | 24 | 112 |
xrechnung · cii | 172 | 167 | 155 | 159 |
xrechnung · ubl | 100 | 95 | 90 | 90 |
xrechnung · zugferd | 23 | 23 | 23 | 23 |
zugferd-basic · cii | 1 | 1 | 1 | 1 |
zugferd-basic · zugferd | 3 | 3 | 3 | 3 |
zugferd-basicwl · cii | 1 | 1 | 0 | 0 |
zugferd-basicwl · zugferd | 3 | 3 | 0 | 0 |
zugferd-extended · cii | 2 | 2 | 2 | 2 |
zugferd-extended · zugferd | 3 | 3 | 3 | 3 |
zugferd-minimum · cii | 1 | 1 | 0 | 0 |
zugferd-minimum · zugferd | 3 | 3 | 0 | 0 |
Data kit 0.1.0 (8c8d13d3eed69eec), 1,665 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.