Skip to main content

Overview

Step 5 applies the plan’s vesting schedule to determine what portion of each participant’s account is vested (owned by the employee) versus unvested (subject to forfeiture if they terminate).
Vesting is a critical employee retention mechanism that gradually transfers ownership of ESOP shares to participants based on years of service.

Core Responsibilities

Vesting Calculation

Apply vesting schedule based on service years

Forfeiture Identification

Calculate non-vested amounts subject to forfeiture

Multi-Class Support

Track vesting per security in multi-class mode

Cash Vesting

Apply vesting to both shares and cash balances

How Vesting Works

Vesting Schedule Types

Ownership increases gradually over time:
vesting_schedule = {
    1: 0.20,  # 20% after 1 year
    2: 0.40,  # 40% after 2 years
    3: 0.60,  # 60% after 3 years
    4: 0.80,  # 80% after 4 years
    5: 1.00   # 100% after 5 years
}
Example:
  • Employee has 1,000 allocated shares
  • Service years: 3.5 years
  • Vesting: 60% (based on 3 years, rounded down)
  • Vested: 1,000 × 0.60 = 600 shares
  • Unvested: 1,000 × 0.40 = 400 shares (potential forfeiture)

Processing Logic

Single-Class Mode

for employee in active_employees:
    # 1. Determine vesting percentage
    service_years_int = int(employee.service_years)  # Round down: 3.9 → 3
    
    if service_years_int in vesting_schedule:
        vesting_pct = vesting_schedule[service_years_int]
    else:
        # If beyond max schedule year, assume 100% vested
        max_year = max(vesting_schedule.keys())
        vesting_pct = 1.0 if service_years_int > max_year else 0.0
    
    # 2. Calculate total balances
    total_shares = (
        employee.opening_shares +        # Beginning balance
        employee.allocated_shares -      # This year's allocation
        employee.diversified_shares      # Minus diversification
    )
    
    total_cash = (
        employee.opening_cash +
        employee.allocated_cash -
        employee.diversified_cash
    )
    
    # 3. Apply vesting
    employee.vested_shares = total_shares * vesting_pct
    employee.vested_cash = total_cash * vesting_pct
    
    # 4. Calculate potential forfeitures (if terminated)
    employee.potential_forfeitures = total_shares * (1 - vesting_pct)
    employee.potential_forfeitures_cash = total_cash * (1 - vesting_pct)

Multi-Class Mode

Vesting is applied per security:
for employee in active_employees:
    # Determine vesting %
    vesting_pct = get_vesting_percentage(employee.service_years)
    
    total_vested_shares = 0
    total_potential_forfeitures = 0
    
    # Apply to each security holding
    for security_id, holding in employee.holdings.items():
        # Total shares in this security
        shares_in_security = holding.shares
        
        # Vested amount
        vested_in_security = shares_in_security * vesting_pct
        total_vested_shares += vested_in_security
        
        # Potential forfeitures
        forfeitures_in_security = shares_in_security * (1 - vesting_pct)
        total_potential_forfeitures += forfeitures_in_security
    
    # Set aggregate amounts
    employee.vested_shares = total_vested_shares
    employee.potential_forfeitures = total_potential_forfeitures
    
    # Cash vesting (aggregate, not per-security)
    total_cash = employee.opening_cash + employee.allocated_cash - employee.diversified_cash
    employee.vested_cash = total_cash * vesting_pct
    employee.potential_forfeitures_cash = total_cash * (1 - vesting_pct)

Vesting Examples

Scenario:
  • Service years: 5.2 years
  • Vesting schedule: 100% at year 5
  • Allocated shares: 1,000
  • Opening shares: 4,000
  • Total: 5,000 shares
Calculation:
  • Vesting %: 100%
  • Vested shares: 5,000 × 1.0 = 5,000 shares
  • Potential forfeitures: 5,000 × 0.0 = 0 shares
✅ Employee owns entire account

Cash Vesting

New in v0.2: Cash balances are vested using the same schedule as shares.
Participants may have cash from:
  • Company cash contributions
  • Diversification elections (converted from stock to cash)
  • Dividends or interest
  • Opening cash balances
Cash vesting mirrors share vesting:
total_cash = opening_cash + allocated_cash - diversified_cash
vested_cash = total_cash * vesting_percentage
potential_forfeitures_cash = total_cash * (1 - vesting_percentage)
Example:
  • Employee has $10,000 cash in account
  • Service: 2 years → 40% vested
  • Vested cash: 10,000×0.40=10,000 × 0.40 = 4,000
  • Potential forfeiture: 10,000×0.60=10,000 × 0.60 = 6,000

Potential Forfeitures

