Module 1: Understanding Deployment Options
7. Project Stage and Deployment
Overview
In this capsule you'll understand how your project's stage (MVP, Growth, Scale) changes the recommended deployment strategy. The same AI app may need a different strategy when it has 10 users than when it has 10,000. By the end, you'll know when and how to evolve your deployment without rewriting everything.
Context: The previous capsule's decision matrix evaluates your current situation. But situations change. An MVP that starts on Railway may need to migrate to AWS as it grows. This capsule prepares you for those transitions — and tells you when NOT to migrate (because many migrate prematurely).
The Three Stages of an AI Project
MVP (Minimum Viable Product)
Users: 1-100
Traffic: <1K requests/day
Team: 1-2 developers
Budget: $0-50/month
Objective: Validate that the idea works
Duration: 1-3 months
At MVP, your priority is iteration speed. You're not optimizing for scale — you're discovering whether your product makes sense. Every hour you spend configuring infrastructure is an hour you don't spend talking to users or improving prompts.
Growth
Users: 100-10,000
Traffic: 1K-50K requests/day
Team: 2-5 developers
Budget: $50-500/month
Objective: Scale what already works
Duration: 3-12 months
At Growth, your priority is stability + controlled scalability. The product works, you have real users, and you need it to not go down. You start thinking about monitoring, informal SLAs, and capacity.
Scale
Users: 10,000+
Traffic: 50K+ requests/day
Team: 5+ developers + ops
Budget: $500+/month
Objective: Operate reliably at volume
Duration: 12+ months
At Scale, your priority is reliability + operational efficiency. You have a dedicated team, formal SLAs, and the cost of downtime is high. You invest in infrastructure because the ROI justifies it.
Deployment Strategy by Stage
MVP: Speed above all
Recommended strategy: MANAGED (Railway, Render)
Why:
├── Deploy in minutes (git push → online)
├── Free tier covers the volume
├── Zero ops (you don't waste time on infra)
├── If the product fails, you didn't invest in infra
└── Easy to migrate later (Docker is portable)
Alternative: LOCAL (Docker Compose on a laptop)
├── For demo and development
├── Before having a public domain
└── If the data can't leave your machine
# MVP deployment: as simple as possible
# main.py — Everything in one file
from fastapi import FastAPI
from openai import OpenAI
import os
app = FastAPI()
client = OpenAI(api_key=os.environ["OPENAI_API_KEY"])
@app.get("/health")
def health():
return {"status": "ok"}
@app.post("/ask")
def ask(prompt: str):
r = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": prompt}],
max_tokens=500
)
return {"answer": r.choices[0].message.content}
# Deploy on Railway: 3 commands
railway login
railway init
railway up
# Public URL in 2 minutes
What you do NOT do at MVP:
- ❌ Kubernetes
- ❌ Multi-region
- ❌ Complex auto-scaling
- ❌ Infrastructure as Code (Terraform)
- ❌ SageMaker
- ❌ Microservices
Growth: Stability + controlled scalability
Recommended strategy: MANAGED (pro) or LOCAL (VPS with Docker)
Why:
├── Predictable traffic, you need uptime
├── Health checks and monitoring are necessary
├── Docker Compose gives you control without complexity
├── A VPS with fixed cost is predictable
└── You can add Redis, workers, databases
Alternative: SERVERLESS (Lambda)
├── If traffic is very variable (peaks)
├── For asynchronous components (batch processing)
└── If you want zero ops on specific components
# Growth: Docker Compose multi-service
# docker-compose.yml
services:
api:
build: ./api
ports:
- "8000:8000"
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- REDIS_URL=redis://cache:6379
depends_on:
cache:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
cache:
image: redis:7-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
worker:
build: ./worker
environment:
- REDIS_URL=redis://cache:6379
depends_on:
- cache
What you add at Growth:
- ✅ Health checks
- ✅ Caching (Redis)
- ✅ Environment config (dev/staging/prod)
- ✅ Basic monitoring (UptimeRobot, logs)
- ✅ Automated deploys (GitHub Actions)
- ✅ Error tracking (Sentry)
Scale: Reliability + efficiency
Recommended strategy: SELF-HOSTED (AWS) or SERVERLESS (Lambda) or HYBRID
Why:
├── Traffic justifies the infra investment
├── An ops team can maintain the complexity
├── Formal SLAs require redundancy
├── Cost optimization has significant ROI
└── Multi-region if you have global users
The ops team absorbs the complexity that at MVP/Growth was unacceptable.
What you add at Scale:
- ✅ Auto-scaling (horizontal)
- ✅ Load balancing
- ✅ Multi-region (if needed)
- ✅ Full observability (metrics, traces, logs)
- ✅ Disaster recovery and automated backups
- ✅ Infrastructure as Code (Terraform/Pulumi)
- ✅ Detailed operational runbooks
When to Migrate Stage
Signs that you need to migrate
MVP → Growth (migrate when):
├── You have real users who depend on the service
├── Downtime causes impact (not just inconvenience)
├── The free tier falls short (RAM, CPU, requests)
├── You need features the platform doesn't have
└── The product is validated and you're going to keep investing in it
Growth → Scale (migrate when):
├── Traffic exceeds a single server's capacity
├── You need formal SLAs (99.9% uptime)
├── You have an ops team (or budget to hire one)
├── Cost optimization of >$500/month justifies the migration
└── Compliance or regulation requires full control
Signs that you should NOT migrate (premature migration)
Do NOT migrate if:
├── "AWS is what serious companies use" → That's not a requirement
├── "We need Kubernetes" with 50 users → Extreme overkill
├── "We should be multi-region" with local traffic → Unnecessary
├── "The free tier has limits" → Are you reaching them?
└── "I want to learn AWS in production" → Learn on LocalStack, not with real money
Premature migration is one of the most costly mistakes in startups: weeks of engineering work to migrate to infra you don't need. That time could have been invested in improving the product.
Migration Patterns by Stage
Pattern 1: Railway → VPS with Docker
When: Traffic exceeds the Railway plan, or you need more control (custom networking, persistent volumes, SSH access).
# Step 1: Your app already has a Dockerfile (Railway uses it)
# No code change — just hosting
# Step 2: Provision a VPS
# DigitalOcean, Linode, or Hetzner ($12-48/month)
# Step 3: Setup on the VPS
ssh root@your-vps
apt update && apt install docker.io docker-compose-plugin
git clone your-repo
cp .env.production .env
docker compose up -d
# Step 4: Domain and SSL
# Caddy as a reverse proxy (auto-SSL)
Effort: 2-4 hours. Risk: low (same Docker container).
Pattern 2: VPS → AWS (Lambda + S3)
When: You need specific AWS services (S3 for storage, Lambda for event-driven processing, SageMaker for models).
# Your code with an abstraction layer (Module 6)
import os
ENVIRONMENT = os.environ.get("ENVIRONMENT", "local")
def get_storage_client():
"""Return a storage client based on the environment."""
import boto3
if ENVIRONMENT == "local":
return boto3.client("s3", endpoint_url="http://localhost:4566")
else:
return boto3.client("s3") # Real AWS
Effort: 1-2 weeks. Risk: medium (new services, IAM, networking).
Pattern 3: Managed → Hybrid (Container + Lambda)
When: Your main API runs well on managed, but you need asynchronous batch processing that doesn't fit in the request/response cycle.
Before (all on Railway):
User → Railway (FastAPI) → processes everything synchronously
After (hybrid):
User → Railway (FastAPI) → immediate response
→ SQS → Lambda → batch processing
→ S3 → result available
Effort: 1 week. Risk: low-medium (adds complexity, but Railway keeps running).
The "Don't Migrate Until It Hurts" Rule
The principle
Migrate deployment strategy when the current one causes you real pain — not anticipated pain.
Real pain:
├── "The service goes down 2 times/week due to memory limits"
├── "Requests time out because the VPS can't handle the traffic"
├── "The Railway bill is $200/month and a VPS would do the same for $48"
└── "Compliance forces us to have the data on our own server"
Anticipated pain (don't migrate for this):
├── "Someday we'll have millions of users"
├── "Serious companies use AWS"
├── "I don't want growth to catch us off guard"
└── "My friend migrated and it went well"
Premature optimization kills startups
The time you spend migrating to AWS is time you don't spend improving your product. If your product doesn't have product-market fit, the infrastructure is irrelevant. First validate, then optimize.
Time lost on premature migration:
├── Learning AWS/IAM/Lambda: 20-40 hrs
├── Migrating code and CI/CD: 10-20 hrs
├── Testing and debugging: 10-20 hrs
├── Documentation and runbooks: 5-10 hrs
├── Total: 45-90 hrs
Things you could do in 45-90 hrs:
├── Interview 30 users
├── Implement 5 new features
├── Improve 100 prompts
├── Reduce inference latency 50%
└── Launch 3 product experiments
Decision Matrix by Stage
Quick template
| Criterion | MVP | Growth | Scale |
|---|---|---|---|
| Priority #1 | Iteration speed | Stability | Reliability |
| Priority #2 | Minimal cost | Controlled scalability | Operational efficiency |
| Typical strategy | Managed | Managed/Local | Self-hosted/Hybrid |
| Infrastructure | Railway free | Railway Pro / VPS | AWS / Multi-region |
| Monitoring | UptimeRobot | Sentry + logs | Full observability |
| Team ops | 0 (the dev does it) | 0.5 (dev spends partial time) | 1+ (dedicated) |
| SLA | "best effort" | 99% informal | 99.9% formal |
| Recovery | "re-deploy" | "manual rollback" | "automated rollback" |
Troubleshooting
Problem 1: "My manager wants AWS from day 1"
Solution: Present numbers. "Railway costs $0/month at MVP and gets us online in 2 hours. AWS costs $200+/month (including my setup time) and takes 2 weeks. I propose Railway for the MVP, with a documented migration path to AWS if we validate the product."
Problem 2: "I migrated prematurely and now everything is more complex"
Solution: Evaluate whether you can simplify. If you migrated to AWS but only use EC2 (no Lambda, S3, SageMaker), a VPS with Docker Compose does the same with less complexity. Reverse migration (simplifying) is also a valid option.
Problem 3: "I don't know if I'm in MVP or Growth"
Solution: Ask yourself: "Does anyone complain if my service goes down for 1 hour?" If the answer is nobody (or just you), you're in MVP. If real users complain, you're in Growth.
Hands-On Exercises
Exercise 1: Identify your stage
Classify your current project (or one you know) as MVP, Growth, or Scale. Justify it with real metrics.
See solution
Example:
Project: Q&A app about internal documentation
Stage: MVP → Growth (transition)
Evidence:
- Users: 45 active (we went from 10 two months ago)
- Traffic: ~800 req/day (growing 20%/month)
- Team: 1 developer
- Downtime impact: Medium (support teams use it daily)
- Budget: $0 current (Railway free tier)
Diagnosis: We're in the MVP → Growth transition
- We already have users who depend on the service
- The free tier is still enough but we're at 70% of the limit
- We need health checks and basic monitoring
Plan: Migrate to Railway Pro ($5/month) and add UptimeRobot.
Don't migrate to AWS — there's no justification yet.
Exercise 2: 12-month migration plan
Create a 12-month timeline for your project, indicating in which month you would do each migration (if applicable) and why.
See solution
Timeline: Documentation RAG app
Months 1-3 (MVP):
Deployment: Railway free tier
Trigger to migrate: Free tier limits
Months 4-6 (Growth early):
Deployment: Railway Pro ($5/month)
Add: Redis cache, health checks
Trigger to migrate: >200 users or >5K req/day
Months 7-9 (Growth):
Deployment: VPS Docker Compose ($24/month)
Add: Monitoring (UptimeRobot + Sentry), CI/CD
Trigger to migrate: >500 concurrent users or need for AWS services
Months 10-12 (Growth → Scale):
Evaluation: Do we need AWS?
If yes: Migration with LocalStack (Modules 4-6 of this guide)
If no: Stay on the VPS, optimize
Add: Load balancing if there are peaks
Key: Each migration has a measurable trigger, not an arbitrary date.
Exercise 3: "Premature optimization" calculation
Your team wants to migrate to AWS now (at MVP stage). Calculate: (a) hours of work to migrate, (b) value of those hours in product improvements, (c) when the migration would have positive ROI.
See solution
(a) Hours to migrate to AWS:
- Learning Lambda + API Gateway + IAM: 15 hrs
- Configuring CI/CD for AWS: 8 hrs
- Migrating code and testing: 12 hrs
- Documenting: 5 hrs
Total: 40 hrs
(b) Alternative value (40 hrs of improvements):
- 15 user interviews
- 3 new features
- Reduce latency 30% with prompt optimization
- Implement caching (30% savings in API costs)
(c) Migration ROI:
Railway Pro: $20/month
AWS Lambda: $5/month (at our volume)
Savings: $15/month
Hours invested: 40 hrs × $50/hr = $2,000
Break-even: $2,000 / $15 = 133 months = 11 YEARS
Conclusion: Migrating to AWS does NOT have ROI at MVP.
Migrate only when Railway causes real pain.
Exercise 4: "Real pain" checklist
Create a checklist of 5 real-pain signs that would justify migrating from your current strategy. Be specific with metrics.
See solution
## Migration checklist: Railway → VPS/AWS
Migrate when AT LEAST 2 of these are met:
- [ ] Memory limit reached (>90% of the plan's 512MB)
- [ ] Requests time out >5% of the total (cold starts or CPU limit)
- [ ] Railway bill > $50/month (a VPS would do the same for $24)
- [ ] Feature blocked by the platform (e.g.: WebSockets, volumes)
- [ ] Compliance requires data control (SOC2, HIPAA)
Do NOT migrate if:
- Only one sign is met (optimize first)
- The sign is anticipated, not current
- You don't have time to do the migration well (>20 hrs)
Summary
- The 3 stages (MVP, Growth, Scale) have fundamentally different deployment priorities.
- MVP: Speed above all. Managed platforms (Railway/Render). Zero ops.
- Growth: Stability + controlled scalability. Docker Compose on a VPS or managed pro.
- Scale: Reliability + efficiency. AWS, hybrid, or self-hosted with an ops team.
- Don't migrate prematurely. Premature migration is one of the most costly mistakes in startups.
- Migrate when there's real pain (metrics, not feelings): downtime, limits reached, excessive costs.
- Document migration triggers with specific metrics in your decision matrix.
- The ROI of migrating is almost never positive at MVP. Time is better invested in the product.
Additional Resources
- The Twelve-Factor App — Principles for cloud-native apps that ease migration between stages
- Startup CTO's Handbook — Guide for CTOs on infrastructure decisions
- Choose Boring Technology — Classic essay on why to choose boring tech
- The Pragmatic Engineer — Blog on engineering and infrastructure decisions
- Running in Production Podcast — Real cases of deployment in production
- Railway Blog — Scaling Stories — Scaling stories on Railway