|
|
"""Cost estimation for different deployment platforms.""" |
|
|
|
|
|
from __future__ import annotations |
|
|
|
|
|
from typing import Any, Dict, List, Optional |
|
|
|
|
|
|
|
|
class CostEstimator: |
|
|
"""Estimates deployment costs for different platforms.""" |
|
|
|
|
|
def estimate_platform_cost( |
|
|
self, |
|
|
platform: str, |
|
|
framework: Optional[str] = None, |
|
|
traffic: str = "low", |
|
|
storage: str = "small" |
|
|
) -> Dict[str, Any]: |
|
|
"""Estimate monthly cost for a platform.""" |
|
|
|
|
|
|
|
|
pricing = { |
|
|
"vercel": { |
|
|
"hobby": 0, |
|
|
"pro": 20, |
|
|
"enterprise": "custom", |
|
|
"description": "Free tier: 100GB bandwidth, Pro: $20/month unlimited" |
|
|
}, |
|
|
"netlify": { |
|
|
"starter": 0, |
|
|
"pro": 19, |
|
|
"business": 99, |
|
|
"description": "Free tier: 100GB bandwidth, Pro: $19/month" |
|
|
}, |
|
|
"aws": { |
|
|
"lambda": 0.20, |
|
|
"ec2_small": 15, |
|
|
"ec2_medium": 30, |
|
|
"description": "Pay-as-you-go, ~$15-50/month for small apps" |
|
|
}, |
|
|
"gcp": { |
|
|
"cloud_run": 0.40, |
|
|
"compute_small": 12, |
|
|
"description": "Free tier available, ~$12-40/month" |
|
|
}, |
|
|
"azure": { |
|
|
"app_service": 13, |
|
|
"functions": 0.20, |
|
|
"description": "Free tier available, ~$13-50/month" |
|
|
}, |
|
|
"railway": { |
|
|
"starter": 5, |
|
|
"pro": 20, |
|
|
"description": "$5/month starter, $20/month pro" |
|
|
}, |
|
|
"render": { |
|
|
"free": 0, |
|
|
"starter": 7, |
|
|
"standard": 25, |
|
|
"description": "Free tier available, $7-25/month" |
|
|
}, |
|
|
"fly.io": { |
|
|
"starter": 0, |
|
|
"scale": 10, |
|
|
"description": "Free tier: 3 VMs, Scale: $10+/month" |
|
|
}, |
|
|
"kubernetes": { |
|
|
"managed": 73, |
|
|
"self_hosted": 50, |
|
|
"description": "Managed: $73+/month, Self-hosted: $50+/month" |
|
|
}, |
|
|
"docker": { |
|
|
"hosting": 5, |
|
|
"description": "Varies by hosting provider, ~$5-20/month" |
|
|
} |
|
|
} |
|
|
|
|
|
platform_lower = platform.lower() |
|
|
cost_info = pricing.get(platform_lower, { |
|
|
"estimated": "Unknown", |
|
|
"description": "Cost estimation not available" |
|
|
}) |
|
|
|
|
|
|
|
|
base_cost = cost_info.get("pro") or cost_info.get("starter") or cost_info.get("estimated", 0) |
|
|
if isinstance(base_cost, (int, float)): |
|
|
if traffic == "high": |
|
|
base_cost *= 2 |
|
|
elif traffic == "medium": |
|
|
base_cost *= 1.5 |
|
|
|
|
|
return { |
|
|
"platform": platform, |
|
|
"framework": framework, |
|
|
"estimated_monthly_cost": base_cost if isinstance(base_cost, (int, float)) else base_cost, |
|
|
"cost_range": self._get_cost_range(platform_lower, traffic), |
|
|
"description": cost_info.get("description", ""), |
|
|
"traffic_level": traffic, |
|
|
"recommendations": self._get_cost_recommendations(platform_lower, base_cost) |
|
|
} |
|
|
|
|
|
def _get_cost_range(self, platform: str, traffic: str) -> str: |
|
|
"""Get cost range string.""" |
|
|
ranges = { |
|
|
"vercel": "$0-20/month", |
|
|
"netlify": "$0-19/month", |
|
|
"aws": "$15-100/month", |
|
|
"gcp": "$12-80/month", |
|
|
"azure": "$13-100/month", |
|
|
"railway": "$5-20/month", |
|
|
"render": "$0-25/month", |
|
|
"fly.io": "$0-50/month", |
|
|
"kubernetes": "$50-200/month", |
|
|
"docker": "$5-50/month" |
|
|
} |
|
|
return ranges.get(platform, "Varies") |
|
|
|
|
|
def _get_cost_recommendations(self, platform: str, cost: Any) -> List[str]: |
|
|
"""Get cost optimization recommendations.""" |
|
|
recommendations = [] |
|
|
|
|
|
if platform in ["vercel", "netlify", "render"]: |
|
|
recommendations.append("Start with free tier for development") |
|
|
recommendations.append("Upgrade to paid tier only when needed") |
|
|
|
|
|
if platform in ["aws", "gcp", "azure"]: |
|
|
recommendations.append("Use reserved instances for 30-50% savings") |
|
|
recommendations.append("Monitor usage to optimize costs") |
|
|
|
|
|
if isinstance(cost, (int, float)) and cost > 50: |
|
|
recommendations.append("Consider serverless options for cost savings") |
|
|
recommendations.append("Review and optimize resource allocation") |
|
|
|
|
|
return recommendations |
|
|
|
|
|
def compare_platforms(self, platforms: List[str], framework: Optional[str] = None) -> Dict[str, Any]: |
|
|
"""Compare costs across multiple platforms.""" |
|
|
comparisons = [] |
|
|
for platform in platforms: |
|
|
cost_info = self.estimate_platform_cost(platform, framework) |
|
|
comparisons.append(cost_info) |
|
|
|
|
|
|
|
|
sorted_platforms = sorted( |
|
|
[c for c in comparisons if isinstance(c["estimated_monthly_cost"], (int, float))], |
|
|
key=lambda x: x["estimated_monthly_cost"] |
|
|
) |
|
|
|
|
|
return { |
|
|
"platforms": comparisons, |
|
|
"cheapest": sorted_platforms[0] if sorted_platforms else None, |
|
|
"recommendation": self._get_best_platform_recommendation(sorted_platforms, framework) |
|
|
} |
|
|
|
|
|
def _get_best_platform_recommendation(self, sorted_platforms: List[Dict], framework: Optional[str]) -> str: |
|
|
"""Get recommendation for best platform.""" |
|
|
if not sorted_platforms: |
|
|
return "Compare platforms based on your specific needs" |
|
|
|
|
|
cheapest = sorted_platforms[0] |
|
|
|
|
|
if framework == "next.js": |
|
|
return f"For Next.js, consider Vercel (optimized) or {cheapest['platform']} (cost-effective)" |
|
|
elif framework in ["django", "flask", "fastapi"]: |
|
|
return f"For Python apps, {cheapest['platform']} offers good value" |
|
|
else: |
|
|
return f"{cheapest['platform']} is the most cost-effective option" |
|
|
|
|
|
|