Volume 2: Organizational Intelligence Platforms

Pattern 8: Tier-Based Segmentation

Intent

Organize entities into a small number of actionable tiers (typically 3-5) based on health scores and risk profiles, where each tier receives a distinct treatment strategy, communication cadence, and resource allocation level.

Also Known As

  • Customer Segmentation
  • Stratification Model
  • Tiering Strategy
  • Portfolio Segmentation
  • Health-Based Grouping

Problem

Scores alone don't tell you what to do.

Pattern 6 gives Sarah health scores: - Martinez family: 42/100 - Chen family: 87/100
- Rodriguez family: 68/100 - Thompson family: 31/100

Pattern 7 gives her risk profiles: - Martinez: High withdrawal risk, medium payment risk - Chen: Low all risks - Rodriguez: Medium everything - Thompson: High payment risk, high academic risk

But Sarah has 100 families. She can't create custom strategies for each.

She needs: "Which families get high-touch support? Which need urgent intervention? Which can be low-touch?"

Without tiers: - Treatment is either one-size-fits-all (inefficient) or ad-hoc (inconsistent) - Can't scale personalized attention - No clear prioritization framework - Hard to allocate resources - Difficult to measure tier-specific performance

The solution: Group similar families into tiers, each tier gets a strategy.

Context

When this pattern applies:

  • Managing many entities (50+) where personalization to each is impractical
  • Need to allocate scarce resources (time, money, attention)
  • Different entities require different treatment intensity
  • Want consistent, repeatable strategies
  • Building automated workflows that treat tiers differently

When this pattern may not be needed:

  • Very small scale (<20 entities) where individual attention is feasible
  • All entities truly need identical treatment
  • Resources are unlimited (rare!)
  • No clear differences in entity needs or value

Forces

Competing concerns:

1. Few Tiers vs Many Tiers - Fewer tiers = simpler, easier to manage - More tiers = finer-grained strategies, more personalization - Balance: 3-5 tiers for most use cases

2. Fixed Thresholds vs Dynamic - Fixed: Easy to understand, stable over time (score >80 = high tier) - Dynamic: Adapts to distribution (top 20% = high tier) - Balance: Start fixed, consider dynamic for mature systems

3. Single-Dimension vs Multi-Dimension - Single: Use overall health score only - Multi: Consider health + risk + value + tenure - Balance: Primary dimension (health) with overrides for special cases

4. Automatic vs Manual - Automatic: Consistent, scalable, no human bias - Manual: Can override for special circumstances - Balance: Auto-assign with manual override capability

5. Static vs Mobile - Static: Families stay in tier unless re-calculated - Mobile: Families move between tiers frequently - Balance: Periodic re-calculation (weekly/monthly) with real-time triggers for urgent moves

Solution

Define 3-5 tiers based on health scores and risk profiles, assign clear strategies to each tier, and implement both automated tier assignment and tier-specific workflows.

Common tier structures:

Tier 1: Champions (High) - 20-30% of families - Score: 80-100 - Risk: Low across dimensions - Strategy: Maintain, celebrate, leverage - Touch frequency: Low (quarterly) - Focus: Retention, advocacy, referrals

Tier 2: Stable (Medium-High) - 30-40% of families - Score: 60-79 - Risk: Low to moderate - Strategy: Standard engagement, monitor - Touch frequency: Medium (monthly) - Focus: Maintain satisfaction, prevent decline

Tier 3: Developing (Medium-Low) - 20-30% of families - Score: 40-59 - Risk: Moderate to high - Strategy: Increased attention, proactive support - Touch frequency: High (weekly) - Focus: Improvement, risk mitigation

Tier 4: Critical (At-Risk) - 10-20% of families - Score: 0-39 - Risk: High in one or more dimensions - Strategy: Intensive intervention, personal touch - Touch frequency: Very high (daily/as-needed) - Focus: Save relationship, immediate problems

Alternative: 3-Tier Model (Simpler)

High (60-100): Standard operations Medium (30-59): Enhanced support Low (<30): Crisis intervention

Alternative: 5-Tier Model (More Granular)

Platinum (90-100): VIP treatment Gold (75-89): Premium service Silver (50-74): Standard service Bronze (25-49): Intensive support Critical (<25): Emergency intervention

Structure

Tier Configuration Table

