Deployment
AWS staging and production releases with Terraform, ECS, verified revisions, and rollback
Krawl uses an AWS release path for the API, web app, and docs. Fly is retired. The current release status records the evidence for each environment. Infrastructure creation and passing CI alone do not establish a production release.
Deployment layout
The repository is a monorepo with separate Docker images:
| App | Build context | Runtime |
|---|---|---|
| API | Repository root, apps/api/Dockerfile | Python 3.12 / FastAPI on port 8080 |
| Web | apps/web/ | React / Vite, served by nginx on port 8080 |
| Docs | apps/docs/ | Next.js standalone on port 3000 |
Terraform defines a separate ECS cluster per environment, immutable ECR repositories, an HTTPS Application Load Balancer, scoped IAM roles and CloudWatch logs. Services start with zero tasks; the release workflow activates them after infrastructure and DNS are ready. API, web and docs each run one task. No autoscaler is configured.
Staging has an isolated VPC, encrypted private RDS PostgreSQL 16 with seven-day backups, an AWS-managed database password and its own generated hash secret. The API task reads the current database password for each new physical connection. Secret values do not belong in GitHub variables, Terraform input files or release artifacts.
Prepare staging
Follow the repository's AWS runbook for the reviewed account, region, cost estimate, issued ACM certificate, remote state and exact Terraform plan. Only the staging hostnames should change during staging setup:
https://staging.krawl.shhttps://api.staging.krawl.shhttps://docs.staging.krawl.sh
Keep existing production DNS records and production data untouched. Configure
the GitHub environment aws-staging, restrict deployment branches to main,
and set these non-secret variables from the Terraform outputs:
| Variable | Purpose |
|---|---|
AWS_RELEASE_ROLE_ARN | Environment-scoped GitHub OIDC role |
AWS_RELEASE_CONFIG | Exact JSON release manifest with service, image and URL references |
AWS_RELEASE_ENABLED | Set true after infrastructure, certificate and DNS readiness |
Provider invocation permissions default off. Supplying AWS hosting access does not enable funded research or payment acceptance. Configure provider credentials through Secrets Manager and record the approved evaluation budget separately.
Release a reviewed commit
Run the Deploy AWS GitHub Actions workflow from main, select staging,
supply a full 40-character commit SHA and acknowledge the API maintenance window.
The exact SHA must have a successful push CI run on main. The workflow assumes
its environment role through OIDC; GitHub does not need long-lived AWS keys.
The workflow publishes missing images with immutable SHA tags, resolves their ECR digests, registers task definitions, and updates API, docs and web in order. Retries reuse existing image tags. The web image is built with the destination API origin; a new origin requires a new reviewed commit. Docs use the configured API origin for their MCP proxy.
API replacement can interrupt in-flight work. The single API task stops before its replacement starts, with a bounded shutdown period. Schedule a quiet maintenance window. Do not increase API task count until overlapping startup recovery, session ownership and rate limits support it.
Verify the deployed revision
A stable ECS service is only one check. The public endpoints must also agree with the requested source revision:
- API
/health: HTTP 200,status=ok,db=ok, andX-Krawl-Revisionequal to the release SHA. - Web
/release.json: matchingrevisionand the expectedapi_url. - Docs
/release.json: matchingrevision. The root redirects to/docs; the load balancer probes/docsfor HTTP 200.
Both AWS environments require an API key. Anonymous or unknown-key research requests must fail before execution. Separately check actual sign-in, key issuance, account isolation, exports and erasure using synthetic accounts. A synthetic report proves those storage and export paths; it does not prove research quality, paid provider execution or billing reconciliation.
Failure and rollback
The workflow saves an aws-{environment}-release-{sha} artifact containing
source revision, image digests, prior task definitions, task counts and rollback
outcomes. Task-registration failures record preparation_failed before services
change. Activation or health failures restore every touched service's prior task
and desired count, including zero-task bootstrap states.
Rollback preserves concurrent operator changes and reports unresolved outcomes
as failed_requires_operator. A failed release remains failed even if task
restoration succeeds. Confirm the prior public revision after restoration.
Task rollback does not undo database migrations or external effects.
CloudWatch logs retain 30 days under the infrastructure configuration. Review ECS events, target health, API database readiness and the saved release artifact when diagnosing a failure. Keep previous image digests available for recovery.
Production cutover
Production requires verified existing database and unchanged hash-secret references, verified network connectivity, and a continuity record. The current production module creates neither a database nor a replacement hash secret. Do not substitute staging data or rotate the hashing secret during migration; that would orphan existing API keys and result ownership.
The aws-production environment also requires AWS_PRODUCTION_DATA_VERIFIED,
AWS_STAGING_ACCEPTANCE_SHA for the exact release commit, and a repository
AWS_STAGING_ACCEPTANCE_URL. Complete the binding release gates, backup and
restore checks, funded critical flows and owner decisions before production DNS
cutover. See the release definition.
The previous Fly deployment guide is retained as historical material. Its credentials and commands are not the AWS release procedure.