Build vs Buy: When Schools Should Use Existing AI Tools vs Build an Internal Story Generator

Deciding between buying an existing AI storybook SaaS platform versus building internal custom solution is one of the most consequential technology decisions K-12 schools and districts face. A robust decision framework combines total cost of ownership analysis, capability gap assessment, technical resource evaluation, and long-term strategic alignment to determine optimal path. This is essential whether you’re a district IT director evaluating EdTech procurement, curriculum coordinator planning literacy initiatives, or technology committee weighing 5-year investment decisions where wrong choice costs $50,000-500,000 in wasted resources.

Key takeaways

A robust build vs buy framework blends financial modeling, capability analysis, resource assessment, and strategic alignment.

Build vs buy impacts long-term costs, feature velocity, and organizational capability beyond initial price tag.

Multi-factor decision matrices ensure AI API costs, maintenance burden, customization needs, and opportunity costs all weigh appropriately.

Total cost of ownership (TCO), time-to-value, and vendor lock-in risk matter as much as upfront licensing fees.

Musketeers Tech helps schools navigate build vs buy decisions with unbiased analysis, custom development when justified, and SaaS integration when appropriate, ensuring optimal resource allocation for literacy technology investments.

Why simple price comparison fails build vs buy decisions

Sticker-price thinking is the problem. Most school districts compare SaaS subscription cost ($500-5,000/year) against custom development estimate ($30,000-80,000) and conclude “buy is cheaper.” This works for simple tools but fails for strategic systems because hidden costs dominate TCO, maintenance consumes 40-60% of development budget annually, customization limitations surface after deployment, and opportunity costs of missed features compound yearly. Without comprehensive analysis, 60-80% of build vs buy decisions optimize wrong variables.

Pure price comparison is simple but, without TCO and strategic fit analysis, it produces decisions that cost more long-term and deliver less value.

What comprehensive build vs buy analysis actually means

Build vs buy decision frameworks combine multiple evaluation dimensions beyond initial pricing:

Total cost of ownership including development, maintenance, infrastructure, opportunity costs, and strategic value.

Capability gap assessment comparing SaaS feature sets against specific institutional requirements.

Resource evaluation determining whether internal team can build, maintain, and evolve solution successfully.

These are integrated into a decision matrix so technology investments align with organizational capacity, budget constraints, and strategic literacy goals.

Core components of build vs buy decision framework

1. Total cost of ownership (TCO) modeling

Calculates complete 5-year cost for both build and buy scenarios.

Includes development, licensing, maintenance, infrastructure, training, and opportunity costs.

Accounts for hidden costs like integration complexity and vendor switching expenses.

2. Capability and customization analysis

Evaluates whether existing SaaS platforms meet 80%+ of requirements.

Identifies must-have custom features justifying build decision.

Assesses competitive differentiation value from custom capabilities.

3. Technical resource and timeline assessment

Determines whether internal team possesses skills to build and maintain.

Calculates realistic development timeline accounting for school constraints.

Evaluates opportunity cost of diverting IT resources from other priorities.

How build vs buy analysis improves resource allocation

1. Better budget planning and cost predictability together

TCO analysis surfaces hidden maintenance and scaling costs upfront.

Multi-year modeling refines budget allocation preventing mid-project funding crises.

Combined, they enable accurate financial planning protecting against cost overruns.

2. Handling unique requirements and standard features efficiently

Custom development shines on specialized workflows standard SaaS can’t support.

SaaS platforms shine on commodity features every school needs (user management, reporting).

Hybrid approaches let your district buy core platform, customize critical differentiators.

3. More robust risk management and vendor dependency

Build path gets full control but accepts maintenance burden and talent retention risk.

Buy path gets faster deployment but accepts vendor lock-in and feature prioritization risk.

This trade-off analysis surfaces which risks your organization can tolerate better.

Total cost of ownership analysis

If you are making strategic technology decisions, TCO determines financial viability over 5-year planning horizon.

SaaS subscription cost modeling

Existing AI storybook platforms charge per-user or per-school with tiered pricing.

Typical SaaS pricing structure:

