Inspect the Arithmetic — TFSA Over-Contribution Penalty Calculator
Version 1.2
Last verified: August 2026
Transparent arithmetic is the operating system of this calculator.
This document publishes the formulae, event-handling logic, and assumptions used to estimate CRA TFSA over-contribution penalties on the calculator page.
No opinions. No hidden assumptions. Just arithmetic.
Purpose
The calculator estimates the tax (penalty) that CRA may assess on TFSA over-contributions. It offers two modes: Simple (one excess amount over a fixed number of months) and Advanced (month-by-month with contributions, withdrawals, and room changes on specific dates). This page explains both methods.
A. Simple method
Simple mode is for a single lump-sum over-contribution that stayed at a constant amount for a known number of months.
Formula:
penalty = excessAmount × 1% × months
In plain language: you enter the excess amount (in dollars) and the number of whole months the excess remained. The estimate is 1% of the excess for each of those months. For example, $5,000 excess for 4 months gives penalty = 5,000 × 0.01 × 4 = $200.
When to use Simple: Only when the excess amount did not change over the period. If you had contributions or withdrawals that changed the excess during those months, use Advanced mode instead, which estimates the penalty based on the highest excess reached in each affected month.
B. Advanced method
Advanced mode estimates the penalty based on the highest excess amount in each calendar month. It processes your transactions in date order and applies the 1% rule to that highest excess per month.
1. Monthly penalty
For each calendar month in the calculation range:
monthly penalty = 0.01 × (highest excess amount in that month)
The rate is 1% (0.01). “Highest excess in that month” means the maximum value of excess reached at any point during the month, including after each transaction.
2. Total penalty
total penalty = sum of (monthly penalty) for every month in the date range
Months with no excess contribute zero to the total. The total is not “excess × number of months” unless excess is constant and unchanged for every month; the engine tracks the highest excess per month explicitly.
Why the highest excess in the month matters
CRA assesses the penalty each month based on the highest excess that existed during that month. So if you had $5,000 excess at the start of a month and then withdrew $3,000 on the 20th, your excess at the end of the month is $2,000 — but the month is still assessed on $5,000, because that was the highest excess reached in that month. A withdrawal later in the month does not erase an earlier higher excess for that same month.
The calculator therefore processes events in date order and, for each calendar month, records the maximum excess seen at any step during that month. That maximum is used for the monthly penalty.
Event-handling logic
Events are processed in chronological order. Two state variables are maintained:
- room — available TFSA contribution room (starts at your “starting room”, then adjusted by events)
- excess — amount by which contributions have exceeded room (the over-contribution)
Contribution
A contribution first uses available room; any amount that cannot be applied to room becomes (or adds to) excess.
useFromRoom = min(contribution amount, room)
room = room − useFromRoom
excess = excess + (contribution amount − useFromRoom)
Withdrawal
A withdrawal reduces current excess when it occurs but does not restore contribution room in the same calendar year.
excess = max(0, excess − withdrawal amount)
On January 1 of the following year, the full withdrawal amount is restored as contribution room. Like other room additions, it first absorbs any excess carried into January; any remainder becomes available room.
withdrawal add-back = total withdrawals made in the prior calendar year
absorbed = min(excess, withdrawal add-back)
excess = excess − absorbed
room = room + (withdrawal add-back − absorbed)
Room adjustment
A room adjustment (or the automatic Jan 1 new room) is applied once: it first absorbs current excess (reduces excess); only the remainder is added to available room. No double-counting.
absorbed = min(excess, amount)
excess = excess − absorbed
remaining = amount − absorbed
room = room + remaining
Timeline construction
- All transactions you enter with dates inside the calculation range are included; transactions outside the range are ignored.
- Withdrawals are totalled by calendar year. If the following January 1 is in range, the engine inserts a withdrawal-add-back event for that date.
- If you set annual new TFSA room (Jan 1) > 0, the engine inserts a room-adjustment event on January 1 for each year that falls within the range.
- Events are sorted by date and processed in order. On the same date, explicit and annual room adjustments are applied first, then withdrawal add-backs, withdrawals, and contributions. This makes restored room available to a contribution dated January 1.
- For each calendar month, the engine records the highest excess reached during that month and applies the 1% formula.
Worked example
Using the following inputs:
- Start date: 2026-01-01
- End date: 2026-04-30
- Starting room: 0
- Annual Jan 1 room: 7,000
- Transactions:
- 2026-01-10 — contribution — 9,000
- 2026-02-15 — withdrawal — 1,000
- 2026-03-03 — contribution — 500
Timeline (sorted):
- 2026-01-01 — Jan 1 room: room = 0 + 7,000 = 7,000; excess = 0.
- 2026-01-10 — Contribution 9,000: useFromRoom = min(9,000, 7,000) = 7,000; room = 0; excess = 0 + 2,000 = 2,000.
January: Highest excess in month = 2,000. Monthly penalty = 0.01 × 2,000 = $20.
- 2026-02-15 — Withdrawal 1,000: excess = 2,000 − 1,000 = 1,000.
February: At start of month excess was 2,000; after withdrawal, 1,000. Highest in month = 2,000. Monthly penalty = 0.01 × 2,000 = $20.
- 2026-03-03 — Contribution 500: room = 0; useFromRoom = 0; excess = 1,000 + 500 = 1,500.
March: Highest excess = 1,500. Monthly penalty = 0.01 × 1,500 = $15.
April: No events. Excess remains 1,500. Monthly penalty = 0.01 × 1,500 = $15.
Totals:
total penalty = 20 + 20 + 15 + 15 = $70
months with excess = 4
peak excess = $2,000
ending excess = $1,500
Sample input/output contract
Input shape (engine):
{
startDate: "YYYY-MM-DD",
endDate: "YYYY-MM-DD",
startingRoom: number,
annualJan1Room: number,
transactions: [
{ date: "YYYY-MM-DD", type: "contribution" | "withdrawal" | "room_adjustment", amount: number },
...
]
}
Output shape (on success):
{
totalPenalty: number,
monthsWithPenalty: number,
peakExcess: number,
endingExcess: number,
endingRoom: number,
monthlyBreakdown: [ { month, highestExcess, monthlyPenalty, ... }, ... ],
normalizedTimeline: [ ... ],
assumptions: [ string, ... ]
}
On validation failure, the engine returns { error: "message" }.
Assumptions and limitations
- Penalty is 1% per month on the highest excess in each calendar month, consistent with CRA’s stated approach. Your actual assessment may depend on CRA’s records and filing details.
- Transactions outside the selected date range are ignored; the calculator does not load or assume events before the start date or after the end date.
- Withdrawals reduce excess when made and restore contribution room on January 1 of the following year.
- Only withdrawals inside the selected date range are known to the model. To carry a prior-year withdrawal into January, the range must include both the withdrawal and the following January 1.
- Jan 1 room is applied only when “annual new TFSA room (Jan 1)” is greater than zero.
- All amounts are in CAD. Dates are in YYYY-MM-DD. Money math uses floating point; rounding is applied for display only.
- This is an educational estimate. CRA rules and your specific situation may differ. This is not tax advice.
Regression tests
The engine includes a small regression harness. In the browser console (with the calculator page loaded) or in Node after loading the engine, run TfsaOverContributionEngine.runRegressionTests(). The focused Node tests also cover prior-year withdrawal restoration and January 1 ordering.
If any discrepancy is identified between this documentation and the calculator output, the arithmetic in the engine governs.
Back to TFSA Over-Contribution Penalty Calculator
Sources and References