Skip to content

Update the pension tax relief docs page (#704) - #1721

Merged
vahid-ahmadi merged 8 commits into
mainfrom
vahid-ahmadi/issue-704-pension-tax-relief-docs
Oct 24, 2026
Merged

vahid-ahmadi merged 8 commits into
mainfrom
vahid-ahmadi/issue-704-pension-tax-relief-docs

Conversation

@vahid-ahmadi

@vahid-ahmadi vahid-ahmadi commented May 27, 2026 •

Copy link
Copy Markdown
Collaborator

Corrects the pension tax relief page (docs/book/programs/gov/hmrc/pension-tax-relief.md), written for #704.

The page itself is already on main: it shipped in #2386 (merged 21 October 2026), and its original .added changelog entry was released in 2.143.0. This branch has merged main, dropped the released fragment and now carries only corrections to main's copy of the page.

What this PR corrects (from its changelog fragment):

Brought the pension tax relief page (docs/book/programs/gov/hmrc/pension-tax-relief.md) up to date with main: #2488 has merged, unused annual allowance is now estimated from 2020-21 rather than defaulting to nil, defined-benefit accrual can be supplied as defined_benefit_pension_input_amount, with defined_benefit_pension_share for the workplace contributions it replaces, relevant UK earnings follow taxable employment income and trading profit before losses, relief-at-source contributions stay in income for the annual allowance charge and raise its rate limits only under the s. 192(4) condition, which HMRC's PTM056120 does not state, and s. 192(4) raises the higher rate limit as well as the basic rate limit. The worked examples were re-run on policyengine-uk 2.148.2.

The claim-by-claim review behind these corrections, with sources, is in the "Ready for hub review" comment on this PR.

  • Changelog fragment: changelog.d/704-pension-tax-relief-page-corrections.changed.md (changed).
  • Docs and changelog only; no code changes.

🤖 Generated with Claude Code

@vahid-ahmadi
vahid-ahmadi force-pushed the vahid-ahmadi/issue-704-pension-tax-relief-docs branch 2 times, most recently from 8a85069 to 486961e Compare October 8, 2026 14:55
vahid-ahmadi and others added 3 commits October 12, 2026 11:02
#704 reported four worked scenarios where the user expected higher-rate
pension contributions to produce only basic-rate (20%) relief, but the
model returned full marginal-rate (40%) reductions in income tax.

Investigation: the model is correct. The reported numbers match HMRC's
treatment in aggregate (RAS + higher-rate top-up via Self Assessment).
The user's mental model only counted the first half (relief at source).

Persist the explanation in a docs page covering:

- how pension_contributions_relief works (reduces taxable income by the
  contribution amount, capped at annual allowance / basic amount /
  earned income / age limit),
- the four #704 worked scenarios with PolicyEngine's exact returns and
  the marginal-rate arithmetic that produces them,
- the two-part real-world mechanism (RAS + basic-rate-band extension)
  and why PolicyEngine reports the combined total (matches HMRC
  pension tax relief statistics methodology),
- a note that the 0% marginal-tax-rate display reported in the issue
  is a frontend concern in the policyengine.org app, not the model
  repo,
- references to FA 2004 s.188-194 and s.227, HMRC's user-facing pension
  tax relief guide, and pension tax relief statistics.
…elog fragment

Checked every variable, parameter, path and link against main in October
2026, updated the data pipeline references to Microcosm UK, and renamed the
changelog fragment to a Towncrier type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-ran the four #704 cases on policyengine-uk 2.126.12 (income tax falls by
£600 and £2,400, unchanged) and the £110,000 personal allowance example.
Described the tapered annual allowance from its parameters, the wider
contribution base for the annual allowance charge, and that the charge is
added to income tax. Rewrote the marginal tax rate section: the model has
its own marginal_tax_rate variable, which now returns 20% and 40% for these
cases, so the reported 0% no longer reproduces. Fixed code links that
pointed outside the repo, removed em dashes, and dropped the extra bullet
from the changelog fragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vahid-ahmadi
vahid-ahmadi force-pushed the vahid-ahmadi/issue-704-pension-tax-relief-docs branch from 486961e to 8e28c70 Compare October 12, 2026 09:10
MaxGhenis and others added 5 commits October 23, 2026 02:09
Main already carries a later, reviewed version of this page (added by #2386
and revised on its branch through 20 October); the conflict resolves to
main's version before the page is corrected.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's version of the page predates #2488 (merged 20 October) and #2536
(merged 21 October). Corrections, each checked against main a45baf5:

