The Startup Infrastructure Dilemma
Startups face a unique challenge: you need infrastructure that's robust enough for production, but lean enough to fit a seed-stage budget. Over-engineering wastes runway. Under-engineering creates technical debt that slows you down when you need to scale.
The sweet spot is an architecture that starts simple, costs little, and scales incrementally as your user base grows.
Stage 1: The MVP (0-1K Users)
At this stage, simplicity is king. Your stack should be:
- Compute: A single ECS Fargate service or a small EC2 instance
- Database: RDS PostgreSQL (db.t3.micro, free tier eligible)
- Storage: S3 for static assets and file uploads
- CDN: CloudFront for serving your frontend
- DNS: Route 53
Estimated monthly cost: $30-80
Key Principles
- Use managed services to minimize ops burden
- Deploy everything in a single region
- Use environment variables for configuration (no hardcoded values)
- Set up basic monitoring with CloudWatch alarms
The whole stage-1 footprint is small enough to express as a single Terraform module, which matters more than it looks: the day you need a second environment, you want it to be a variable change rather than an afternoon of clicking.
module "app" {
source = "./modules/service"
name = "api"
environment = "production"
cpu = 256 # 0.25 vCPU - genuinely enough at this stage
memory = 512
desired_count = 1
# Fargate Spot for everything non-critical: ~70% cheaper, and at one
# task you are already accepting a restart window.
capacity_provider = "FARGATE_SPOT"
db_instance_class = "db.t3.micro"
db_allocated_storage = 20
db_multi_az = false # single-AZ until revenue says otherwise
}Stage 2: Growth Mode (1K-50K Users)
As you gain traction, invest in reliability and performance:
- Compute: ECS Fargate with auto-scaling, or move to EKS if your team has Kubernetes experience
- Database: Upgrade RDS instance size, add read replicas
- Caching: ElastiCache (Redis) for sessions and frequent queries
- Queue: SQS for background job processing
- Monitoring: Add Datadog or Grafana Cloud for observability
Estimated monthly cost: $200-800
Key Principles
- Implement CI/CD with GitHub Actions + ECR + ECS deploy
- Add a staging environment that mirrors production
- Use Infrastructure as Code (Terraform or CDK) from this point forward
- Set up cost alerts and billing dashboards
Scale on the metric that reflects user pain. CPU is the default and it is usually the wrong one for a web API: a service can be at 30% CPU and still be queueing requests behind a slow dependency.
resource "aws_appautoscaling_policy" "requests_per_target" {
name = "api-rps"
service_namespace = "ecs"
scalable_dimension = "ecs:service:DesiredCount"
resource_id = "service/${var.cluster}/${var.service}"
policy_type = "TargetTrackingScaling"
target_tracking_scaling_policy_configuration {
target_value = 800 # requests per task per minute
predefined_metric_specification {
predefined_metric_type = "ALBRequestCountPerTarget"
resource_label = "${var.alb_suffix}/${var.tg_suffix}"
}
scale_in_cooldown = 300 # scale in slowly
scale_out_cooldown = 30 # scale out fast
}
}The asymmetric cooldowns are deliberate. Adding capacity late costs you an outage; removing it late costs you a few dollars.
Stage 3: Scaling (50K+ Users)
At this stage, you need horizontal scalability and fault tolerance:
- Compute: EKS with horizontal pod autoscaling
- Database: Aurora PostgreSQL with multi-AZ, or DynamoDB for high-throughput workloads
- Event-driven: EventBridge + Lambda for async workflows
- CDN: CloudFront with edge functions for personalization
- Multi-region: Begin planning for multi-region if you have global users
Estimated monthly cost: $2K-10K+
Key Principles
- Implement service mesh for observability and traffic management
- Use spot instances for non-critical workloads (60-70% savings)
- Implement fine-grained IAM policies and security groups
- Set up disaster recovery with cross-region backups
Knowing When to Move Between Stages
Stage boundaries are not user counts, whatever the headings above suggest. They are symptoms. Move up when you see them, and not before:
| Signal | What it means | Move to |
|---|---|---|
| Deploys need a maintenance window | Single task, no rolling capacity | Stage 2 autoscaling |
| p95 latency tracks database CPU | Read load exceeds one instance | Read replicas + cache |
| A background job blocks a web request | No async path exists | SQS + worker service |
| One team's deploy breaks another's service | Shared service, separate owners | Split services |
| Cost per user rises as users grow | Something scales linearly that should not | Profile before scaling |
That last row is the one worth watching. Healthy infrastructure gets cheaper per user over time. If yours is not, adding capacity converts a design problem into a larger bill.
Cost Optimization Strategies
1. Right-Size Your Resources
Most startups over-provision. Use AWS Compute Optimizer and Cost Explorer to identify waste.
2. Use Savings Plans
Once your usage patterns stabilize, commit to 1-year savings plans for 30-40% savings on compute. Commit to your trough, not your peak: unused commitment is pure loss, and burst capacity is what Spot is for.
3. Leverage Spot Instances
Use spot instances for development environments, CI/CD runners, and batch processing.
4. Clean Up Unused Resources
Set up automated scripts to identify and terminate unused EBS volumes, old snapshots, and idle load balancers. Unattached EBS volumes are the classic case: they survive the instance that created them and bill indefinitely.
# unattached volumes, oldest first, with monthly cost
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[].{ID:VolumeId,GB:Size,Created:CreateTime}' \
--output table5. Watch Data Transfer
Data transfer rarely appears in architecture reviews and regularly appears in bills. Cross-AZ traffic between a service and its database is billed in both directions, so a chatty service split across availability zones pays for its own conversation.
6. Monitor Continuously
Set up AWS Budgets with alerts. Review your bill weekly during growth phases.
Common Mistakes
- Choosing Kubernetes too early: ECS Fargate is simpler and cheaper for small teams
- Running dev environments 24/7: schedule them to shut down outside business hours
- Ignoring data transfer costs: these add up fast with multi-AZ and cross-region setups
- Not using IaC from the start: manual infrastructure becomes unmanageable quickly
- Buying reserved capacity before usage stabilizes: a one-year commitment made during a growth spike outlives the spike
When to Bring in Help
If your team is spending more time on infrastructure than on product, it's time to get help. At InfoDive Labs, we design cost-efficient AWS architectures for startups, from MVP to scale. On one recent cloud-native migration we cut infrastructure cost by 60% while moving the platform to 99.99% uptime, and a security and performance engagement for EZ Rankings reduced server costs by 40% alongside a 3x improvement in load times.