-- Define tier configurations
CREATE TABLE tier_definitions (
  tier_id INT PRIMARY KEY IDENTITY(1,1),
  tier_name VARCHAR(50) NOT NULL,
  tier_level INT NOT NULL,  -- 1 = highest, 4 = lowest

  -- Score thresholds
  min_score DECIMAL(5,2) NOT NULL,
  max_score DECIMAL(5,2) NOT NULL,

  -- Risk overrides
  force_if_high_risk BIT DEFAULT 0,  -- Force to this tier if high risk in any dimension

  -- Strategy parameters
  target_touch_frequency_days INT,  -- How often to engage
  requires_personal_touch BIT DEFAULT 0,
  auto_escalation_enabled BIT DEFAULT 0,

  -- Resource allocation
  staff_time_percentage DECIMAL(5,2),  -- % of coordinator time
  communication_budget_multiplier DECIMAL(4,2),  -- 1.0 = standard, 2.0 = double

  -- Description
  description NVARCHAR(500),
  strategy_summary NVARCHAR(1000),

  CONSTRAINT UQ_tier_name UNIQUE (tier_name),
  CONSTRAINT UQ_score_range UNIQUE (min_score, max_score)
);

-- Seed data: 4-tier model
INSERT INTO tier_definitions (tier_name, tier_level, min_score, max_score, force_if_high_risk, 
  target_touch_frequency_days, requires_personal_touch, staff_time_percentage, 
  communication_budget_multiplier, description, strategy_summary) VALUES

('Champions', 1, 80, 100, 0, 90, 0, 0.20, 0.8,
 'High engagement, low risk families who are thriving',
 'Maintain satisfaction, request referrals, celebrate success, minimal intervention'),

('Stable', 2, 60, 79, 0, 30, 0, 0.30, 1.0,
 'Solid engagement, moderate satisfaction, low risk',
 'Standard communications, monitor for changes, maintain current state'),

('Developing', 3, 40, 59, 0, 7, 1, 0.30, 1.3,
 'Declining engagement or emerging risks, needs attention',
 'Proactive outreach, address concerns, improve engagement, prevent further decline'),

('Critical', 4, 0, 39, 1, 1, 1, 0.20, 1.5,
 'High risk of churn, urgent problems, immediate intervention needed',
 'Personal meetings, intensive support, save relationship, address immediate issues');

-- Track tier assignments
CREATE TABLE family_tiers (
  assignment_id INT PRIMARY KEY IDENTITY(1,1),
  family_id INT NOT NULL,
  tier_id INT NOT NULL,

  -- Assignment metadata
  assigned_date DATETIME2 DEFAULT GETDATE(),
  assignment_method VARCHAR(50) DEFAULT 'automatic',  -- 'automatic' or 'manual'
  assigned_by VARCHAR(100),

  -- Previous tier (for tracking movements)
  previous_tier_id INT NULL,
  tier_change_reason NVARCHAR(500),

  -- Override flags
  is_manual_override BIT DEFAULT 0,
  override_reason NVARCHAR(500),
  override_expires DATETIME2 NULL,  -- If temporary override

  CONSTRAINT FK_tier_family FOREIGN KEY (family_id) 
    REFERENCES families(family_id),
  CONSTRAINT FK_tier_definition FOREIGN KEY (tier_id) 
    REFERENCES tier_definitions(tier_id),
  CONSTRAINT UQ_family_tier UNIQUE (family_id)
);

-- Indexes
CREATE INDEX IX_tier_assignment ON family_tiers(tier_id, assigned_date);
CREATE INDEX IX_tier_movement ON family_tiers(family_id, assigned_date);

-- Track tier movement history
CREATE TABLE tier_movement_history (
  movement_id INT PRIMARY KEY IDENTITY(1,1),
  family_id INT NOT NULL,

  from_tier_id INT,
  to_tier_id INT NOT NULL,
  movement_date DATETIME2 DEFAULT GETDATE(),

  -- Metrics at time of movement
  health_score_at_movement DECIMAL(5,2),
  highest_risk_dimension VARCHAR(50),

  -- Movement analysis
  movement_direction VARCHAR(20),  -- 'promotion', 'demotion', 'lateral'
  days_in_previous_tier INT,

  CONSTRAINT FK_movement_family FOREIGN KEY (family_id) 
    REFERENCES families(family_id)
);

CREATE INDEX IX_movement_date ON tier_movement_history(movement_date);
CREATE INDEX IX_movement_direction ON tier_movement_history(movement_direction);

Implementation

Tier Assignment Engine

class TierAssignmentEngine {
  constructor(db) {
    this.db = db;
    this.tierDefinitions = null;
  }