SAAS_PRICING_EXAMPLES = {
    'basic_platform': {
        'tier': 'School Site License',
        'annual_cost': 2000,
        'included_teachers': 25,
        'included_students': 750,
        'books_per_month': 500,
        'features': [
            'Standard templates',
            'Basic reading levels',
            'Parent sharing',
            'Usage reports'
        ]
    },
    
    'premium_platform': {
        'tier': 'District License',
        'annual_cost_per_school': 3500,
        'unlimited_teachers': True,
        'unlimited_students': True,
        'unlimited_books': True,
        'features': [
            'Custom templates',
            'Advanced curriculum alignment',
            'SSO integration',
            'API access',
            'Dedicated support',
            'Custom branding'
        ]
    }
}

def calculate_saas_tco(
    schools: int,
    teachers_per_school: int,
    years: int = 5
):
    """Calculate 5-year TCO for SaaS platform."""
    
    # Base subscription cost
    if schools <= 3:
        # Small district: per-school pricing
        annual_subscription = schools * 2000
    elif schools <= 10:
        # Medium district: volume discount
        annual_subscription = schools * 1500
    else:
        # Large district: enterprise pricing
        annual_subscription = schools * 1200
    
    # Implementation and training (one-time)
    implementation_cost = 5000 + (schools * 500)  # Setup + per-school training
    
    # Annual support and integration
    annual_integration = 2000  # SIS integration, SSO maintenance
    annual_training = schools * 200  # Teacher PD each year
    
    # Calculate 5-year total
    year_1 = implementation_cost + annual_subscription + annual_integration + annual_training
    years_2_5 = (annual_subscription + annual_integration + annual_training) * (years - 1)
    
    total_tco = year_1 + years_2_5
    
    return {
        'implementation': implementation_cost,
        'annual_subscription': annual_subscription,
        'annual_recurring': annual_integration + annual_training,
        'year_1_cost': year_1,
        'year_2_5_cost': years_2_5,
        'total_5_year_tco': total_tco,
        'average_annual_cost': total_tco / years
    }

# Example: 5-school district
saas_tco = calculate_saas_tco(schools=5, teachers_per_school=15, years=5)
"""
Results:
- Implementation: $7,500 (one-time)
- Annual subscription: $7,500
- Annual recurring: $3,000 (integration + training)
- Year 1: $18,000
- Years 2-5: $42,000
- Total 5-year TCO: $60,000
- Average annual: $12,000/year
"""

Custom development cost modeling

Building internal solution requires development, infrastructure, and ongoing maintenance.

Custom development TCO:

def calculate_custom_build_tco(
    development_hours: int,
    developer_rate: int,
    years: int = 5,
    team_size: int = 1
):
    """Calculate 5-year TCO for custom-built solution."""
    
    # Initial development cost
    initial_development = development_hours * developer_rate
    
    # Infrastructure costs
    infrastructure_monthly = {
        'hosting': 150,  # AWS/GCP compute, storage
        'databases': 100,  # PostgreSQL, Redis
        'apis': 200,  # OpenAI, DALL-E API costs
        'cdn': 50,  # CloudFront/Cloudflare
        'monitoring': 50,  # DataDog, Sentry
        'backups': 30  # Automated backups
    }
    annual_infrastructure = sum(infrastructure_monthly.values()) * 12
    
    # Maintenance and enhancement (40% of dev cost annually)
    annual_maintenance_hours = development_hours * 0.4
    annual_maintenance = annual_maintenance_hours * developer_rate
    
    # Security and compliance
    annual_security = {
        'ssl_certificates': 200,
        'security_audits': 2000,
        'penetration_testing': 3000,
        'compliance_review': 1500
    }
    annual_security_total = sum(annual_security.values())
    
    # Training and documentation
    initial_documentation = 40 * developer_rate  # 40 hours
    annual_training = 2000  # Teacher training materials
    
    # Calculate 5-year total
    year_1 = (
        initial_development + 
        initial_documentation +
        annual_infrastructure + 
        annual_maintenance + 
        annual_security_total +
        annual_training
    )
    
    years_2_5 = (
        annual_infrastructure + 
        annual_maintenance + 
        annual_security_total +
        annual_training
    ) * (years - 1)
    
    total_tco = year_1 + years_2_5
    
    return {
        'initial_development': initial_development,
        'initial_documentation': initial_documentation,
        'annual_infrastructure': annual_infrastructure,
        'annual_maintenance': annual_maintenance,
        'annual_security': annual_security_total,
        'year_1_cost': year_1,
        'year_2_5_cost': years_2_5,
        'total_5_year_tco': total_tco,
        'average_annual_cost': total_tco / years,
        'breakeven_year': None  # Calculate separately
    }

