How the Luxembourg indépendant calculator is verified
Inputs
| Input | Field | Type |
|---|---|---|
| Annual profit after expenses (EUR) | annualProfit | number |
The formula
Each derived value below is computed by the Valem engine from the expression shown, in this order. Nothing else runs — there is no hidden code path.
| Derived value | Field | Formula (JSONata) |
|---|---|---|
| Income tax (class 1) | baseTax | ($t := annualProfit; $round(0.08 * $max([0, $min([$t, 15400]) - 13200]) + 0.09 * $max([0, $min([$t, 17600]) - 15400]) + 0.10 * $max([0, $min([$t, 19800]) - 17600]) + 0.11 * $max([0, $min([$t, 22050]) - 19800]) + 0.12 * $max([0, $min([$t, 24250]) - 22050]) + 0.14 * $max([0, $min([$t, 26550]) - 24250]) + 0.16 * $max([0, $min([$t, 28800]) - 26550]) + 0.18 * $max([0, $min([$t, 31100]) - 28800]) + 0.20 * $max([0, $min([$t, 33400]) - 31100]) + 0.22 * $max([0, $min([$t, 35700]) - 33400]) + 0.24 * $max([0, $min([$t, 38000]) - 35700]) + 0.26 * $max([0, $min([$t, 40300]) - 38000]) + 0.28 * $max([0, $min([$t, 42600]) - 40300]) + 0.30 * $max([0, $min([$t, 44900]) - 42600]) + 0.32 * $max([0, $min([$t, 47200]) - 44900]) + 0.34 * $max([0, $min([$t, 49500]) - 47200]) + 0.36 * $max([0, $min([$t, 51750]) - 49500]) + 0.38 * $max([0, $min([$t, 54050]) - 51750]) + 0.39 * $max([0, $min([$t, 117450]) - 54050]) + 0.40 * $max([0, $min([$t, 176150]) - 117450]) + 0.41 * $max([0, $min([$t, 234850]) - 176150]) + 0.42 * $max([0, $t - 234850]), 2)) |
| Employment fund surcharge | employmentFund | $round(baseTax * (annualProfit > $const.employmentFundThreshold ? $const.employmentFundHighRate : $const.employmentFundRate), 2) |
| Income after tax (before contributions) | incomeAfterTax | $round($max([0, annualProfit - baseTax - employmentFund]), 2) |
Rates and thresholds
The expressions above read these as $const. They are the figures the annual refresh replaces, so they live as data rather than being written into the formulas — which is what makes a year-on-year change a one-line diff instead of an edit to arithmetic.
| Constant | Value |
|---|---|
employmentFundRate | 0.07 |
employmentFundHighRate | 0.09 |
employmentFundThreshold | 150000 |
Test vectors (3)
Every case is executed against this model on each build, by the Java engine and independently by a JavaScript one. A mismatch of a single cent fails the build, so the page cannot ship advertising a figure the model no longer produces.
Case 1 — 70,000 EUR profit — a typical full-time indépendant
given annualProfit | 70000 |
|---|---|
expect baseTax | 15074 |
expect employmentFund | 1055.18 |
expect incomeAfterTax | 53870.82 |
Case 2 — 25,000 EUR — part-time
given annualProfit | 25000 |
|---|---|
expect baseTax | 1210.5 |
expect employmentFund | 84.74 |
expect incomeAfterTax | 23704.76 |
Case 3 — 200,000 EUR — above the 9% employment fund threshold
given annualProfit | 200000 |
|---|---|
expect baseTax | 66838 |
expect employmentFund | 6015.42 |
expect incomeAfterTax | 127146.58 |
Sources
- Administration des contributions directes — Barèmes · checked 2026-08-22
- The tax scale in Luxembourg — class 1 brackets and the employment fund surcharge · checked 2026-08-22
Check it yourself — and reuse it
The whole model as JSON — inputs, outputs, formulas, vectors and sources in one re-runnable document.
This model is published under CC BY 4.0: use it, adapt it, build on it, with attribution. The licence covers the model — the expression of each rule and the arrangement of the catalog. The rates and thresholds are law, and nobody licenses those; the sources above are where they come from.
← Back to the Luxembourg indépendant calculator
Built with Valem — a live, verifiable calculator you can fork and embed.