  async loadTierDefinitions() {
    this.tierDefinitions = await this.db.query(`
      SELECT * FROM tier_definitions ORDER BY tier_level ASC
    `);
  }

  async assignTier(familyId, options = {}) {
    const { manual = false, overrideReason = null, assignedBy = 'system' } = options;

    if (!this.tierDefinitions) {
      await this.loadTierDefinitions();
    }

    // Get family metrics
    const metrics = await this.db.query(`
      SELECT engagement_score FROM family_engagement_metrics WHERE family_id = ?
    `, [familyId]);

    const risks = await this.db.query(`
      SELECT 
        withdrawal_risk, payment_risk, academic_risk, disengagement_risk,
        highest_risk_dimension
      FROM risk_assessments WHERE family_id = ?
    `, [familyId]);

    if (!metrics[0]) {
      throw new Error(`No health metrics found for family ${familyId}`);
    }

    const score = metrics[0].engagement_score;
    const riskProfile = risks[0] || {};

    // Determine tier based on score
    let assignedTier = this.determineTierByScore(score);

    // Check for risk override (force to Critical tier if high risk)
    const hasHighRisk = Object.values(riskProfile).some(risk => 
      typeof risk === 'number' && risk > 75
    );

    if (hasHighRisk && !manual) {
      const criticalTier = this.tierDefinitions.find(t => t.force_if_high_risk);
      if (criticalTier) {
        assignedTier = criticalTier;
      }
    }

    // Get previous tier
    const previousAssignment = await this.db.query(`
      SELECT tier_id FROM family_tiers WHERE family_id = ?
    `, [familyId]);

    const previousTierId = previousAssignment[0]?.tier_id;
    const isChanged = !previousTierId || previousTierId !== assignedTier.tier_id;

    // Save assignment
    await this.saveTierAssignment(familyId, assignedTier.tier_id, {
      previousTierId,
      isManual: manual,
      overrideReason,
      assignedBy,
      score,
      highestRisk: riskProfile.highest_risk_dimension
    });

    // If tier changed, log movement
    if (isChanged && previousTierId) {
      await this.logTierMovement(familyId, previousTierId, assignedTier.tier_id, score, riskProfile);
    }

    return {
      familyId,
      tier: assignedTier.tier_name,
      tierId: assignedTier.tier_id,
      score: score,
      changed: isChanged,
      previousTier: previousTierId ? 
        this.tierDefinitions.find(t => t.tier_id === previousTierId)?.tier_name : null
    };
  }

  determineTierByScore(score) {
    // Find tier where score falls within min/max range
    const tier = this.tierDefinitions.find(t => 
      score >= t.min_score && score <= t.max_score
    );

    if (!tier) {
      // Fallback to lowest tier if no match (shouldn't happen with proper config)
      return this.tierDefinitions[this.tierDefinitions.length - 1];
    }

    return tier;
  }

  async saveTierAssignment(familyId, tierId, metadata) {
    const { previousTierId, isManual, overrideReason, assignedBy, score, highestRisk } = metadata;

    await this.db.query(`
      INSERT INTO family_tiers (
        family_id, tier_id, previous_tier_id, 
        assignment_method, assigned_by,
        is_manual_override, override_reason
      ) VALUES (?, ?, ?, ?, ?, ?, ?)
      ON CONFLICT (family_id) DO UPDATE SET
        tier_id = EXCLUDED.tier_id,
        previous_tier_id = family_tiers.tier_id,
        assigned_date = GETDATE(),
        assignment_method = EXCLUDED.assignment_method,
        assigned_by = EXCLUDED.assigned_by,
        is_manual_override = EXCLUDED.is_manual_override,
        override_reason = EXCLUDED.override_reason
    `, [
      familyId, tierId, previousTierId,
      isManual ? 'manual' : 'automatic',
      assignedBy,
      isManual ? 1 : 0,
      overrideReason
    ]);
  }

  async logTierMovement(familyId, fromTierId, toTierId, score, riskProfile) {
    // Determine movement direction
    const fromTier = this.tierDefinitions.find(t => t.tier_id === fromTierId);
    const toTier = this.tierDefinitions.find(t => t.tier_id === toTierId);

    const direction = toTier.tier_level < fromTier.tier_level ? 'promotion' :
                      toTier.tier_level > fromTier.tier_level ? 'demotion' : 'lateral';

    // Calculate days in previous tier
    const previousAssignment = await this.db.query(`
      SELECT assigned_date FROM family_tiers WHERE family_id = ?
    `, [familyId]);

    const daysInTier = previousAssignment[0] ? 
      Math.floor((Date.now() - new Date(previousAssignment[0].assigned_date)) / (1000 * 60 * 60 * 24)) : 0;

    await this.db.query(`
      INSERT INTO tier_movement_history (
        family_id, from_tier_id, to_tier_id,
        health_score_at_movement, highest_risk_dimension,
        movement_direction, days_in_previous_tier
      ) VALUES (?, ?, ?, ?, ?, ?, ?)
    `, [
      familyId, fromTierId, toTierId,
      score, riskProfile.highest_risk_dimension,
      direction, daysInTier
    ]);
  }

