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 6 November 2026 on linux x64, Intel(R) Xeon(R) Processor @ 2.10GHz × 4, 16 GiB, Node v22.23.4
| Engine | Runtime | Licence | Profiles | Correct | False alarms | Missed | Rule named | Median | Memory |
|---|---|---|---|---|---|---|---|---|---|
| Beleggoartefacts 2026-08-31 | JavaScript | proprietary | all | 100%1,665 documents | 0 | 0 | 1,096 | 5.7 ms | 854 MB |
| dealerweb/einvoice1.2.2 | PHP 8 | MIT | 7 / 11 | 99.2%1,186 documents | 0 | 10 | 636 | 49 ms | 215 MB |
| KoSIT Validator1.6.3 · Validator Configuration XRechnung 3.0.2 2026-09-02 · reference | Java 11+ | Apache-2.0 | 1 / 11 | 98.6%295 documents | 0 | 0 | 431 | 8 ms | 1,623 MB |
| core-invoice (Rust CLI)2.0.3 | Rust | MIT OR Apache-2.0 | 2 / 11 | 90.3%874 documents | 33 | 52 | 345 | 2.3 ms | 33 MB |
| phive4.6.0 | Java 17+ | Apache-2.0 | all | 89.8%1,665 documents | 0 | 160 | 925 | 8.4 ms | 942 MB |
| Mustangproject2.26.0 | Java 11+ | Apache-2.0 | 6 / 11 | 85%1,077 documents | 10 | 152 | 449 | 43 ms | 1,201 MB |
| en16931 (npm)0.1.0 | Node.js | MIT AND EUPL-1.2 | 1 / 11 | 84.6%765 documents | 2 | 113 | 403 | 76 ms | 336 MB |
| @kontor-mcp/core1.0.4 | Node.js | Apache-2.0 | 2 / 11 | 84.3%1,060 documents | 0 | 153 | 420 | 147 ms | 610 MB |
| verifyhash-einvoice0.2.9 | Python 3 | Apache-2.0 | 2 / 11 | 83.1%1,060 documents | 5 | 174 | 419 | 1.9 ms | 61 MB |
| verifaktura0.1.8 | Node.js | Apache-2.0 | 2 / 11 | 81.9%810 documents | 0 | 147 | 432 | 60 ms | 501 MB |
| EU ITB eInvoicing validator1.14.0-SNAPSHOT (2026-11-05) · CEN 1.3.16 | Java 17+ | EUPL-1.2 | 1 / 11 | 81.3%765 documents | 0 | 143 | 423 | 193 ms | 938 MB |
| einvoice-kit0.1.3 | Node.js | MIT | 1 / 11 | 80%765 documents | 1 | 152 | 367 | 1.1 ms | 150 MB |
| @attestwire/en169310.14.0 | Node.js | MIT | 3 / 11 | 80%1,169 documents | 12 | 222 | 381 | 1.5 ms | 151 MB |
| speedata/einvoicev0.0.22 | Go | BSD-3-Clause | 3 / 11 | 76.8%1,169 documents | 27 | 244 | 342 | 7.7 ms | 49 MB |
| stampbench (@stampbench/core)0.1.1 | Node.js | MIT | 2 / 11 | 71.9%1,060 documents | 13 | 285 | 219 | 1.6 ms | 326 MB |
| en16931 (Rust CLI)0.6.0 | Rust | MIT OR Apache-2.0 | 3 / 11 | 68.9%1,169 documents | 144 | 220 | 329 | 2.5 ms | 23 MB |
| @fin.cx/einvoice11.1.1 | Node.js | MIT | 2 / 11 | 59.7%1,060 documents | 25 | 402 | 110 | 11 ms | 372 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 | 939 MB |
| factur-x (akretion)6.8 | Python 3 | BSD-2-Clause | 4 / 11 | 52.9%17 documents | 0 | 8 | 15 | 0.3 ms | 66 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 6 November 2026.
“Rule named”: of the 1,096 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,665 / 1,665 (100%) | 1,112 / 1,665 (66.8%) | 1,496 / 1,665 (89.8%) | Beleggo |
| Correct verdicts in Mustang’s profilesonly the profiles Mustang itself checks | 1,077 / 1,077 (100%) | 915 / 1,077 (85%) | 912 / 1,077 (84.7%) | Beleggo |
| Agreement with the KoSIT validatoron every XRechnung document — the scope the official validator is responsible for | 291 / 291 (100%) | 274 / 291 (94.2%) | 278 / 291 (95.5%) | Beleggo |
| Defects named with the right rulenot just rejected, but the broken rule reported | 1,096 / 1,096 (100%) | 449 / 1,096 (41%) | 925 / 1,096 (84.4%) | 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 | 43 ms | 8.4 ms | Beleggo |
| Time per document (95th percentile)the slow documents | 19 ms | 78 ms | 27 ms | Beleggo |
| Documents per secondone document at a time | 77.5 | 16.8 | 68.9 | Beleggo |
| CPU time per documentall threads together | 18 ms | 93 ms | 33 ms | Beleggo |
| One-shot call (start + first document)what a command-line call costs | 385 ms | 5,832 ms | 3,943 ms | Beleggo |
| Memory (peak)of the whole process | 854 MB | 1,201 MB | 942 MB | Beleggo |
| Install sizerules and runtime, without Node.js or Java | 16 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 553 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 | 172 | 160 | 164 |
xrechnung · ubl | 100 | 100 | 95 | 95 |
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 (a43e5b5fd46d8e73), 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.