# Example: Medium complexity build
# 600 hours development at $150/hr (contract developer)
custom_tco = calculate_custom_build_tco(
    development_hours=600,
    developer_rate=150,
    years=5
)
"""
Results:
- Initial development: $90,000
- Documentation: $6,000
- Annual infrastructure: $7,080
- Annual maintenance: $36,000 (40% of dev cost)
- Annual security: $6,700
- Year 1: $145,780
- Years 2-5: $199,120
- Total 5-year TCO: $344,900
- Average annual: $68,980/year

Comparison to SaaS ($60,000 over 5 years):
- Custom solution costs 5.7x more
- Never reaches breakeven
"""

Hidden costs and opportunity costs

Beyond direct expenses, both paths include often-overlooked costs.

Hidden cost categories:

HIDDEN_COSTS = {
    'saas_platform': {
        'vendor_switching': {
            'cost': 15000,  # If switching vendors in year 3-4
            'probability': 0.2,
            'description': 'Data export, new training, transition disruption'
        },
        'feature_limitations': {
            'annual_impact': 3000,
            'description': 'Workarounds for missing features, manual processes'
        },
        'integration_complexity': {
            'annual_cost': 2000,
            'description': 'Maintaining SIS sync, SSO updates, API changes'
        }
    },
    
    'custom_build': {
        'talent_retention': {
            'risk_cost': 50000,  # If key developer leaves
            'probability': 0.3,
            'description': 'Knowledge loss, re-training, project delays'
        },
        'technology_obsolescence': {
            'year_3_cost': 25000,
            'description': 'Major refactor needed as AI models evolve'
        },
        'opportunity_cost': {
            'annual_impact': 20000,
            'description': 'IT resources diverted from other strategic projects'
        },
        'feature_velocity': {
            'annual_gap': 5000,
            'description': 'Missed features competitors launch faster'
        }
    }
}

def calculate_risk_adjusted_tco(base_tco: dict, scenario: str):
    """Add hidden costs and risk adjustments to base TCO."""
    
    hidden = HIDDEN_COSTS[scenario]
    total_hidden = 0
    
    for cost_category, details in hidden.items():
        if 'annual_impact' in details:
            total_hidden += details['annual_impact'] * 5
        elif 'annual_cost' in details:
            total_hidden += details['annual_cost'] * 5
        elif 'risk_cost' in details:
            expected_cost = details['risk_cost'] * details['probability']
            total_hidden += expected_cost
        elif 'year_3_cost' in details:
            total_hidden += details['year_3_cost']
    
    risk_adjusted_tco = base_tco['total_5_year_tco'] + total_hidden
    
    return {
        **base_tco,
        'hidden_costs': total_hidden,
        'risk_adjusted_tco': risk_adjusted_tco,
        'risk_adjusted_annual': risk_adjusted_tco / 5
    }

# Risk-adjusted comparison
saas_adjusted = calculate_risk_adjusted_tco(saas_tco, 'saas_platform')
custom_adjusted = calculate_risk_adjusted_tco(custom_tco, 'custom_build')

"""
Risk-adjusted 5-year TCO:
SaaS: $60,000 + $28,000 = $88,000 ($17,600/year)
Custom: $344,900 + $90,000 = $434,900 ($86,980/year)

Custom solution costs 4.9x more when accounting for hidden costs
"""

Total TCO analysis time: 6-8 hours including scenario modeling and sensitivity analysis.

Risk factor: MEDIUM. Cost estimates vary widely based on requirements; validate assumptions with quotes.

Capability gap assessment

If you need specialized features, capability analysis determines whether SaaS meets requirements.

Standard features every platform should provide

Core literacy tool capabilities available in most existing SaaS platforms.

Standard SaaS capabilities:

If your requirements consist primarily of these standard features, buying existing platform is almost always optimal choice.

Custom requirements justifying build path

Specific scenarios where custom development may provide value.

Build-justifying requirements:

