Crossposted from https://manuchandrasekhar.com/posts/2026/02-01-stategraph-aws-deployment/
If you're following the Infrastructure as Code space, Josh Pollara is a name you've likely encountered. While I haven't personally tried terrateam, I've been following what he and his co-founders have been building. One of the most common questions I get from customers using Terraform is around state management. Most AWS deployments default to S3 as a backend (with DynamoDB for locking in pre-1.10 Terraform versions). The idea of exploring another mechanism in the state management space intrigued me, especially with promises around faster plans through their upcoming Velocity feature. The First Principles page is worth reading, and this stood out:
Infrastructure is a graph. Store it as a graph.
I started with their backend implementation using the Docker Compose quickstart. I'll save the nuances of the transactional nature of state changes and metadata tracking for a future post.
Dev setup with Docker(Finch) compose
The Docker Compose setup was straightforward for local development. Initially, I struggled with configuring this as a Terraform state backend. Stategraph implements the HTTP backend protocol, requiring an endpoint and authentication mechanism. My confusion was primarily because I skipped the Creating an API key section in the quickstart guide.
The documentation could benefit from emphasizing the API key requirement earlier in the flow for users who might skip ahead (like me).
terraform {
backend "http" {
address = "http://myrest.api.com/foo"
username = "session"
password = "<your-api-key>"
}
}
Note that the user settings does give you an option to create a service account for CICD pipelines.
For security, avoid hardcoding credentials in your backend configuration. Use environment variables instead. The environment variables TF_HTTP_USERNAME and TF_HTTP_PASSWORD are your best bet here.
terraform {
backend "http" {
address = "http://localhost:8080/api/v1/states/backend/<group-id>"
}
}
Understanding the group-id
The group-id is a unique identifier that Stategraph assigns to organize and locate your Terraform state files. Think of it as a folder ID or address where your infrastructure state is stored. In HCP Terraform terms, it's similar to a workspace or project identifier. This is the first time I noticed the stategraph CLI.
For MacOs users, the installation is as simple as:
brew tap stategraph/stategraph
brew install stategraph
Generate the group-id using these commands (detailed in Create a state):
# Get your tenant ID
stategraph user tenants list
# Create a new state (returns group_id)
stategraph states create --tenant <tenant_id> --name "stategraph-demo"
Response example:
{
"id": "...",
"name": "stategraph-demo",
"group_id": "550e8434-t59b-56d4-a716-329055440073",
"workspace": "default"
}
Initial Web Interface Impressions
The Stategraph web interface impressed me with its clean design. Even with just two state files in my initial setup, the interface clearly prioritized giving visibility into individual resources within state files and across multiple states. The screenshots below show the different views available:
State Overview:
Control Plan Insights:
State Metadata:
Deployment configuration using Terraform
The local Docker Compose setup was just the beginning. I wanted to deploy Stategraph into a production-ready environment using ECS with an external PostgreSQL database on RDS. After several iterations and troubleshooting various configuration issues, I have a working deployment using Stategraph server version 0.1.16.
The complete Terraform configuration I used is available at: Stategraph ECS Infrastructure
Architecture Overview
The infrastructure configuration creates a Stategraph environment with:
-
ECS EC2: Runs the Stategraph container (
ghcr.io/stategraph/stategraph-server) - CloudFront: CDN for HTTPS termination and global distribution
- Application Load Balancer: Routes traffic to ECS tasks
- RDS PostgreSQL 17: Database for state storage and transaction history
- VPC: Isolated network with public/private subnets
- Secrets Manager: Secure storage for database password and OAuth secrets
Prerequisites
Before deploying, you'll need:
- AWS credentials configured (via environment variables, IAM roles, or AWS profiles)
- Terraform >= 1.0
-
Google OAuth Application - Set up at Google Cloud Console
- Create OAuth 2.0 Client ID for web application
- Configure authorized redirect URIs
Key Configuration
Required Variables
variable "google_oauth_client_id" {
description = "Google OAuth Client ID"
type = string
}
variable "google_oauth_client_secret" {
description = "Google OAuth Client Secret"
type = string
sensitive = true
}
Container Configuration
Stategraph runs on port 8180 internally with nginx as a reverse proxy on port 8080. Key environment variables include:
environment = [
{
name = "STATEGRAPH_UI_BASE"
value = local.stategraph_url
},
{
name = "STATEGRAPH_PORT"
value = "8180"
},
{
name = "STATEGRAPH_OAUTH_TYPE"
value = "oidc"
},
{
name = "STATEGRAPH_OAUTH_OIDC_ISSUER_URL"
value = "https://accounts.google.com"
}
]
secrets = [
{
name = "DB_PASS"
valueFrom = aws_secretsmanager_secret.db_password.arn
},
{
name = "STATEGRAPH_OAUTH_CLIENT_SECRET"
valueFrom = aws_secretsmanager_secret.google_client_secret.arn
}
]
Note: I used
oidcas the OAuth type instead of
Deployment
- Initialize and Deploy:
Follow the standard Terraform workflow:
terraform init
terraform plan
terraform apply
- Configure OAuth:
After deployment, configure your Google OAuth application with the redirect URI:
terraform output google_oauth_redirect_uri
The callback URL will be in the format: https://abc.cloudfront.net/oauth2/oidc/callback
- Access Stategraph:
Retrieve the Stategraph URL from Terraform outputs:
# Get the HTTPS URL (via CloudFront)
terraform output stategraph_url
Stategraph UI
Once deployed, the initial setup flow includes several steps.
-
Google Authentication (Note: I misconfigured
STATEGRAPH_OAUTH_DISPLAY_NAME- it should beGooglerather than the full message shown)
- Main Web Interface
State Migration
Obviously the next thing to do was migrate the state to Stategraph itself. For the Docker compose local development setup, I was copying and pasting without reading half of it. Now came the actual setup where I noticed the additional variables I need to keep in mind. You can generate an API KEY from the user settings and set these environment vars as you would need it for stategraph CLI command.
export STATEGRAPH_API_BASE="<stategragh_url>"
export STATEGRAPH_API_KEY="<api_key>"
Once done, retrieve the tenant id
stategraph user tenants list
And create the state container. This is where I think they should have a glossary of terms in reference to stategraph. We as a community have made some words difficult to use in many other contexts.
stategraph states create --tenant <tenant_id> --name "stategraph-ecs"
{
"created_at": "2026-02-02T05:34:21Z",
"group_id": "<group_id>",
"id": "...",
"name": "stategraph-ecs",
"workspace": "default"
}
Update the Terraform block to use the same backend. I did backup the state before doing it though the configuration didn't have a lot of components and I could have manually cleaned them up if I messed it up.
Run terraform init
Initializing the backend...
Do you want to copy existing state to the new backend?
Pre-existing state was found while migrating the previous "local" backend to the
newly configured "http" backend. No existing state was found in the newly
configured "http" backend. Do you want to copy this state to the new "http"
backend? Enter "yes" to copy and "no" to start with an empty state.
Enter a value:
Enter yes. Here goes nothing..
Successfully configured the backend "http"! Terraform will automatically
use this backend unless the backend configuration changes.
Initializing provider plugins...
- Reusing previous version of hashicorp/random from the dependency lock file
- Reusing previous version of hashicorp/aws from the dependency lock file
- Using previously-installed hashicorp/aws v6.28.0
- Using previously-installed hashicorp/random v3.8.1
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
Run a plan to check everything is ok.
random_password.db_password[0]: Refreshing state... [id=none]
random_id.secret_suffix: Refreshing state... [id=vKBxqA]
data.aws_availability_zones.available: Reading...
aws_secretsmanager_secret.db_password: Refreshing state... [id=arn:aws:secretsmanager:us-east-1:############:secret:stategraph-db-password-bca071a8-MgkbzS]
aws_ecs_cluster.main: Refreshing state... [id=arn:aws:ecs:us-east-1:############:cluster/stategraph]
data.aws_ami.ecs_optimized: Reading...
....
aws_cloudfront_distribution.stategraph: Refreshing state... [id=E2CDRVGI3JY6BT]
aws_db_instance.postgres: Refreshing state... [id=db-QRFNQQCUDBMW4HXCODVUHWKTXE]
aws_ecs_task_definition.stategraph: Refreshing state... [id=stategraph]
aws_ecs_service.stategraph: Refreshing state... [id=arn:aws:ecs:us-east-1:############:service/stategraph/stategraph]
No changes. Your infrastructure matches the configuration.
Terraform has compared your real infrastructure against your configuration and found no differences,
so no changes are needed.
The Resource count on the pane looks off by 2.
If you dig into the inspect state , you have the 48 resources listed.
State Overview
I still need to dive deep into what some of these data points mean, but they are there for you if you want them. The view is scoped to the state you were looking at; in my case the stategraph deployment itself. The page does give you quick jump off points to Search and Inventory.
The dependency blast radius and Top resource types !!
Now what are Orphaned candidates ? :thinkingface:
Inventory
If you select one of the resource types from state overview, it takes you to the inventory of currently managed resources. This is sweet !
Querying Resources
The interface already gives you some sample queries and it worked out well with my stategraph infrastructure here. I am not going to draw parallels just yet, the query interface along with the examples were a nice a touch.
For your recurring queries :
I did feel like a kid during Christmas with a candy box all for himself ;)
Monitoring and Troubleshooting
Monitor your deployment through:
-
CloudWatch Logs:
/ecs/stategraphlog group - ECS Service Events: Check for deployment issues
- Target Group Health: Monitor ALB target group status
Common issues to watch for:
- Database connectivity (security groups, RDS availability)
- OAuth configuration (redirect URIs, client secrets)
- Load balancer health checks
Deployment Challenges
I encountered couple of challenges during my ECS Terraform route:
Version Compatibility: Stategraph iterates releases frequently (almost daily). I struggled to get ALB health checks passing on versions before 0.1.15 due to ECS task failures during database migration tasks, even though database connectivity was confirmed.
Compute Choice: I initially started with Fargate but switched to EC2 instances for some troubleshooting.
Conclusion
Stategraph brings a fresh perspective to infrastructure state management that complement the existing ecosystem well. The visual interface and query capabilities will offer valuable insights that practitioners will appreciate, especially in organizations with a huge number of workloads targeting multiple platforms.
If you are looking to get started , the Terraform configuration here should give you a fully stable infrastructure once you have a Google OAuth client ID. Or swap out the authentication mechanism based on your preference.
Here are the key resources I referenced during configuration:
- Stategraph Documentation
- Stategraph OAuth Setup
- Stategraph Environment Variables - Comprehensive list of configuration options (I appreciate having all environment variables documented in one place!)
- Google Cloud Console - for OAuth setup
There are so many components to this along with the orchestration side using Terrateam which I am excited to try. More of it in the next set of posts.



















Top comments (0)