Calculation catalog › Spending and withdrawals

SEPP distribution annual

Penalty-free 72(t) substantially-equal periodic payment distributed this year (included in traditional withdrawals).

Field: SEPP distribution Unit: US dollars Basis: nominal dollars Computed by: Engine Status: Complete chain

Appears in: cash-flow-drilldown (seppDistribution source line)

Calculation records

  • SEPP amortization-method annual amount Model record, justified by derivation

    Purpose: Fix the annual 72(t) payment from the first-year balance as an ordinary annuity over the Single Life term.

    Statement: strategies/sepp.ts#seppAnnualAmount fixes the amortization-method annual SEPP from the first-year balance as an ordinary-annuity payment over the Single Life Table term at the selected annual rate, with the module's default 5% carried by SEPP_AMORTIZATION_RATE_PCT to satisfy the Notice 2022-6 section 3.02(c) greater-of-5%-or-120%-mid-term ceiling in every rate environment. A zero rate degenerates to balance divided by the term. Units: nominal USD per year. Rounding: none; the result is a binary float compared to cents.

    Formula: A = B r / (1 - (1 + r)^(-n)), and B / n when r = 0

    • B: First SEPP year balance (unit: usd) (domain: positive; a nonpositive balance pays 0)
    • r: Annual rate as a fraction, ratePct / 100 (unit: 1) (domain: r >= 0)
    • n: Single Life Table term for the start age, year2026.rmd.singleLifeTable (unit: years) (domain: positive)

    Timing: fixed once at the first SEPP year and held for the series

    Rounding: none

    Limits:

    • The payment is FIXED at the first year: recomputing it from a later balance would make a supposedly fixed amortization payment vary
    • Single Life is the engine's stated convention among the three tables Notice 2022-6 permits, and it is the shortest at every age, so this sizes the largest payment any permitted table would allow rather than the smallest; no beneficiary-specific table election is claimed
    • The 5% rate is the module default and clears the statutory ceiling; a caller may pass a different permitted rate

    Provenance: derived by codex, implemented by claude.

    Independent review: orchestrator

    Gates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass

    Worksheet: sepp-amortization-method.md Mutation receipt: sepp-amortization-method.mutation.md

    Evidence tests: sepp.evidence.test.ts

    Implemented in: sepp.ts

    Is the number of: sepp-distribution-annual

  • SEPP RMD-method annual amount Composition record, justified by derivation

    Purpose: Recompute the annual 72(t) payment each year from the current balance and the Single Life divisor.

    Statement: strategies/sepp.ts#seppAnnualAmount computes the SEPP RMD-method annual payment as the current start-of-year balance divided by the Single Life Table entry for the attained age, recomputed every year. Because both the balance and the age are reread, the payment is not fixed. Units: nominal USD per year. Rounding: none.

    Formula: A = B / d, where d = singleLifeTable[floor(age)]

    • B: Current start-of-year balance (unit: usd) (domain: positive; a nonpositive balance pays 0)
    • d: Single Life Table divisor for the attained age (unit: years) (domain: positive)

    Timing: once per SEPP year

    Rounding: none

    Limits:

    • The Uniform Lifetime Table is not an alternative here: the published parameters carry no age-55 entry for it, and the module adopts Single Life for both supported methods
    • The published entry is taken as published; a fractional age is floored to the table's whole age rather than interpolated
    • Unlike the amortization method this payment varies year to year, so a test that holds it constant is asserting the wrong method

    Provenance: derived by codex, implemented by claude.

    Independent review: cursor

    Gates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass

    Worksheet: sepp-rmd-method.md Mutation receipt: sepp-rmd-method.mutation.md

    Evidence tests: sepp.evidence.test.ts

    Implemented in: sepp.ts

    Is the number of: sepp-distribution-annual

Records that feed this number

  • SEPP active in an attained-age year Model record, justified by derivation

    Purpose: Decide whether a 72(t) series is still running in a given attained-age year.

    Statement: strategies/sepp.ts#seppActive treats a SEPP as active in an attained-age year at or after the start age only while EITHER the age-60 boundary or the five-year duration is still unsatisfied, implementing the statutory "longer of five years or until 59.5" at annual granularity with age 60 as the engine's stated approximation of 59.5; projection/internal/annualSeppDistributions.ts#annualSeppDistributions consults it before distributing. Units: a boolean per owner-year. Rounding: none; whole attained ages.

    Formula: active(startAge, age) = age >= startAge and (age < 60 or age - startAge < 5)

    • startAge: Attained age at which the series began (unit: years) (domain: integer)
    • age: Attained age in the evaluated year (unit: years) (domain: integer)

    Timing: once per owner-year

    Rounding: none

    Limits:

    • Age 60 is an explicit annual approximation of 59.5: the annual model carries no half-year ages, so a series statute would end midyear ends at the year boundary here
    • Busting the series is not modeled: the engine assumes the schedule is honored and charges no retroactive penalties
    • The rule decides whether the series runs, not how much it pays; the two method records carry the amounts

    Provenance: derived by codex, implemented by claude.

    Independent review: cursor

    Gates (6 of 6 pass): fixture registers a test: pass; pins resolve: pass; families exist: pass; worksheet exists: pass; mutation receipt exists: pass; provenance independent: pass

    Worksheet: sepp-active-annual-rule.md Mutation receipt: sepp-active-annual-rule.mutation.md

    Evidence tests: sepp.evidence.test.ts

    Implemented in: sepp.ts; annualSeppDistributions.ts

    Feeds: sepp-distribution-annual

Engine source: engine/src/projection/internal/types/result.ts (YearResult.sepp)

The evidence links on this page (each record's worksheet, mutation receipt, evidence tests and implementation, and the source links) are pinned to engine commit 2624dbdba9fd, committed 2026-10-11. The live calculation index and output-family census links point at the repository's main branch, so you can check this snapshot against them.