  async assignAllFamilies() {
    const families = await this.db.query(`
      SELECT family_id FROM families WHERE enrolled_current_semester = 1
    `);

    const results = {
      total: families.length,
      assigned: 0,
      changed: 0,
      errors: []
    };

    for (const family of families) {
      try {
        const result = await this.assignTier(family.family_id);
        results.assigned++;
        if (result.changed) results.changed++;
      } catch (error) {
        results.errors.push({
          familyId: family.family_id,
          error: error.message
        });
      }
    }

    return results;
  }

  async getTierDistribution() {
    return await this.db.query(`
      SELECT 
        td.tier_name,
        td.tier_level,
        COUNT(ft.family_id) as family_count,
        COUNT(ft.family_id) * 100.0 / (SELECT COUNT(*) FROM family_tiers) as percentage,
        AVG(fem.engagement_score) as avg_health_score,
        td.target_touch_frequency_days,
        td.staff_time_percentage
      FROM tier_definitions td
      LEFT JOIN family_tiers ft ON td.tier_id = ft.tier_id
      LEFT JOIN family_engagement_metrics fem ON ft.family_id = fem.family_id
      GROUP BY td.tier_id, td.tier_name, td.tier_level, 
               td.target_touch_frequency_days, td.staff_time_percentage
      ORDER BY td.tier_level ASC
    `);
  }

  async getTierMovementAnalysis(days = 30) {
    return await this.db.query(`
      SELECT 
        movement_direction,
        td_from.tier_name as from_tier,
        td_to.tier_name as to_tier,
        COUNT(*) as movement_count,
        AVG(days_in_previous_tier) as avg_days_before_movement
      FROM tier_movement_history tmh
      JOIN tier_definitions td_from ON tmh.from_tier_id = td_from.tier_id
      JOIN tier_definitions td_to ON tmh.to_tier_id = td_to.tier_id
      WHERE tmh.movement_date >= DATE_SUB(NOW(), INTERVAL ? DAY)
      GROUP BY movement_direction, td_from.tier_name, td_to.tier_name
      ORDER BY movement_count DESC
    `, [days]);
  }
}

module.exports = TierAssignmentEngine;

Tier-Specific Strategies

class TierStrategyExecutor {
  constructor(db, tierEngine) {
    this.db = db;
    this.tierEngine = tierEngine;
  }

  async executeTierStrategy(tierId) {
    const tier = await this.db.query(`
      SELECT * FROM tier_definitions WHERE tier_id = ?
    `, [tierId]);

    if (!tier[0]) {
      throw new Error(`Tier ${tierId} not found`);
    }

    const t = tier[0];

    // Different strategy per tier
    switch (t.tier_name) {
      case 'Champions':
        return await this.executeChampionsStrategy(t);
      case 'Stable':
        return await this.executeStableStrategy(t);
      case 'Developing':
        return await this.executeDevelopingStrategy(t);
      case 'Critical':
        return await this.executeCriticalStrategy(t);
      default:
        console.warn(`Unknown tier: ${t.tier_name}`);
    }
  }

  async executeChampionsStrategy(tier) {
    // Champions: Low touch, request referrals, celebrate
    const families = await this.getFamiliesInTier(tier.tier_id);

    const actions = [];
    for (const family of families) {
      // Send quarterly update
      if (await this.shouldContact(family.family_id, tier.target_touch_frequency_days)) {
        actions.push({
          type: 'send_appreciation_email',
          familyId: family.family_id,
          template: 'champion_appreciation'
        });

        // Request referral
        actions.push({
          type: 'request_referral',
          familyId: family.family_id
        });
      }
    }

    return actions;
  }

  async executeStableStrategy(tier) {
    // Stable: Standard communications, monitor
    const families = await this.getFamiliesInTier(tier.tier_id);

    const actions = [];
    for (const family of families) {
      if (await this.shouldContact(family.family_id, tier.target_touch_frequency_days)) {
        actions.push({
          type: 'send_standard_update',
          familyId: family.family_id,
          template: 'monthly_newsletter'
        });
      }
    }

    return actions;
  }