BUILD_JUSTIFICATION_CRITERIA = {
    'district_specific_curriculum': {
        'description': 'Deep integration with proprietary curriculum framework',
        'example': 'Stories must align with district-developed phonics scope/sequence',
        'saas_alternative': 'Most platforms offer curriculum tags, may not be sufficient',
        'build_value': 'HIGH - if curriculum is truly unique and strategic differentiator'
    },
    
    'advanced_data_integration': {
        'description': 'Real-time sync with legacy student information system',
        'example': 'Auto-create accounts from SIS, sync reading scores to gradebook',
        'saas_alternative': 'Premium SaaS platforms offer SIS integration via Clever/ClassLink',
        'build_value': 'LOW - standard integrations usually sufficient'
    },
    
    'specialized_assessment': {
        'description': 'Custom assessment algorithms beyond standard metrics',
        'example': 'AI-powered fluency analysis with district-specific benchmarks',
        'saas_alternative': 'Most platforms offer basic progress tracking',
        'build_value': 'MEDIUM - depends on research validity and assessment innovation'
    },
    
    'multilingual_support': {
        'description': 'Support for less-common languages or dialects',
        'example': 'Generate stories in Navajo or Hawaiian with cultural context',
        'saas_alternative': 'Most platforms support 5-10 major languages only',
        'build_value': 'HIGH - if serving specific language communities underserved by market'
    },
    
    'offline_capability': {
        'description': 'Full functionality without internet connectivity',
        'example': 'Rural schools with unreliable internet',
        'saas_alternative': 'SaaS platforms require internet by nature',
        'build_value': 'MEDIUM - progressive web apps can cache content, generation still needs connection'
    },
    
    'ip_ownership': {
        'description': 'Complete ownership of all generated content and data',
        'example': 'District publishing generated books commercially',
        'saas_alternative': 'Most platforms grant commercial use rights to generated content',
        'build_value': 'LOW - licensing usually sufficient unless building content business'
    }
}

def evaluate_build_justification(requirements: list[str]) -> dict:
    """
    Evaluate whether custom requirements justify build decision.
    
    Returns recommendation with reasoning.
    """
    high_value_count = 0
    medium_value_count = 0
    
    justifications = []
    
    for req in requirements:
        if req in BUILD_JUSTIFICATION_CRITERIA:
            criteria = BUILD_JUSTIFICATION_CRITERIA[req]
            value = criteria['build_value'].split(' - ')[0]
            
            if value == 'HIGH':
                high_value_count += 1
            elif value == 'MEDIUM':
                medium_value_count += 1
            
            justifications.append({
                'requirement': req,
                'value': value,
                'description': criteria['description'],
                'saas_alternative': criteria['saas_alternative']
            })
    
    # Decision logic
    if high_value_count >= 2:
        recommendation = 'BUILD'
        reasoning = f'{high_value_count} high-value custom requirements justify development'
    elif high_value_count == 1 and medium_value_count >= 2:
        recommendation = 'HYBRID'
        reasoning = 'Consider SaaS platform with custom extensions via API'
    else:
        recommendation = 'BUY'
        reasoning = 'Standard features meet most needs; customization not worth TCO premium'
    
    return {
        'recommendation': recommendation,
        'reasoning': reasoning,
        'high_value_requirements': high_value_count,
        'medium_value_requirements': medium_value_count,
        'justifications': justifications
    }

# Example evaluation
requirements = [
    'district_specific_curriculum',
    'multilingual_support',  # Serving Navajo-speaking students
    'advanced_data_integration'
]

evaluation = evaluate_build_justification(requirements)
# Result: HYBRID - 2 high-value + 1 low-value
# Recommendation: Buy SaaS for core, build custom Navajo language extension

Feature velocity and competitive landscape

Consider rate of innovation in AI storybook generation market.

Market evolution factors:

If your custom build freezes capabilities at launch while SaaS evolves, TCO gap widens over time.

Total capability assessment time: 4-6 hours including requirement gathering and vendor feature comparison.

Risk factor: LOW. Capability gaps are usually obvious; main risk is underestimating SaaS flexibility.

Technical resource and timeline evaluation

If you lack internal technical capacity, build path fails regardless of other factors.

Required technical skillset for custom build

Building production-ready AI storybook generator requires specific expertise.

Development team requirements:

