Engineering Team Scaling Calculator - Optimize team growth and structure
from typing import Dict, List, Tuple
class TeamScalingCalculator:
self.conway_factor = 1.5 # Conway's Law impact factor
self.brooks_factor = 0.75 # Brooks' Law diminishing returns
# Optimal team structures based on size
'startup': {'min': 1, 'max': 10, 'structure': 'flat'},
'growth': {'min': 11, 'max': 50, 'structure': 'team_leads'},
'scale': {'min': 51, 'max': 150, 'structure': 'departments'},
'enterprise': {'min': 151, 'max': 9999, 'structure': 'divisions'}
# Role ratios for balanced teams
'engineering_manager': 0.125, # 1:8 ratio
'tech_lead': 0.167, # 1:6 ratio
def calculate_scaling_plan(self, current_state: Dict, growth_targets: Dict) -> Dict:
"""Calculate optimal scaling plan"""
'current_analysis': self._analyze_current_state(current_state),
'growth_timeline': self._create_growth_timeline(current_state, growth_targets),
results['hiring_plan'] = self._generate_hiring_plan(
results['team_structure'] = self._design_team_structure(
growth_targets['target_headcount']
results['budget_projection'] = self._calculate_budget(
current_state.get('location', 'US')
results['risk_factors'] = self._assess_scaling_risks(
# Generate recommendations
results['recommendations'] = self._generate_recommendations(results)
def _analyze_current_state(self, current_state: Dict) -> Dict:
"""Analyze current team state"""
total_engineers = current_state.get('headcount', 0)
'total_headcount': total_engineers,
'team_stage': self._get_team_stage(total_engineers),
# Calculate productivity index
velocity = current_state.get('velocity', 100)
expected_velocity = total_engineers * 20 # baseline 20 points per engineer
analysis['productivity_index'] = (velocity / expected_velocity) * 100
roles = current_state.get('roles', {})
analysis['balance_score'] = self._calculate_balance_score(roles, total_engineers)
if analysis['productivity_index'] < 70:
analysis['issues'].append('Low productivity - possible process or tooling issues')
if analysis['balance_score'] < 60:
analysis['issues'].append('Team imbalance - review role distribution')
manager_ratio = roles.get('managers', 0) / max(total_engineers, 1)
analysis['issues'].append('Over-managed - too many managers')
elif manager_ratio < 0.08 and total_engineers > 20:
analysis['issues'].append('Under-managed - need more engineering managers')
def _get_team_stage(self, headcount: int) -> str:
"""Determine team stage based on size"""
for stage, config in self.team_structures.items():
if config['min'] <= headcount <= config['max']:
def _calculate_balance_score(self, roles: Dict, total: int) -> float:
"""Calculate team balance score"""
ideal_ratios = self.role_ratios
for role, ideal_ratio in ideal_ratios.items():
actual_count = roles.get(role, 0)
actual_ratio = actual_count / total
# Penalize deviation from ideal ratio
deviation = abs(actual_ratio - ideal_ratio)
penalty = deviation * 100
score -= min(penalty, 20) # Max 20 point penalty per role
def _create_growth_timeline(self, current: Dict, targets: Dict) -> List[Dict]:
"""Create quarterly growth timeline"""
current_headcount = current.get('headcount', 0)
target_headcount = targets.get('target_headcount', current_headcount)
timeline_quarters = targets.get('timeline_quarters', 4)
growth_needed = target_headcount - current_headcount
for quarter in range(1, timeline_quarters + 1):
# Apply Brooks' Law - diminishing returns with rapid growth
quarterly_growth = math.ceil(growth_needed * 0.4) # Front-load hiring
remaining_growth = target_headcount - current_headcount
quarters_left = timeline_quarters - quarter + 1
quarterly_growth = math.ceil(remaining_growth / quarters_left)
# Adjust for onboarding capacity
max_onboarding = math.ceil(current_headcount * 0.25) # 25% growth per quarter max
quarterly_growth = min(quarterly_growth, max_onboarding)
current_headcount += quarterly_growth
'quarter': f'Q{quarter}',
'headcount': current_headcount,
'new_hires': quarterly_growth,
'onboarding_capacity': max_onboarding,
'productivity_factor': 1.0 - (0.2 * (quarterly_growth / max(current_headcount, 1)))
def _generate_hiring_plan(self, current: Dict, targets: Dict) -> Dict:
"""Generate detailed hiring plan"""
current_roles = current.get('roles', {})
target_headcount = targets.get('target_headcount', 0)
'total_hires_needed': target_headcount - current.get('headcount', 0),
'interview_capacity_needed': 0,
'recruiting_resources': 0
# Calculate ideal role distribution
for role, ideal_ratio in self.role_ratios.items():
ideal_count = math.ceil(target_headcount * ideal_ratio)
current_count = current_roles.get(role, 0)
hires_needed = max(0, ideal_count - current_count)
hiring_plan['by_role'][role] = {
'current': current_count,
'hires_needed': hires_needed,
'priority': self._get_role_priority(role, current_roles, target_headcount)
# Distribute hires across quarters
timeline = self._create_growth_timeline(current, targets)
for quarter_data in timeline:
quarter = quarter_data['quarter']
hires = quarter_data['new_hires']
hiring_plan['by_quarter'][quarter] = {
'breakdown': self._distribute_quarterly_hires(hires, hiring_plan['by_role'])
# Calculate interview capacity (5 interviews per hire average)
hiring_plan['interview_capacity_needed'] = hiring_plan['total_hires_needed'] * 5
# Calculate recruiting resources (1 recruiter per 50 hires/year)
annual_hires = hiring_plan['total_hires_needed'] * (4 / max(targets.get('timeline_quarters', 4), 1))
hiring_plan['recruiting_resources'] = math.ceil(annual_hires / 50)
def _get_role_priority(self, role: str, current_roles: Dict, target_size: int) -> int:
"""Determine hiring priority for a role"""
# Priority based on criticality and current gaps
'engineering_manager': 10 if target_size > 20 else 5,
'devops': 7 if current_roles.get('devops', 0) == 0 else 5,
return priorities.get(role, 5)
def _distribute_quarterly_hires(self, total_hires: int, role_needs: Dict) -> Dict:
"""Distribute quarterly hires across roles"""
key=lambda x: x[1]['priority'],
remaining_hires = total_hires
for role, needs in sorted_roles:
hires = min(needs['hires_needed'], max(1, remaining_hires // 3))
distribution[role] = hires
def _design_team_structure(self, target_headcount: int) -> Dict:
"""Design optimal team structure"""
stage = self._get_team_stage(target_headcount)
'organizational_model': self.team_structures[stage]['structure'],
'reporting_structure': {},
'size': target_headcount,
num_teams = math.ceil(target_headcount / team_size)
'focus': ['Platform', 'Product', 'Infrastructure', 'Growth'][i % 4]
for i in range(num_teams)
# Create departments with multiple teams
structure['departments'] = [
{'name': 'Platform', 'teams': 3, 'headcount': target_headcount * 0.3},
{'name': 'Product', 'teams': 4, 'headcount': target_headcount * 0.4},
{'name': 'Infrastructure', 'teams': 2, 'headcount': target_headcount * 0.2},
{'name': 'Data', 'teams': 1, 'headcount': target_headcount * 0.1}
# Calculate communication paths (n*(n-1)/2)
structure['communication_paths'] = (target_headcount * (target_headcount - 1)) // 2
structure['management_layers'] = math.ceil(math.log(target_headcount, 7))
def _calculate_budget(self, hiring_plan: Dict, location: str) -> Dict:
"""Calculate budget projection"""
# Average salaries by role and location (in USD)
'engineering_manager': 200000,
'senior_engineer': 160000,
'junior_engineer': 85000,
'product_manager': 150000,
'EU': {k: v * 0.8 for k, v in salary_bands.get('US', {}).items()},
'APAC': {k: v * 0.6 for k, v in salary_bands.get('US', {}).items()}
location_salaries = salary_bands.get(location, salary_bands['US'])
'benefits_cost': 0, # 30% of salary
'equipment_cost': 0, # $5k per hire
'recruiting_cost': 0, # 20% of first-year salary
'onboarding_cost': 0, # $10k per hire
for role, details in hiring_plan['by_role'].items():
hires = details['hires_needed']
salary = location_salaries.get(role, 100000)
budget['annual_salary_cost'] += hires * salary
budget['recruiting_cost'] += hires * salary * 0.2
budget['benefits_cost'] = budget['annual_salary_cost'] * 0.3
budget['equipment_cost'] = hiring_plan['total_hires_needed'] * 5000
budget['onboarding_cost'] = hiring_plan['total_hires_needed'] * 10000
budget['total_cost'] = sum([
budget['annual_salary_cost'],
budget['equipment_cost'],
budget['recruiting_cost'],
budget['onboarding_cost']
if hiring_plan['total_hires_needed'] > 0:
budget['cost_per_hire'] = budget['total_cost'] / hiring_plan['total_hires_needed']
def _assess_scaling_risks(self, current: Dict, targets: Dict) -> List[Dict]:
"""Assess risks in scaling plan"""
growth_rate = (targets['target_headcount'] - current['headcount']) / max(current['headcount'], 1)
if growth_rate > 1.0: # More than 100% growth
'risk': 'Rapid growth dilution',
'mitigation': 'Implement strong onboarding and mentorship programs'
if current.get('attrition_rate', 0) > 15:
'risk': 'High attrition during scaling',
'mitigation': 'Address retention issues before aggressive hiring'
if targets.get('timeline_quarters', 4) < 4:
'risk': 'Compressed timeline',
'mitigation': 'Consider extending timeline or increasing recruiting resources'
def _generate_recommendations(self, results: Dict) -> List[str]:
"""Generate scaling recommendations"""
total_hires = results['hiring_plan']['total_hires_needed']
current_size = results['current_analysis']['total_headcount']
growth_rate = total_hires / current_size
recommendations.append('Consider hiring a dedicated recruiting team')
recommendations.append('Implement scalable onboarding processes')
recommendations.append('Establish clear team charters and boundaries')
recommendations.append('⚠️ High growth risk - consider slowing timeline')
recommendations.append('Focus on senior hires first to establish culture')
recommendations.append('Implement continuous integration practices early')
if results['team_structure']['communication_paths'] > 1000:
recommendations.append('Implement clear communication channels and tools')
recommendations.append('Consider platform teams to reduce dependencies')
if results['current_analysis']['balance_score'] < 70:
recommendations.append('Prioritize hiring for underrepresented roles')
recommendations.append('Consider role rotation for skill development')
def calculate_team_scaling(current_state: Dict, growth_targets: Dict) -> str:
"""Main function to calculate team scaling"""
calculator = TeamScalingCalculator()
results = calculator.calculate_scaling_plan(current_state, growth_targets)
"=== Engineering Team Scaling Plan ===",
f"Current State Analysis:",
f" Current Headcount: {results['current_analysis']['total_headcount']}",
f" Team Stage: {results['current_analysis']['team_stage']}",
f" Productivity Index: {results['current_analysis']['productivity_index']:.1f}%",
f" Team Balance Score: {results['current_analysis']['balance_score']:.1f}/100",
f" Target Headcount: {growth_targets['target_headcount']}",
f" Total Hires Needed: {results['hiring_plan']['total_hires_needed']}",
f" Timeline: {growth_targets['timeline_quarters']} quarters",
for quarter in results['growth_timeline']:
f" {quarter['quarter']}: {quarter['headcount']} total "
f"(+{quarter['new_hires']} hires, "
f"{quarter['productivity_factor']:.0%} productivity)"
results['hiring_plan']['by_role'].items(),
key=lambda x: x[1]['priority'],
for role, details in sorted_roles[:5]:
f" {role}: {details['hires_needed']} hires "
f"(Priority: {details['priority']}/10)"
f" Annual Salary Cost: ${results['budget_projection']['annual_salary_cost']:,.0f}",
f" Total Investment: ${results['budget_projection']['total_cost']:,.0f}",
f" Cost per Hire: ${results['budget_projection']['cost_per_hire']:,.0f}",
f" Model: {results['team_structure']['organizational_model']}",
f" Management Layers: {results['team_structure']['management_layers']}",
f" Communication Paths: {results['team_structure']['communication_paths']:,}",
for rec in results['recommendations']:
output.append(f" • {rec}")
if __name__ == "__main__":
'engineering_manager': 2,
print(calculate_team_scaling(example_current, example_targets))