- #2488 has merged; the page no longer calls it open.
- unused_pension_annual_allowance is estimated from 2020-21
  (formula_2020) rather than defaulting to nil; nil for the £100k example.
- Defined-benefit accrual counts through defined_benefit_pension_share and
  defined_benefit_pension_input_amount, not only a supplied
  pension_contributions_for_annual_allowance.
- Relevant UK earnings are taxable employment income (less expenses) plus
  trading profit after capital allowances and the trading allowance, before
  losses (utils/pensions.py).
- The annual allowance charge keeps relief-at-source contributions in
  income and raises the rate limits only when s. 192(4)'s condition holds
  (private_pension_contributions_tax.py); new £2,946 example.
- s. 192(4) raises the higher rate limit too; the higher-rate top-up can be
  claimed outside Self Assessment and differs in Scotland.
- The model gives no relief on basic-rate RAS above taxable income.
- Tapered allowance minimum was £4,000 in 2020-21 to 2022-23.
- marginal_tax_rate perturbs the two eldest adults in turn.
- #704 gives no year or age, and its reporter expected £0 and -£1,200, so
  the column is the total relief; examples re-run on 2.148.2.
- Replaced the released .added fragment with a .changed fragment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the independent review of the corrections:
- The £45,000 example's £2,946 arises because s. 192(4)'s condition fails
  (income below the basic rate limit), so the limits are not raised; HMRC's
  PTM056120 states no such condition and would give £2,000. The page now
  says the model follows the statute (as docs/engineering/gift-aid.md does).
- defined_benefit_pension_input_amount must be supplied with
  defined_benefit_pension_share; alone it double counts, and a share alone
  changes nothing (defined_benefit_input_per_contribution is 1).
- The model also gives less than the 20% relief at source on contributions
  coming off income taxed below 20% (dividends, the Scottish starter band).
- The carry-forward estimate applies s. 228A(7) to each earlier excess.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…eves

Second-round review, checked against FA 2004 s. 192(4)-(4A) and a household
run on main:
- s. 192(4) turns on tax at the higher or additional rate, so savings
  (from 2017-18) and dividends do not count, and the model also leaves out
  property income from 2027-28 (private_pension_contributions_tax.py);
  Scottish limits are raised under s. 192(4A).
- Where only savings or dividends sit above the basic rate limit the
  model's deduction gives more than the 20% relief at source: £15,000 pay
  and £60,000 dividends with £10,000 gross contributions saves £3,648 in
  the model (2025-26) against £2,000 in law.
- Re-wrapped two long lines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tals

Third-round review, re-run on main: where only dividends sit above the
basic rate limit the model's saving can exceed the 20% in law (£15,000 pay
and £60,000 dividends: £3,648 against £2,000) or fall short of it (£12,000
and £40,000: £1,307.50). The headline, the "full marginal rate" sentence,
the two-mechanism section and the presentation note now hold only for
income taxed at one rate; s. 192(4A) wording follows the statute.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Collaborator

UK hub (Claude build session, for Max)
Ready for hub review

Head: 87eaa7b59d13d4e7dde95571851702f7c8517d82

Context. A later, reviewed version of this page reached main through #2386 (merged 21 October 2026), and its 704.added.md entry is already in CHANGELOG.md under 2.143.0. This branch still had the 12 October version. I merged origin/main into this branch (no rebase, no force-push), resolved the add/add conflict to main's version, deleted the released .added fragment, and corrected main's version. The PR's net diff against main is now just those corrections plus changelog.d/704-pension-tax-relief-page-corrections.changed.md. Suggested title: "Bring the pension tax relief page up to date".

Why it needed updating. Main's page predates #2488 (merged 20 October) and #2536 (merged 21 October).

Review. I had a verifier extract and check every claim, and re-ran every worked example on main myself (household simulations; script pension_examples.py). Independent adversarial reviews followed: rounds 1 to 3 asked for changes, and round 4 approved this head.