“Potential forfeitures” are NOT actual forfeitures yet. They become actual forfeitures only if the employee terminates before becoming fully vested.

When Forfeitures Occur

Forfeitures are realized in Step 7 when:
  1. Employee terminates
  2. Employee has potential_forfeitures > 0
  3. Forfeiture policy is applied
The Flow:
  • Step 5: Calculate potential_forfeitures
  • Step 7: If terminated → convert to forfeited_shares
  • Step 2 (next year): Reallocate forfeited shares

Forfeiture vs. Vested

MetricVestedUnvested (Potential Forfeiture)
OwnershipEmployee ownsCompany owns
If terminatedEmployee keepsCompany reclaims
If continuesStays with employeeMay vest later
DistributionMust be distributedNever distributed

Service Year Rounding

Service years are rounded down (floor) to determine vesting schedule lookup.
Examples:
  • 1.0 years → Lookup year 1
  • 1.9 years → Lookup year 1 (not 2!)
  • 2.0 years → Lookup year 2
  • 2.999 years → Lookup year 2
  • 5.1 years → Lookup year 5
service_years_int = int(employee.service_years)  # Floor function
vesting_pct = vesting_schedule.get(service_years_int, default)
This protects the company from prematurely vesting employees who haven’t yet completed a full service year.

Data Flow

Inputs

{
  "vesting_schedule": {
    1: 0.20,
    2: 0.40,
    3: 0.60,
    4: 0.80,
    5: 1.00
  }
}

Outputs

{
  "vested_shares": 1200.0,             # 60% of 2,000
  "vested_cash": 3000.0,               # 60% of 5,000
  "potential_forfeitures": 800.0,      # 40% of 2,000
  "potential_forfeitures_cash": 2000.0 # 40% of 5,000
}

Edge Cases

If employee service exceeds the max year in vesting schedule:
max_year = max(vesting_schedule.keys())  # e.g., 5
if service_years_int > max_year:
    vesting_pct = 1.0  # Assume 100% vested
Example:
  • Schedule ends at year 5
  • Employee has 12 years service
  • Vesting: 100% (fully vested)
If employee service is less than first schedule year:
if service_years_int < min(vesting_schedule.keys()):
    vesting_pct = 0.0  # Not yet vested
Example:
  • Schedule starts at year 1
  • Employee has 0.5 years service
  • Vesting: 0% (not vested)
In rare cases, diversification or corrections might cause negative balance:
total_shares = max(0, opening + allocated - diversified)
Prevents negative vesting calculations.
Shares allocated this year are immediately subject to vesting:
  • Allocated in Step 3: 500 shares
  • Vesting in Step 5: 40%
  • Vested: 500 × 0.40 = 200 shares
  • Unvested: 500 × 0.60 = 300 shares
New allocations don’t get special treatment—same vesting % applies.

Compliance Events

Legacy compliance log format:
{
  "year": 2025,
  "phase": "vesting",
  "event": "vesting_updated",
  "entity_type": "employee",
  "entity_id": "EMP042",
  "details": {
    "vest_pct": 0.80,
    "vested_shares": 4800.0,
    "vested_cash": 12000.0,
    "potential_forfeitures": 1200.0,
    "potential_forfeitures_cash": 3000.0
  }
}


Vesting Strategy Considerations

Advantages:
  • Gradual ownership transfer
  • Reduces forfeiture shock
  • Better retention over time
  • Employees see progress annually
Disadvantages:
  • More complex to administer
  • Partial forfeitures common
Advantages:
  • Simpler to administer
  • Strong retention at cliff point
  • Clear ownership threshold
Disadvantages:
  • “All or nothing” can be demotivating
  • High forfeiture if employees leave before cliff
  • May violate DOL regulations if cliff > 3 years for ESOPs
Some plans include accelerated vesting for:
  • Death
  • Disability
  • Retirement (age 65)
  • Plan termination
  • Change of control
These triggers can override the normal vesting schedule and grant immediate 100% vesting.

Summary

Step 5 is the vesting calculator that:
  • ✅ Applies vesting schedule based on service years
  • ✅ Calculates vested shares and cash balances
  • ✅ Identifies potential forfeitures (unvested amounts)
  • ✅ Supports multi-class securities with per-security tracking
  • ✅ Handles edge cases (service beyond schedule, negative balances)
  • ✅ Emits compliance events for audit trail
Key Insight: Vesting is a powerful retention tool. Employees who leave before fully vested forfeit unvested amounts, which are then reallocated to remaining participants—creating an incentive to stay with the company.
Vesting calculations in Step 5 are forward-looking estimates. Actual forfeitures only occur in Step 7 if the employee terminates.