REQUIRED_SKILLS = {
    'backend_development': {
        'skills': [
            'Node.js or Python backend frameworks',
            'API design and implementation',
            'Database design (PostgreSQL)',
            'Queue systems (Redis, Celery)',
            'Authentication and authorization (OAuth, SAML)'
        ],
        'experience_level': 'Senior (5+ years)',
        'estimated_hours': 400,
        'hourly_rate_range': [100, 200]
    },
    
    'frontend_development': {
        'skills': [
            'React or Vue.js',
            'Responsive design',
            'State management (Redux)',
            'Real-time updates (WebSocket)'
        ],
        'experience_level': 'Mid-Senior (3+ years)',
        'estimated_hours': 300,
        'hourly_rate_range': [80, 150]
    },
    
    'ai_integration': {
        'skills': [
            'OpenAI API integration',
            'DALL-E/Midjourney/Stable Diffusion',
            'Prompt engineering',
            'Rate limiting and retry logic',
            'Cost optimization'
        ],
        'experience_level': 'Senior (specialized)',
        'estimated_hours': 200,
        'hourly_rate_range': [120, 250]
    },
    
    'devops_infrastructure': {
        'skills': [
            'AWS/GCP/Azure deployment',
            'Docker/Kubernetes',
            'CI/CD pipelines',
            'Monitoring and alerting',
            'Security hardening'
        ],
        'experience_level': 'Senior (3+ years)',
        'estimated_hours': 100,
        'hourly_rate_range': [100, 180]
    },
    
    'educational_content': {
        'skills': [
            'Reading level assessment',
            'Curriculum alignment',
            'Age-appropriate content design',
            'Accessibility standards (WCAG)'
        ],
        'experience_level': 'EdTech specialist',
        'estimated_hours': 80,
        'hourly_rate_range': [75, 120]
    }
}

def assess_internal_capacity(district_it_team: dict) -> dict:
    """
    Assess whether district has capacity to build in-house.
    
    Args:
        district_it_team: Dict with team member skills and availability
    """
    
    total_required_hours = sum(
        skill['estimated_hours'] 
        for skill in REQUIRED_SKILLS.values()
    )
    
    skill_gaps = []
    available_hours = 0
    
    for skill_area, requirements in REQUIRED_SKILLS.items():
        # Check if team has required skills
        has_skills = any(
            skill in member.get('skills', [])
            for member in district_it_team.get('members', [])
            for skill in requirements['skills']
        )
        
        if not has_skills:
            skill_gaps.append({
                'area': skill_area,
                'required_skills': requirements['skills'],
                'hours': requirements['estimated_hours']
            })
    
    # Calculate team availability
    for member in district_it_team.get('members', []):
        available_hours += member.get('available_hours_per_month', 0) * 6  # 6 months
    
    capacity_ratio = available_hours / total_required_hours if total_required_hours > 0 else 0
    
    recommendation = 'OUTSOURCE' if len(skill_gaps) >= 3 else \
                     'HYBRID' if len(skill_gaps) >= 1 else \
                     'IN_HOUSE'
    
    return {
        'total_required_hours': total_required_hours,
        'available_hours': available_hours,
        'capacity_ratio': capacity_ratio,
        'skill_gaps': skill_gaps,
        'recommendation': recommendation,
        'reasoning': f'{len(skill_gaps)} critical skill gaps; ' +
                    f'team has {capacity_ratio:.0%} of required capacity'
    }

# Example: Typical district IT team
district_team = {
    'members': [
        {
            'role': 'IT Director',
            'skills': ['Network administration', 'Vendor management'],
            'available_hours_per_month': 20
        },
        {
            'role': 'Systems Administrator',
            'skills': ['Windows Server', 'Active Directory', 'Basic SQL'],
            'available_hours_per_month': 40
        },
        {
            'role': 'Help Desk Technician',
            'skills': ['End user support', 'Basic troubleshooting'],
            'available_hours_per_month': 10
        }
    ]
}

capacity_assessment = assess_internal_capacity(district_team)
"""
Result:
- Total required: 1,080 hours
- Available: 420 hours (over 6 months)
- Capacity: 39%
- Skill gaps: 5/5 critical areas
- Recommendation: OUTSOURCE

Typical district IT lacks specialized skills for AI application development
"""

Development timeline for MVP and production

Realistic timeline accounting for school schedules and resource constraints.

Development phases:

DEVELOPMENT_TIMELINE = {
    'discovery_and_planning': {
        'duration_weeks': 4,
        'activities': [
            'Requirements gathering',
            'Vendor evaluation (if considering SaaS)',
            'Technical architecture design',
            'Security and compliance review',
            'Budget approval process'
        ],
        'school_year_constraint': 'Can start any time'
    },
    
    'mvp_development': {
        'duration_weeks': 12,
        'activities': [
            'Core generation engine',
            'Basic UI for teachers and students',
            'PDF export',
            'User authentication',
            'Initial testing with pilot teachers'
        ],
        'school_year_constraint': 'Avoid Dec/Jan (winter break), May/June (end of year)'
    },
    
    'pilot_testing': {
        'duration_weeks': 8,
        'activities': [
            'Deploy to 2-3 pilot classrooms',
            'Gather teacher feedback',
            'Bug fixes and refinements',
            'Usage analytics review'
        ],
        'school_year_constraint': 'Best: Feb-Apr or Sep-Nov'
    },
    
    'production_buildout': {
        'duration_weeks': 16,
        'activities': [
            'Classroom management features',
            'Parent portal',
            'Advanced curriculum alignment',
            'Reporting and analytics',
            'Security audit and penetration testing',
            'Load testing for district-wide rollout'
        ],
        'school_year_constraint': 'Can proceed during pilot'
    },
    
    'district_rollout': {
        'duration_weeks': 12,
        'activities': [
            'Teacher professional development',
            'Gradual rollout to all schools',
            'Support infrastructure setup',
            'Integration with SIS',
            'Policy and acceptable use guidelines'
        ],
        'school_year_constraint': 'Best: August (back to school) or January (semester start)'
    }
}

def calculate_realistic_timeline(start_date: str) -> dict:
    """
    Calculate realistic timeline accounting for school calendar.
    
    Args:
        start_date: Project start date (YYYY-MM-DD)
    """
    from datetime import datetime, timedelta
    
    start = datetime.strptime(start_date, '%Y-%m-%d')
    current_date = start
    
    phases = []
    total_weeks = 0
    
    for phase_name, details in DEVELOPMENT_TIMELINE.items():
        phase_start = current_date
        duration = details['duration_weeks']
        
        # Add buffer for school calendar constraints
        if 'Dec/Jan' in details.get('school_year_constraint', ''):
            # Check if phase crosses winter break
            if current_date.month in [11, 12, 1]:
                duration += 4  # Add 4 weeks buffer
        
        phase_end = current_date + timedelta(weeks=duration)
        
        phases.append({
            'phase': phase_name,
            'start': phase_start.strftime('%Y-%m-%d'),
            'end': phase_end.strftime('%Y-%m-%d'),
            'duration_weeks': duration,
            'activities': details['activities']
        })
        
        current_date = phase_end
        total_weeks += duration
    
    return {
        'start_date': start_date,
        'estimated_completion': current_date.strftime('%Y-%m-%d'),
        'total_weeks': total_weeks,
        'total_months': round(total_weeks / 4.33, 1),
        'phases': phases
    }

# Example: Start project in August 2026
timeline = calculate_realistic_timeline('2026-08-01')
"""
Results:
- Start: August 1, 2026
- MVP ready: ~November 2026 (16 weeks with buffer)
- Pilot complete: ~February 2027 (24 weeks)
- Production ready: ~June 2027 (40 weeks)
- District rollout complete: ~September 2027 (52+ weeks)

Total: 12-14 months from start to district-wide deployment

Compare to SaaS: 2-3 months from contract to full deployment
"""

Total resource assessment time: 3-4 hours including skill inventory and timeline modeling.

Risk factor: HIGH. Underestimating timeline and skill requirements is most common build decision failure.

Decision framework and recommendation matrix

If you need structured decision process, use weighted criteria matrix.

Multi-criteria decision matrix

Weight multiple factors based on district priorities.

Decision criteria:

DECISION_CRITERIA = {
    'cost': {
        'weight': 0.25,
        'scoring': {
            'buy': 9,  # Lower 5-year TCO
            'build': 3,  # Higher TCO but potential long-term savings
            'hybrid': 6
        }
    },
    
    'time_to_value': {
        'weight': 0.20,
        'scoring': {
            'buy': 10,  # 2-3 months to full deployment
            'build': 2,  # 12-14 months to full deployment
            'hybrid': 5
        }
    },
    
    'customization': {
        'weight': 0.15,
        'scoring': {
            'buy': 5,  # Limited to vendor roadmap
            'build': 10,  # Complete control
            'hybrid': 8
        }
    },
    
    'technical_risk': {
        'weight': 0.15,
        'scoring': {
            'buy': 9,  # Vendor handles infrastructure, security
            'build': 3,  # District assumes all technical risk
            'hybrid': 6
        }
    },
    
    'feature_velocity': {
        'weight': 0.10,
        'scoring': {
            'buy': 9,  # Continuous updates from vendor
            'build': 4,  # Slow feature development
            'hybrid': 6
        }
    },
    
    'vendor_lock_in': {
        'weight': 0.08,
        'scoring': {
            'buy': 4,  # Dependent on vendor
            'build': 10,  # Complete independence
            'hybrid': 7
        }
    },
    
    'scalability': {
        'weight': 0.07,
        'scoring': {
            'buy': 10,  # Vendor handles scaling
            'build': 6,  # Must plan infrastructure
            'hybrid': 8
        }
    }
}

