Amazon ECS
Deploy Stategraph on AWS ECS Fargate with a complete, production-ready infrastructure stack using Terraform. This guide uses the official Stategraph ECS Terraform module for a simple, maintainable deployment.
Prerequisites
Before deploying Stategraph on ECS, ensure you have:
- Terraform 1.0+ installed
- AWS CLI 2.0+ configured with credentials
- AWS Account with appropriate permissions
- Existing VPC with private and public subnets (or use the complete example to create one)
- ACM certificate for HTTPS
- Domain name for the application
- Access to the Stategraph server image — it's distributed privately so we can make sure your team has the support it needs; reach out and we'll get you set up
Architecture Overview
Stategraph on ECS uses a managed, AWS-native architecture:
Internet
│
▼
Application Load Balancer (HTTPS:443)
│
▼
ECS Service (Fargate Tasks in Private Subnets)
│
├─▶ RDS PostgreSQL (Multi-AZ)
├─▶ Secrets Manager (Credentials)
└─▶ CloudWatch Logs (Monitoring)
What the module creates:
- ECS cluster and service (Fargate launch type)
- Application Load Balancer with HTTPS listener
- RDS PostgreSQL database (Multi-AZ by default)
- Security groups (ALB, ECS, RDS)
- IAM roles for ECS tasks
- Secrets Manager secrets for credentials
- CloudWatch Log Group for container logs
- Auto Scaling policies (optional)
What you must provide:
- VPC and subnets
- ACM certificate for HTTPS
- Domain name
Quick Start
1. Request ACM Certificate
Before deploying, create an SSL certificate in AWS Certificate Manager:
# Request certificate for your domain
aws acm request-certificate \
--domain-name stategraph.example.com \
--validation-method DNS \
--region us-east-1
# Note the CertificateArn from the output
Follow the AWS Console instructions to validate the certificate via DNS. This typically takes 5-10 minutes.
2. Create Terraform Configuration
Create a new directory and a main.tf file:
mkdir stategraph-ecs && cd stategraph-ecs
# main.tf
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# Network configuration (use your existing VPC)
vpc_id = "vpc-xxxxx"
private_subnet_ids = ["subnet-xxxxx", "subnet-yyyyy"]
public_subnet_ids = ["subnet-aaaaa", "subnet-bbbbb"]
# Domain and certificate
domain_name = "stategraph.example.com"
certificate_arn = "arn:aws:acm:us-east-1:123456789012:certificate/xxxxx"
# Environment
environment = "production"
# Tags (optional)
tags = {
Project = "Stategraph"
ManagedBy = "Terraform"
}
}
output "alb_dns_name" {
description = "Load balancer DNS - create a CNAME record pointing your domain here"
value = module.stategraph.alb_dns_name
}
output "database_endpoint" {
description = "RDS database endpoint"
value = module.stategraph.database_endpoint
sensitive = true
}
3. Initialize Terraform
terraform init
4. Review the Plan
terraform plan
This will show all the resources that Terraform will create.
5. Deploy
terraform apply
Deployment takes approximately 10-15 minutes.
6. Configure DNS
After deployment, create a DNS record pointing your domain to the ALB:
# Get the ALB DNS name
terraform output alb_dns_name
# Create a CNAME record in your DNS provider:
# Name: stategraph.example.com
# Type: CNAME
# Value: <alb-dns-name>
Or use a Route53 alias record:
# Get the ALB zone ID for Route53 alias
terraform output -raw alb_zone_id
7. Access Stategraph
After DNS propagation (5-10 minutes), access Stategraph at:
https://stategraph.example.com
Cookie Security
Stategraph derives cookie security from the configured URL (
STATEGRAPH_UI_BASE):
https://URLs → cookies are set with theSecureflag (recommended for production)http://URLs → cookies are set without theSecureflagThe ECS module sets this to
https://<domain_name>by default. Ensure thedomain_namevariable matches your certificate and DNS.
Configuration Options
Required Variables
| Variable | Description | Example |
|---|---|---|
vpc_id |
VPC ID where resources will be created | vpc-xxxxx |
private_subnet_ids |
Private subnet IDs for ECS and RDS | ["subnet-xxxxx", "subnet-yyyyy"] |
public_subnet_ids |
Public subnet IDs for ALB | ["subnet-aaaaa", "subnet-bbbbb"] |
domain_name |
Domain name for the application | stategraph.example.com |
certificate_arn |
ACM certificate ARN for HTTPS | arn:aws:acm:... |
Optional Variables (Common Settings)
| Variable | Description | Default |
|---|---|---|
environment |
Environment name | production |
ecs_task_cpu |
ECS task CPU units | 1024 |
ecs_task_memory |
ECS task memory (MB) | 2048 |
ecs_desired_count |
Number of ECS tasks | 2 |
enable_autoscaling |
Enable ECS autoscaling | true |
database_instance_class |
RDS instance type | db.t3.medium |
database_multi_az |
Enable Multi-AZ for RDS | true |
stategraph_image |
Docker image | <stategraph-server-image>:latest |
For a complete list of variables, see the module documentation included with your private module access, or reach out and we'll walk you through it.
Using an Existing VPC
If you already have a VPC with public and private subnets, simply reference them in your configuration:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# Reference your existing VPC
vpc_id = "vpc-0123456789abcdef0"
private_subnet_ids = ["subnet-aaa", "subnet-bbb"] # ECS tasks and RDS
public_subnet_ids = ["subnet-ccc", "subnet-ddd"] # ALB
# ... other required variables
}
VPC Requirements:
- At least 2 private subnets in different availability zones (for ECS and RDS)
- At least 2 public subnets in different availability zones (for ALB)
- NAT Gateway or NAT instances for private subnet internet access
- DNS hostnames enabled
Creating a New VPC
If you need to create a VPC, use the terraform-aws-modules/vpc module. A complete working example is included with your private module access — reach out if you don't have it yet.
Example with VPC creation:
module "vpc" {
source = "terraform-aws-modules/vpc/aws"
version = "~> 5.0"
name = "stategraph-vpc"
cidr = "10.0.0.0/16"
azs = ["us-east-1a", "us-east-1b", "us-east-1c"]
private_subnets = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
public_subnets = ["10.0.101.0/24", "10.0.102.0/24", "10.0.103.0/24"]
enable_nat_gateway = true
enable_dns_hostnames = true
}
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
vpc_id = module.vpc.vpc_id
private_subnet_ids = module.vpc.private_subnets
public_subnet_ids = module.vpc.public_subnets
# ... other variables
}
Using External PostgreSQL
If you have an existing PostgreSQL database, set create_database = false and provide connection details:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# ... other required variables
create_database = false
external_database_host = "postgres.example.com"
external_database_port = 5432
external_database_name = "stategraph"
external_database_username = var.database_username # Use variables for sensitive data
external_database_password = var.database_password
}
Requirements:
- PostgreSQL 13+ (17.x recommended)
- Network connectivity from ECS tasks (configure security groups)
- SSL/TLS support recommended
Authentication
Enable OAuth authentication with Google or OIDC:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# ... other required variables
oauth_enabled = true
oauth_provider = "google" # or "oidc"
oauth_client_id = var.oauth_client_id
oauth_client_secret = var.oauth_client_secret
# For OIDC provider:
# oauth_issuer_url = "https://accounts.google.com"
}
OAuth Redirect URI — the path is /oauth2/{provider}/callback:
https://stategraph.example.com/oauth2/google/callback # for Google
https://stategraph.example.com/oauth2/oidc/callback # for OIDC
Configure this callback URL in your OAuth provider settings.
Important: Store OAuth credentials securely using Terraform variables (create a terraform.tfvars file and add it to .gitignore):
# terraform.tfvars (do not commit)
oauth_client_id = "your-client-id"
oauth_client_secret = "your-client-secret"
For detailed OAuth configuration, see the Authentication guide.
Enable cost estimation
Cost analysis is off by default. The pricing service ships inside the server image; turn it on by
setting STATEGRAPH_COST_ENABLED=true on the server container. Set it in the task definition
so cost survives task replacements and rolling deployments. The bundled pricing service runs in the
same container, so STATEGRAPH_PRICING_SERVICE_URL already defaults to http://localhost:8090 —
set it only to point at an external pricing service.
Add it to the server container's environment block in the task definition:
"containerDefinitions": [
{
"name": "stategraph",
"environment": [
{ "name": "STATEGRAPH_COST_ENABLED", "value": "true" }
]
}
]
On first boot the pricing service loads the price book into the cloud_pricing database in the
background, so the server and UI stay available immediately. Use a managed or volume-backed
PostgreSQL so cloud_pricing has durable storage. See Cost Setup for
verification, refresh cadence, and air-gapped installs.
Health Checks
Stategraph provides two health check endpoints for ALB and ECS configuration:
| Endpoint | Purpose | Available |
|---|---|---|
/health/live |
Liveness probe — returns 200 as long as nginx is running | Immediately on startup |
/health/ready |
Readiness probe — returns 200 when the backend is ready | After database migrations complete |
The module configures these automatically. During container startup, database migrations run before the backend starts. The /health/live endpoint remains available throughout, while /health/ready will return 502 until migrations are complete.
For detailed configuration options, see the Health Checks reference.
Scaling
Auto-Scaling (Enabled by Default)
The module configures ECS autoscaling based on CPU and memory utilization:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# ... other variables
enable_autoscaling = true
ecs_min_count = 1
ecs_desired_count = 2
ecs_max_count = 4
autoscaling_cpu_threshold = 70 # Scale when CPU > 70%
autoscaling_memory_threshold = 80 # Scale when memory > 80%
}
Manual Scaling
To scale manually (or for development), disable autoscaling:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# ... other variables
enable_autoscaling = false
ecs_desired_count = 3 # Fixed count
}
Vertical Scaling
Increase task resources for more demanding workloads:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.0.0" # module source provided when you get access: https://stategraph.com/contact
# ... other variables
ecs_task_cpu = 2048 # 2 vCPU
ecs_task_memory = 4096 # 4 GB
}
Upgrading
Update Stategraph Version
- Update the image tag in your configuration:
module "stategraph" {
# ... other variables
stategraph_image = "<stategraph-server-image>:1.2.0" # image URL provided when you get access: https://stategraph.com/contact
}
- Apply the change:
terraform apply
ECS will perform a rolling deployment with zero downtime.
Update Module Version
- Update the module reference:
module "stategraph" {
source = "<stategraph-ecs-module>?ref=v1.1.0" # module source provided when you get access: https://stategraph.com/contact
# ...
}
- Reinitialize and apply:
terraform init -upgrade
terraform plan
terraform apply
Monitoring
View Container Logs
# Get the log group name from Terraform
aws logs tail $(terraform output -raw cloudwatch_log_group_name) --follow
# Filter by error level
aws logs tail /ecs/stategraph-production --filter-pattern "ERROR"
View ECS Service Status
# Get cluster and service names from Terraform
aws ecs describe-services \
--cluster $(terraform output -raw ecs_cluster_name) \
--services $(terraform output -raw ecs_service_name)
CloudWatch Metrics
The module automatically enables Container Insights for enhanced monitoring. View metrics in the CloudWatch Console under Container Insights > ECS Clusters.
Key Metrics:
- CPUUtilization: Percentage of allocated CPU used
- MemoryUtilization: Percentage of allocated memory used
- TargetResponseTime: ALB target response time
- HealthyHostCount: Number of healthy tasks
- RequestCount: Number of requests to ALB
Database Credentials
Access database credentials from Secrets Manager:
aws secretsmanager get-secret-value \
--secret-id $(terraform output -raw database_secret_arn) \
--query SecretString --output text | jq -r '.password'
Complete Example
For a complete, working example that includes VPC creation and all optional features, see the examples/complete directory included with your private module access. Reach out if you need access.
Module Documentation
Detailed module documentation — including all variables, outputs, advanced configuration options, and examples — is distributed privately along with the module. Reach out through our contact page and we'll get you set up with access.
Next Steps
- Set up Velocity — parallel plan and apply for Terraform
- Enable cost estimation — surface cost in your terraform plan output
- Set up authentication
- Perform gap analysis on AWS resources