Measured, not claimed

Validation engines compared

Beleggo, Mustangproject, phive and 16 more 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

All 19 engines at a glance

EngineRuntimeLicenceProfilesCorrectFalse alarmsMissedRule namedMedianMemory
Beleggoartefacts 2026-08-31JavaScriptproprietaryall100%1,665 documents001,0965.7 ms854 MB
dealerweb/einvoice1.2.2PHP 8MIT7 / 1199.2%1,186 documents01063649 ms215 MB
KoSIT Validator1.6.3 · Validator Configuration XRechnung 3.0.2 2026-09-02 · referenceJava 11+Apache-2.01 / 1198.6%295 documents004318 ms1,623 MB
core-invoice (Rust CLI)2.0.3RustMIT OR Apache-2.02 / 1190.3%874 documents33523452.3 ms33 MB
phive4.6.0Java 17+Apache-2.0all89.8%1,665 documents01609258.4 ms942 MB
Mustangproject2.26.0Java 11+Apache-2.06 / 1185%1,077 documents1015244943 ms1,201 MB
en16931 (npm)0.1.0Node.jsMIT AND EUPL-1.21 / 1184.6%765 documents211340376 ms336 MB
@kontor-mcp/core1.0.4Node.jsApache-2.02 / 1184.3%1,060 documents0153420147 ms610 MB
verifyhash-einvoice0.2.9Python 3Apache-2.02 / 1183.1%1,060 documents51744191.9 ms61 MB
verifaktura0.1.8Node.jsApache-2.02 / 1181.9%810 documents014743260 ms501 MB
EU ITB eInvoicing validator1.14.0-SNAPSHOT (2026-11-05) · CEN 1.3.16Java 17+EUPL-1.21 / 1181.3%765 documents0143423193 ms938 MB
einvoice-kit0.1.3Node.jsMIT1 / 1180%765 documents11523671.1 ms150 MB
@attestwire/en169310.14.0Node.jsMIT3 / 1180%1,169 documents122223811.5 ms151 MB
speedata/einvoicev0.0.22GoBSD-3-Clause3 / 1176.8%1,169 documents272443427.7 ms49 MB
stampbench (@stampbench/core)0.1.1Node.jsMIT2 / 1171.9%1,060 documents132852191.6 ms326 MB
en16931 (Rust CLI)0.6.0RustMIT OR Apache-2.03 / 1168.9%1,169 documents1442203292.5 ms23 MB
@fin.cx/einvoice11.1.1Node.jsMIT2 / 1159.7%1,060 documents2540211011 ms372 MB
KoSIT Validator + ZUGFeRD configuration1.6.3 · Validator Configuration ZUGFeRD 2.5.2 2026-06-11 · referenceJava 11+Apache-2.04 / 1152.9%17 documents08634.7 ms939 MB
factur-x (akretion)6.8Python 3BSD-2-Clause4 / 1152.9%17 documents08150.3 ms66 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).

In detail: Beleggo, Mustangproject and phive

Correct verdicts

MeasureBeleggoMustangprojectphiveAhead
Correct verdicts, every documentagainst each sample’s expected verdict1,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 checks1,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 for291 / 291 (100%)274 / 291 (94.2%)278 / 291 (95.5%)Beleggo
Defects named with the right rulenot just rejected, but the broken rule reported1,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 knows11 / 116 / 1111 / 11Beleggo · phive

Speed and cost

MeasureBeleggoMustangprojectphiveAhead
Time per document (median)after warm-up5.7 ms43 ms8.4 msBeleggo
Time per document (95th percentile)the slow documents19 ms78 ms27 msBeleggo
Documents per secondone document at a time77.516.868.9Beleggo
CPU time per documentall threads together18 ms93 ms33 msBeleggo
One-shot call (start + first document)what a command-line call costs385 ms5,832 ms3,943 msBeleggo
Memory (peak)of the whole process854 MB1,201 MB942 MBBeleggo
Install sizerules and runtime, without Node.js or Java16 MB56 MB58 MBBeleggo

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.

What each engine does

BeleggoMustangprojectphive
EN 16931 (UBL and CII)yesyesyes
XRechnung 3 with the official KoSIT severitiesyespartlypartly
Peppol BIS 3 and Peppol country rulesyesnoyes
NLCIUS, CIUS-RO, HR-CIUS, CIUS-PTyesnoyes
Factur-X / ZUGFeRD profiles (XSD and Schematron)yesyesyes
Visible PDF page checked against the XMLyesnono
Check digits (IBAN, VAT id, Leitweg-ID, tax number …)yesnono
Runs in the browser, no upload, no serveryesnono
Full PDF/A-3 validation (every rule of the veraPDF profiles)yesyesno
ZUGFeRD 1.0 and Order-Xyesyesno
French CTC rules (BR-FR Flux 2) as errors, in UBL and CIIyespartlyyes
XRechnung Schematron, current edition (2.6.0)yespartlyyes
Peppol BIS 3 in CIIyesnono
EXTENDED-CTC-FR and Flux 10 e-reporting (France)yespartlyyes
Every line recomputed (quantity × price)yesyesno
Warnings already announced as future errorsyesnono
Peppol PINT (EU, A-NZ, SG, JP, MY, AE, OM) — Beleggo in its CLI and MCP server, rules fetched from OpenPeppolyesnoyes
Peppol Invoice Response and Message Level Statusyesnoyes

Where and why they differ

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:

By profile

ProfileDocumentsBeleggoMustangprojectphive
en16931 · cii184184126121
en16931 · ubl419419340339
en16931 · zugferd162162162161
hr-cius · ubl4545545
nlcius · ubl2020919
peppol-bis3 · cii2211
peppol-bis3 · ubl10610656104
peppol-bis3 · zugferd1111
pt-cius · ubl302302101302
ro-cius · ubl11211224112
xrechnung · cii172172160164
xrechnung · ubl1001009595
xrechnung · zugferd23232323
zugferd-basic · cii1111
zugferd-basic · zugferd3333
zugferd-basicwl · cii1100
zugferd-basicwl · zugferd3300
zugferd-extended · cii2222
zugferd-extended · zugferd3333
zugferd-minimum · cii1100
zugferd-minimum · zugferd3300

How it was measured

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.