Corrected (15)

  1. Restrict the ordinary ATI pension uplift to relief at source #2488 merged on 20 October 2026; the page no longer calls it open (gh api .../pulls/2488).
  2. unused_pension_annual_allowance is estimated from 2020-21 from an assumed five-year history, applying s. 228A(7). It no longer "defaults to nil" (variables/gov/hmrc/pensions/unused_pension_annual_allowance.py:51-86, Fix the annual allowance on survey data, the UC benefit cap earnings threshold, relevant UK earnings and Scottish water uprating #2536). It is nil for the £100,000 example; a £50,000 employee contributing £5,000 gets £146,480.
  3. Defined-benefit accrual: supply defined_benefit_pension_input_amount together with defined_benefit_pension_share. The input alone double counts, and the share alone changes nothing before 75, since defined_benefit_input_per_contribution is 1. Sources: defined_benefit_pension_input_amount.py:38-42 and pension_contributions_for_annual_allowance.py.
  4. Relevant UK earnings are taxable employment income (less expenses) plus trading profit after capital allowances and the trading allowance, before losses (utils/pensions.py:6-42).
  5. The tapered allowance minimum was £4,000 from 2020-21 to 2022-23 (parameters/gov/hmrc/income_tax/allowances/annual_allowance/minimum.yaml).
  6. Annual allowance charge: relief-at-source contributions stay in income. Section 192(4) raises the basic and higher rate limits only if tax at the higher or additional rate would otherwise be due, and s. 192(4A) covers Scottish taxpayers (https://www.legislation.gov.uk/ukpga/2004/12/section/192; private_pension_contributions_tax.py:58-130).
  7. New worked example: £45,000 employee, £20,000 relief at source and £50,000 employer contributions gives a £2,946 charge in the model; a net pay arrangement gives £2,000. HMRC's PTM056120 states no s. 192(4) condition and would give £2,000. The model follows the statute, as docs/engineering/gift-aid.md:149-155 notes.
  8. Section 192(4) raises the higher rate limit as well as the basic rate limit. The top-up can be claimed outside Self Assessment, and the stated rates apply in England, Wales and Northern Ireland.
  9. Relief at source worth more than the tax saved: the model gives less than the law for contributions above taxable income (£720 on £3,600) and for those coming off income taxed below 20% (dividends, the Scottish starter band).
  10. Where only dividends or savings sit above the basic rate limit, the model can give more or less than the law. Re-run on main: £15,000 pay plus £60,000 dividends saves £3,648 against £2,000 in law; £12,000 plus £40,000 saves £1,308.
  11. The headline, the "full marginal rate" sentence, the two-mechanism section and the "presentation question" note are now limited to income taxed at one rate.
  12. Pension tax relief calculations #704 gives no year or age, so the page now says the scenarios were re-run for 2025-26 at age 40.
  13. Pension tax relief calculations #704's reporter expected £0 and -£1,200, so the column is now "Total relief as an income-tax change".
  14. marginal_tax_rate raises the two eldest adults' pay in turn (marginal_tax_rate.py:30-51; gov.simulation.marginal_tax_rate_adults = 2). The re-run version is 2.148.2, not 2.140.0.
  15. Replaced the released .added fragment with a .changed fragment.

Checked and correct (re-run on main 2.148.2)

  • Pension tax relief calculations #704 cases: income tax change -£600 and -£2,400; marginal tax rate 20% and 40%.
  • £3,600 personal contribution with no earnings: £3,600 relief; as an employee contribution: £0.
  • £100,000 employee paying £70,000: £70,000 relief and a £2,000 charge, falling to £0 with £10,000 carried forward.
  • £110,000 employee: personal allowance £7,570, or £12,570 after a £10,000 contribution.

Law and code checked:

Uncertain

  • Which reading of s. 192(4) HMRC applies in practice (statute or PTM056120) is a methodology question that docs/engineering/gift-aid.md already records. The page states both.

@vahid-ahmadi vahid-ahmadi changed the title Document pension tax relief mechanics (#704) Update the pension tax relief docs page (#704) Oct 23, 2026
@vahid-ahmadi
vahid-ahmadi added this pull request to the merge queue Oct 23, 2026
Merged via the queue into main with commit 44e72eb Oct 24, 2026
10 checks passed
@vahid-ahmadi
vahid-ahmadi deleted the vahid-ahmadi/issue-704-pension-tax-relief-docs branch October 24, 2026 08:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants