✦ Free Calculator

Could that Roth conversion quietly spike your Medicare bill?

IRMAA doesn't ask why your income was high for one year — a big conversion, a home sale, a bond fund cashing out gains, it all counts the same. This calculator checks your MAGI against the real 2026 tier tables and shows the surcharge in dollars, not just a bracket name. Drop it into your own article in one script tag, and it looks like it was built for your site, not bolted onto it.

Sibling of <retirement-calc-spend> — same engine, different question.

Full explanation: The IRMAA Medicare Surcharge →

See it in context

Here's exactly what that looks like — a live instance embedded inside a sample article, using someone else's fonts and colors, not ours.

medicaremoneycoach.com/blog/does-a-roth-conversion-trigger-irmaa
Medicare Planning · 5 min read

Does a Roth Conversion Trigger IRMAA? Here's the Math Nobody Shows You.

MM
Medicare Money Coach
Medicare premium & IRMAA surcharge planning

Every fall, a batch of clients gets a letter from Social Security they weren't expecting — a Medicare premium notice with a number that's hundreds of dollars higher than last year's. Almost every time, the cause traces back to a decision made two years earlier: a Roth conversion, a big capital gain, a one-time windfall. Nobody warned them the two were connected.

The brackets that actually matter

IRMAA isn't a single number — it's a set of income tiers, and MAGI (not taxable income, not AGI — modified AGI, which adds back things like muni bond interest) determines which one you land in. Cross a bracket by a single dollar and you pay the surcharge for the whole bracket, not just the amount over the line. That's the part people miss: there's no phase-in, no proration. One dollar over is treated the same as ten thousand dollars over.

The two-year lookback quirk

Your 2026 Medicare premium is based on your 2024 tax return — not this year's income, not last year's. That lag is exactly why IRMAA catches people off guard: the conversion you did two years ago, when income felt irrelevant because you weren't on Medicare yet, is the number showing up on your premium bill today. By the time the letter arrives, the year that caused it is long over.

A surcharge tier decided two years ago doesn't ask what the money was for — it just counts.

Why a single conversion year is the usual culprit

Clients rarely get surprised by steady, predictable income. They get surprised by the one-off: converting a large traditional IRA balance to Roth in a single tax year, selling a rental property, harvesting gains to rebalance a portfolio. Any of these can push MAGI into a higher IRMAA tier for exactly one year — but the surcharge still applies to that full year, dollar for dollar, regardless of the reason.

Check your number before you convert, not after

Enter your expected MAGI on the right and see which tier it lands in, what the surcharge costs per person and per household, and how close you are to the next threshold. If a planned conversion would tip you over a line, splitting it across two smaller tax years is often the fix — but only if you catch it before the year closes, not after the letter arrives.

Try it

That's the exact <retirement-calc-irmaa> widget, unmodified — same script tag, same math as the full app. See the full picture → · Jump to the embed code ↓

For developers

Everything below is for embedding this calculator on your own site — integration code, theming, and events.

Live demos

Default (single, defaults)

Themed (orange accent, single filer, pre-Medicare)

Preview your theme

Pick colors that match your site, then copy the CSS snippet at the bottom.

Theme colors

Big number, slider thumb, CTA button
#4f8ec9
Outer surface of the calc
#ffffff
Result area + toggle background
#f7f9fc
Title, slider values, result subline
#1a1f2e
retirement-calc-irmaa {
  --rc-accent: #4f8ec9;
  --rc-bg: #ffffff;
  --rc-surf: #f7f9fc;
  --rc-text: #1a1f2e;
}

Integration code

Drop this into your HTML:

<script src="https://app.retirementscenario.com/embed/v1/irmaa.js"></script>

<retirement-calc-irmaa></retirement-calc-irmaa>

Or pre-seed values relevant to your audience:

<retirement-calc-irmaa
  plan-type="household"
  current-age="67"
  annual-magi="220000">
</retirement-calc-irmaa>

Attributes

AttributeDefaultRange
plan-typehouseholdsingle or household (= MFJ)
current-age6755 – 85 (pre-65 users see forward-looking projection)
annual-magi22000050,000 – 1,000,000 (your forward-looking MAGI — IRMAA uses 2-yr lookback)
refsrc(none)partner attribution tag

Honest scope: 2026 IRS values (refresh annually with the engine's IRS-limits refresh slice). Combined Medicare Part B + Part D surcharge per person per year. Doesn't model Part A premiums (employment-based, separate). Doesn't model Medigap or Medicare Advantage premiums (plan-specific). IRMAA uses a 2-year lookback — your 2026 surcharge is based on your 2024 MAGI. Enter your forward-looking MAGI; the calc shows what would apply if MAGI stays at this level.

Theming

Override CSS custom properties on the host:

retirement-calc-irmaa {
  --rc-accent: #ff6b35;    /* primary color */
  --rc-bg: #ffffff;        /* card background */
  --rc-surf: #f7f9fc;      /* sub-surface (result area) */
  --rc-text: #1a1f2e;
  --rc-muted: #6a7280;
  --rc-border: rgba(20,30,50,0.10);
  --rc-radius: 12px;
}

Events

The element emits two custom events you can listen to:

document.querySelector('retirement-calc-irmaa')
  .addEventListener('rc-calculated', (e) => {
    console.log('IRMAA tier:', e.detail.tier);             // null = standard premium; else { tierNum, threshold, perPerson }
    console.log('Per person/yr:', e.detail.perPerson);
    console.log('Household/yr:', e.detail.householdAnnual);
    console.log('Distance over current tier:', e.detail.distanceFromCurrentTier);
    console.log('Distance to next tier:', e.detail.distanceToNextTier);
    console.log('Medicare-eligible?', e.detail.medicareEligible);
  });

document.querySelector('retirement-calc-irmaa')
  .addEventListener('rc-cta-clicked', (e) => {
    console.log('User clicked CTA to:', e.detail.url);
  });