def calculate_weighted_score(scenario: str) -> dict:
    """Calculate weighted score for build, buy, or hybrid."""
    
    total_score = 0
    criteria_scores = []
    
    for criterion, details in DECISION_CRITERIA.items():
        score = details['scoring'][scenario]
        weighted_score = score * details['weight']
        total_score += weighted_score
        
        criteria_scores.append({
            'criterion': criterion,
            'raw_score': score,
            'weight': details['weight'],
            'weighted_score': weighted_score
        })
    
    return {
        'scenario': scenario,
        'total_score': round(total_score, 2),
        'criteria_breakdown': criteria_scores
    }

# Calculate scores for all scenarios
scenarios = ['buy', 'build', 'hybrid']
results = {scenario: calculate_weighted_score(scenario) for scenario in scenarios}

"""
Weighted Scores:
BUY: 8.31/10
BUILD: 5.24/10
HYBRID: 6.51/10

Recommendation: BUY for most school districts
- Lowest TCO
- Fastest time-to-value
- Lowest technical risk

BUILD only if:
- 2+ high-value custom requirements
- Internal technical capacity exists
- 3+ year commitment to maintenance
"""

Situational recommendations

Different district profiles favor different approaches.

Recommendation by district profile:

DISTRICT_PROFILES = {
    'small_rural': {
        'characteristics': {
            'schools': '1-3',
            'students': '<1000',
            'it_staff': '1-2',
            'budget': '<$50k/year for EdTech'
        },
        'recommendation': 'BUY',
        'reasoning': [
            'Limited technical capacity',
            'Cannot afford custom development costs',
            'Standard features meet needs',
            'SaaS pricing affordable ($2k-6k/year)'
        ],
        'suggested_platform': 'Entry-tier SaaS with basic features'
    },
    
    'suburban_medium': {
        'characteristics': {
            'schools': '5-15',
            'students': '2000-8000',
            'it_staff': '3-8',
            'budget': '$50k-200k/year for EdTech'
        },
        'recommendation': 'BUY or HYBRID',
        'reasoning': [
            'SaaS platforms offer district-level features',
            'API access enables custom integrations',
            'IT team can manage integrations, not full builds',
            'Budget supports premium tiers with customization'
        ],
        'suggested_platform': 'Premium SaaS with API access, custom SIS integration'
    },
    
    'urban_large': {
        'characteristics': {
            'schools': '20-100+',
            'students': '10000-100000+',
            'it_staff': '10-50+',
            'budget': '$500k-5M+/year for EdTech'
        },
        'recommendation': 'HYBRID or BUY',
        'reasoning': [
            'Large enough to justify dedicated development team',
            'Unique requirements at scale (50k+ students)',
            'Budget supports custom features',
            'Hybrid: SaaS core + custom district dashboard'
        ],
        'suggested_platform': 'Enterprise SaaS with white-label options + custom reporting layer'
    },
    
    'specialized_charter_network': {
        'characteristics': {
            'schools': '5-20',
            'students': '2000-10000',
            'it_staff': '2-10',
            'budget': 'Variable, grant-funded',
            'unique_factor': 'Specialized curriculum (Montessori, STEM, language immersion)'
        },
        'recommendation': 'BUY with customization',
        'reasoning': [
            'Curriculum alignment critical',
            'SaaS platforms offer content customization',
            'Grant funding may support custom features',
            'Charter network scale justifies investment'
        ],
        'suggested_platform': 'Curriculum-flexible SaaS + custom content library'
    },
    
    'edtech_innovation_district': {
        'characteristics': {
            'schools': 'Variable',
            'students': 'Variable',
            'it_staff': 'Strong technical team',
            'budget': 'Innovation grants, pilot funding',
            'unique_factor': 'Research partnership, competitive advantage focus'
        },
        'recommendation': 'BUILD or HYBRID',
        'reasoning': [
            'Innovation is strategic priority',
            'Internal development builds institutional capability',
            'Research partnerships benefit from custom data collection',
            'Pilot can inform broader market'
        ],
        'suggested_platform': 'Custom build with potential commercialization'
    }
}

def recommend_for_district(district_characteristics: dict) -> dict:
    """
    Recommend build/buy/hybrid based on district profile.
    
    Args:
        district_characteristics: Dict with schools, students, it_staff, budget
    """
    
    schools = district_characteristics.get('schools', 0)
    it_staff = district_characteristics.get('it_staff', 0)
    budget = district_characteristics.get('budget', 0)
    
    # Simple decision tree
    if schools <= 3 or it_staff <= 2:
        profile = 'small_rural'
    elif schools >= 20 and it_staff >= 10:
        profile = 'urban_large'
    elif district_characteristics.get('specialized'):
        profile = 'specialized_charter_network'
    else:
        profile = 'suburban_medium'
    
    recommendation_data = DISTRICT_PROFILES[profile]
    
    return {
        'matched_profile': profile,
        'recommendation': recommendation_data['recommendation'],
        'reasoning': recommendation_data['reasoning'],
        'suggested_platform': recommendation_data['suggested_platform']
    }

Total decision framework time: 2-3 hours including stakeholder input and criteria weighting.

Risk factor: LOW. Decision matrices surface trade-offs clearly; main risk is ignoring recommendation.

Where Musketeers Tech fits into build vs buy decisions

If you are evaluating options

Help you move from vendor comparisons to comprehensive TCO analysis with realistic cost modeling, hidden cost identification, and risk-adjusted scenarios.

Conduct unbiased capability assessment comparing SaaS platforms against actual requirements.

Provide technical capacity audit determining whether internal team can realistically build and maintain.

If you decide to buy SaaS platform

Support vendor selection with RFP development, technical evaluation, and contract negotiation.

Implement SaaS integration including SSO, SIS sync, and custom reporting layers.

Build custom extensions via platform APIs when specific requirements need augmentation.

If you decide to build custom solution

Design and develop production-ready AI storybook generator with curriculum alignment, classroom management, and parent engagement.

Implement infrastructure, security, and compliance meeting K-12 requirements.

Provide ongoing maintenance and feature development as internal capacity partner.

So what should you do next?

Conduct preliminary analysis by documenting specific requirements beyond commodity features, calculating realistic 5-year budget including hidden costs, assessing internal technical capacity honestly without optimism bias.

Request SaaS demos from 3-5 vendors testing actual workflows with pilot teachers, evaluating curriculum alignment and customization flexibility, comparing pricing across realistic usage scenarios.

Build decision matrix with weighted criteria reflecting district priorities, score build/buy/hybrid scenarios objectively, present recommendation to decision makers with TCO and risk analysis before committing resources.

Frequently Asked Questions (FAQs)

1. How much does it really cost to build a custom AI storybook generator?

Realistic custom build costs $90,000-150,000 for initial development plus $40,000-60,000 annually for maintenance, infrastructure, and enhancements. Total 5-year TCO typically runs $250,000-450,000 including hidden costs like talent retention, security audits, and opportunity costs. Compare to SaaS at $60,000-120,000 over 5 years for most districts.

2. Can we start with SaaS and switch to custom build later?

Yes, but switching costs are significant ($15,000-30,000) including data migration, user re-training, and workflow disruption. Better approach: start with SaaS, use extensively, identify true gaps that justify custom build after 2-3 years of usage data. Most districts discover SaaS meets 90%+ of needs, eliminating build rationale.

3. What if our district has unique curriculum requirements?

Most “unique” requirements aren’t actually unique. Evaluate whether SaaS platforms with custom content libraries, curriculum tagging, or API access can meet needs. True uniqueness (serving under-represented languages, research partnerships, competitive differentiation) justifies custom build. Curriculum alignment preferences rarely justify $300k+ development investment.

4. How do we evaluate vendor stability and avoid lock-in?

Check vendor funding (Series A+), customer count (100+ schools), years in business (2+ years), and data portability. Request content export formats, API documentation, and source code escrow agreements. Build exit strategy into contract with defined transition assistance and data ownership terms. Lock-in risk exists but is manageable with proper contracts.

5. How does Musketeers Tech help with build vs buy decisions?

Musketeers Tech provides unbiased build vs buy analysis including comprehensive TCO modeling with risk adjustments, capability gap assessment and requirement validation, technical capacity audit and resource planning, vendor evaluation and RFP support for buy decisions, custom development and integration services for build decisions, and hybrid approaches combining SaaS core with custom extensions, ensuring your district invests resources optimally whether that means buying existing platform, building custom solution, or taking hybrid approach.

January 20, 2026 Musketeers Tech Musketeers Tech
← Back