  async executeDevelopingStrategy(tier) {
    // Developing: Proactive outreach, address concerns
    const families = await this.getFamiliesInTier(tier.tier_id);

    const actions = [];
    for (const family of families) {
      // More frequent check-ins
      if (await this.shouldContact(family.family_id, tier.target_touch_frequency_days)) {
        // Identify specific risk
        const risks = await this.db.query(`
          SELECT 
            withdrawal_risk, payment_risk, academic_risk, disengagement_risk,
            highest_risk_dimension
          FROM risk_assessments WHERE family_id = ?
        `, [family.family_id]);

        const highestRisk = risks[0]?.highest_risk_dimension;

        // Targeted action based on risk
        if (highestRisk === 'payment') {
          actions.push({
            type: 'send_payment_support_email',
            familyId: family.family_id,
            template: 'payment_assistance_offer'
          });
        } else if (highestRisk === 'withdrawal') {
          actions.push({
            type: 'schedule_check_in_call',
            familyId: family.family_id
          });
        } else if (highestRisk === 'disengagement') {
          actions.push({
            type: 'send_re_engagement_campaign',
            familyId: family.family_id
          });
        }
      }
    }

    return actions;
  }

  async executeCriticalStrategy(tier) {
    // Critical: Intensive intervention, personal touch
    const families = await this.getFamiliesInTier(tier.tier_id);

    const actions = [];
    for (const family of families) {
      // Daily monitoring, immediate personal contact
      actions.push({
        type: 'create_intervention_task',
        familyId: family.family_id,
        priority: 'urgent',
        assignTo: 'coordinator',
        description: 'Critical tier family requires immediate personal contact'
      });

      // Assess situation
      const risks = await this.db.query(`
        SELECT * FROM risk_assessments WHERE family_id = ?
      `, [family.family_id]);

      const r = risks[0];

      // Multiple high risks = emergency meeting
      const highRisks = [
        r.withdrawal_risk > 70,
        r.payment_risk > 70,
        r.academic_risk > 70
      ].filter(Boolean).length;

      if (highRisks >= 2) {
        actions.push({
          type: 'schedule_emergency_meeting',
          familyId: family.family_id,
          within_hours: 24
        });
      }
    }

    return actions;
  }

  async getFamiliesInTier(tierId) {
    return await this.db.query(`
      SELECT 
        f.family_id,
        f.family_name,
        ft.assigned_date
      FROM family_tiers ft
      JOIN families f ON ft.family_id = f.family_id
      WHERE ft.tier_id = ?
        AND f.enrolled_current_semester = 1
    `, [tierId]);
  }

  async shouldContact(familyId, frequencyDays) {
    // Check last contact
    const lastContact = await this.db.query(`
      SELECT MAX(interaction_timestamp) as last_contact
      FROM interaction_log
      WHERE family_id = ?
        AND interaction_type IN ('email_sent', 'sms_sent', 'phone_call_made')
    `, [familyId]);

    if (!lastContact[0]?.last_contact) return true;

    const daysSinceContact = Math.floor(
      (Date.now() - new Date(lastContact[0].last_contact)) / (1000 * 60 * 60 * 24)
    );

    return daysSinceContact >= frequencyDays;
  }
}

Variations

By Tier Count

3 Tiers (Simple): - High, Medium, Low - Good for: Small organizations, simple strategies

4 Tiers (Recommended): - Champions, Stable, Developing, Critical - Good for: Most organizations

5 Tiers (Granular): - Platinum, Gold, Silver, Bronze, Critical - Good for: Large organizations, premium pricing models

By Assignment Logic

Score-Based (Simple):

if (score >= 80) tier = 'Champions';
else if (score >= 60) tier = 'Stable';
else if (score >= 40) tier = 'Developing';
else tier = 'Critical';

Score + Risk (Better):

let tier = determineTierByScore(score);
if (hasHighRisk) tier = 'Critical';  // Override

Multi-Factor (Advanced):

// Consider score, risk, tenure, value, potential
const tierScore = (
  healthScore * 0.4 +
  (100 - maxRisk) * 0.3 +
  tenureBonus * 0.2 +
  lifetimeValue * 0.1
);
tier = determineTierByComposite(tierScore);

By Domain

Homeschool Co-op: - Champions: Thriving families, volunteers, referrers - Stable: Engaged, paying on time - Developing: Declining engagement - Critical: High withdrawal/payment risk

SaaS: - Power Users: High usage, advocates - Standard Users: Regular usage, paying - Casual Users: Low usage, churn risk - At-Risk: Not logging in, payment issues

Property Management: - Platinum Tenants: Long-term, no issues - Good Tenants: On-time rent, low maintenance - Problem Tenants: Late rent, complaints - Eviction Track: Multiple violations

Consequences

Benefits

1. Scalable personalization 100 families organized into 4 groups = manageable strategies

2. Resource optimization Champions need 20% of time, Critical need 20% of time, but very different treatment

3. Clear prioritization Critical tier = urgent, Champions = low priority

4. Measurable tier performance "Developing tier retention: 78% vs 65% last semester"

5. Automated workflows Tier assignment triggers appropriate communication sequence

6. Team alignment Everyone knows what "Critical tier" means and how to respond

Costs

1. Oversimplification 4 tiers can't capture all nuance - some families don't fit cleanly

2. Threshold sensitivity Score of 59 vs 60 = different tier, but is difference real?

3. Gaming potential Families learn tier thresholds, might game system

4. Stigma risk "Critical tier" could feel stigmatizing if communicated poorly

5. Configuration burden Must define strategies for each tier, keep updated

Sample Code

Dashboard - tier overview:

async function getTierDashboard() {
  const distribution = await tierEngine.getTierDistribution();
  const movements = await tierEngine.getTierMovementAnalysis(30);

  console.log('=== TIER DISTRIBUTION ===');
  distribution.forEach(tier => {
    console.log(`
${tier.tier_name}:
  Families: ${tier.family_count} (${tier.percentage.toFixed(1)}%)
  Avg Health: ${tier.avg_health_score?.toFixed(1) || 'N/A'}
  Touch Frequency: Every ${tier.target_touch_frequency_days} days
  Staff Time: ${tier.staff_time_percentage}%
    `);
  });

  console.log('\n=== TIER MOVEMENTS (Last 30 Days) ===');
  movements.forEach(m => {
    console.log(`${m.from_tier} → ${m.to_tier} (${m.movement_direction}): ${m.movement_count} families`);
  });
}

Known Uses

Homeschool Co-Op Intelligence Platform - 4-tier model implemented - Distribution: Champions 28%, Stable 42%, Developing 21%, Critical 9% - Tier-specific retention: Champions 98%, Stable 89%, Developing 72%, Critical 43% - Time allocation: Champions 15%, Stable 30%, Developing 35%, Critical 20%

SaaS Customer Success - Gainsight, ChurnZero: Tier-based playbooks - Different CSM coverage by tier - Automated workflows per tier

Financial Services - Wealth management: Platinum/Gold/Silver client tiers - Different advisor ratios per tier - Tier-specific service levels

Requires: - Pattern 6: Composite Health Scoring - score determines tier - Pattern 7: Multi-Dimensional Risk Assessment - risk can override tier

Enables: - Pattern 21: Automated Workflow Execution - schedule frequency per tier - Pattern 22: Progressive Escalation Sequences - escalation path per tier - Pattern 24: Template-Based Communication - templates per tier

Enhanced by: - Pattern 9: Early Warning Signals - alert on unexpected tier movement - Pattern 10: Engagement Velocity Tracking - predict tier movement

References

Academic Foundations

  • Mehta, Nick, et al. (2016). Customer Success. Wiley. ISBN: 978-1119167969 - Segmentation strategies for customer success
  • Kotler, Philip, and Kevin Lane Keller (2015). Marketing Management (15th ed.). Pearson. ISBN: 978-0133856460 - Market segmentation theory
  • Wedel, Michel, and Wagner A. Kamakura (2000). Market Segmentation: Conceptual and Methodological Foundations (2nd ed.). Springer. ISBN: 978-0792386353
  • RFM Analysis: Hughes, A.M. (1994). "Strategic Database Marketing." - Recency, Frequency, Monetary segmentation

SaaS Customer Success

Healthcare Stratification

Practical Implementation

  • Pattern 6: Composite Health Scoring - Health score determines tier
  • Pattern 7: Multi-Dimensional Risk - Risk level influences tier placement
  • Pattern 15: Intervention Recommendation Engine - Tier-appropriate interventions
  • Pattern 23: Triggered Interventions - Different triggers per tier
  • Volume 3, Pattern 3: Conversational Rhythm - Tier-appropriate communication frequency

Tools & Services