Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.shipfastai.dev/llms.txt

Use this file to discover all available pages before exploring further.

Shipfastai’s Enterprise tier includes a complete set of Terraform modules that provision a production-ready AWS environment. The infrastructure runs your backend and frontend as containerized services on ECS Fargate, backed by a managed RDS PostgreSQL database, and fronted by an Application Load Balancer with TLS termination. This page explains what is provisioned, how to deploy it, and how to run database migrations once your services are running.
The Terraform infrastructure described on this page is included exclusively in the Enterprise tier. If you are on the Basic or Pro tier, refer to the Railway & Vercel guide instead.
Estimated AWS costs for a small production workload (2 Fargate tasks each for backend and frontend, a db.t3.medium RDS instance, one NAT Gateway, and an ALB) are roughly $50–100 per month. Costs scale with traffic, task count, and data transfer. Use the AWS Pricing Calculator to estimate your specific configuration before deploying.

Prerequisites

Before running Terraform, make sure you have the following installed and configured on your machine:
  • AWS CLI configured with credentials that have sufficient IAM permissions to create VPCs, ECS clusters, RDS instances, ECR repositories, and IAM roles. Run aws sts get-caller-identity to verify your credentials.
  • Terraform 1.5 or later. Run terraform version to check.
  • Docker, for building and pushing your backend and frontend images to ECR.

What the Terraform modules provision

The modules in products/enterprise/infra/terraform/ create the following AWS resources:
ResourceDescription
VPCIsolated network with public and private subnets across two Availability Zones, a NAT Gateway, and an Internet Gateway
ECS clusterFargate cluster with Container Insights enabled; runs the backend API service and the frontend web service
ECR repositoriesTwo private image registries — one for the backend, one for the frontend — with image scanning on push
RDS PostgreSQLPostgreSQL 15 instance (db.t3.medium by default) in private subnets, with Multi-AZ enabled in production, automated backups, and deletion protection
Application Load BalancerInternet-facing ALB in public subnets; routes /api traffic to the backend target group and all other traffic to the frontend target group
Auto ScalingCPU-based auto scaling for both the API service (2–10 tasks) and the web service (2–6 tasks)
CloudWatchLog groups for both ECS services, plus alarms for high CPU and error rates
Secrets ManagerA single secret that holds sensitive runtime variables injected into ECS task definitions

Initialize and deploy

1

Navigate to the Terraform directory

cd products/enterprise/infra/terraform
2

Create your tfvars file

Copy the example variables file and fill in your values:
cp terraform.tfvars.example terraform.tfvars
Open terraform.tfvars and set at minimum:
aws_region   = "us-east-1"
environment  = "production"
app_name     = "shipfastai-enterprise"
db_password  = "a-strong-random-password"
domain_name  = "api.yourdomain.com"
You can also override instance sizes, task counts, and auto-scaling limits. Refer to variables.tf for the full list of inputs and their defaults.
3

Initialize Terraform

terraform init
This downloads the AWS provider and configures the S3 backend for remote state. Before running this command, create an S3 bucket for Terraform state and update the backend "s3" block in main.tf with your bucket name and key.
4

Preview the plan

terraform plan
Review the output carefully. Terraform will list every resource it intends to create. Verify that the region, instance sizes, and CIDR blocks match your expectations before proceeding.
5

Apply the configuration

terraform apply
Type yes when prompted. The apply takes approximately 10–15 minutes, with the RDS instance taking the longest to become available. When it completes, Terraform prints the ALB DNS name, ECR repository URLs, and RDS endpoint as outputs.

Pushing Docker images

After terraform apply succeeds, build your images locally and push them to the ECR repositories Terraform created. The repository URLs are available in the Terraform outputs.
# Authenticate Docker with ECR
aws ecr get-login-password --region us-east-1 | \
  docker login --username AWS --password-stdin \
  <your-account-id>.dkr.ecr.us-east-1.amazonaws.com

# Build and push the backend image
docker build -t shipfastai-backend ./products/enterprise/backend
docker tag shipfastai-backend:latest \
  <backend-ecr-url>:latest
docker push <backend-ecr-url>:latest

# Build and push the frontend image
docker build -t shipfastai-frontend ./products/enterprise/frontend
docker tag shipfastai-frontend:latest \
  <frontend-ecr-url>:latest
docker push <frontend-ecr-url>:latest
Replace <backend-ecr-url> and <frontend-ecr-url> with the values from the backend_ecr_url and frontend_ecr_url Terraform outputs. After pushing, force a new deployment so ECS pulls the updated images:
aws ecs update-service \
  --cluster shipfastai-enterprise-cluster \
  --service shipfastai-enterprise-api \
  --force-new-deployment

aws ecs update-service \
  --cluster shipfastai-enterprise-cluster \
  --service shipfastai-enterprise-web \
  --force-new-deployment

Running migrations on AWS

You need to run Alembic migrations whenever you deploy a new schema version. There are two common approaches. Run migrations as a one-off ECS task. Use the AWS CLI to start a task that overrides the container command with the Alembic upgrade command:
aws ecs run-task \
  --cluster shipfastai-enterprise-cluster \
  --task-definition shipfastai-enterprise-api \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[<private-subnet-id>],securityGroups=[<ecs-tasks-sg-id>],assignPublicIp=DISABLED}" \
  --overrides '{"containerOverrides":[{"name":"api","command":["alembic","upgrade","head"]}]}'
Retrieve the private subnet IDs and security group ID from the Terraform outputs (private_subnet_ids and the ECS tasks security group). Use a bastion host for interactive access. If you prefer to connect directly to the database, launch a small EC2 instance in a public subnet within the same VPC, configure its security group to allow inbound SSH, and add a rule to the RDS security group allowing connections from the bastion instance on port 5432. You can then SSH in and run Alembic from there. For automated deployments, the ECS task approach is recommended because it requires no additional infrastructure and uses the same Docker image as your running service.