Environment Strategy
Last updated: 2026-03-27 Decision owners: Joe, CC
Current State: Single Environment ("dev")
We run a single AWS environment that serves production traffic at app.nquiry.ai. It is named "dev" in all Terraform resources (invapp-dev-*) but is production in every functional sense:
- Terraform environment:
environments/dev/ - Resource prefix:
invapp-dev(cluster, service, ECR repo, ALB, RDS, etc.) - State backend:
s3://invapp-terraform-state-760007728097keydev/terraform.tfstate - Domain:
app.nquiry.aivia Route53 + CloudFront + ALB - ECS:
invapp-dev-cluster/invapp-dev-app-service(1 task, 512 CPU / 1024 MB) - RDS:
invapp-dev-postgres, single-AZ,db.t3.micro, deletion protection ON - Redis:
cache.t3.micro, single node - WAF: Bot control in count (log-only) mode
- CloudTrail: Data events disabled (cost savings)
- CloudFront Basic Auth: Currently enabled (pre-launch gate)
There is no staging environment. Local development runs via npm run dev against a local PostgreSQL instance (or tunneled RDS).
Why "dev" is actually prod
The naming is a historical artifact. When infrastructure was first provisioned, we started with "dev" expecting to add staging/prod later. Since we are a one-person team with no paying users yet, the single environment has been sufficient. All real data (test scenarios, demo investigations) lives here.
Gate 1: Rename dev to prod
Trigger: Before first paying customer or public launch.
What changes
- Create
infrastructure/terraform/environments/prod/main.tfwith identical module configuration - Resource prefix becomes
invapp-prod - Migrate state:
terraform state mvor freshterraform importfor all resources - Update CI/CD env vars in GitHub Actions secrets:
ECR_REPOSITORY:invapp-dev-app->invapp-prod-appECS_CLUSTER:invapp-dev-cluster->invapp-prod-clusterECS_SERVICE:invapp-dev-app-service->invapp-prod-app-service
- Update CloudFront Basic Auth: disable (
enable_basic_auth = false) - Consider enabling:
- WAF bot control in
blockmode - CloudTrail data events
- Multi-AZ RDS (
enable_multi_az = true) - Larger instance sizes if load warrants
- WAF bot control in
What stays the same
- Single environment (no staging yet)
- Same AWS account
- Same domain (
app.nquiry.ai) - Same deployment flow (push to main -> deploy)
- Local dev unchanged (
npm run dev)
What we explicitly skip
- No staging environment (cost, complexity, team size)
- No blue-green or canary deployments
- No separate database for staging
Gate 2: Add Staging
Trigger: When real users are on the platform and we need a pre-prod validation gate (e.g., multiple team members, customer-impacting changes need soak testing).
What changes
- Create
infrastructure/terraform/environments/staging/main.tf - Resource prefix:
invapp-staging - Staging domain:
staging.nquir.aior similar - Deployment flow becomes:
main-> staging (auto) -> prod (manual promotion or auto after soak) - Staging gets its own RDS, Redis, ECS cluster (smaller instances)
- Staging shares Cognito user pool or gets its own (TBD based on testing needs)
Cost estimate
Roughly doubles AWS spend. Current baseline is low (t3.micro everything), so staging would add ~$50-80/month for the minimal footprint.
Decision Rationale
| Factor | Decision |
|---|---|
| Team size | 1 developer + AI agents. No need for environment isolation between team members. |
| User base | Pre-launch. No paying customers yet. Downtime risk is acceptable. |
| Cost | Every duplicated environment doubles infrastructure spend for no current benefit. |
| Complexity | Managing state across environments adds operational burden with no payoff at this scale. |
| Speed | Single environment means faster iteration. No promotion gates to slow down shipping. |
This is a deliberate, documented choice -- not an oversight. We will add environments when the risk/benefit equation changes.