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:

AppBuild contextRuntime
APIRepository root, apps/api/DockerfilePython 3.12 / FastAPI on port 8080
Webapps/web/React / Vite, served by nginx on port 8080
Docsapps/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.sh
  • https://api.staging.krawl.sh
  • https://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:

VariablePurpose
AWS_RELEASE_ROLE_ARNEnvironment-scoped GitHub OIDC role
AWS_RELEASE_CONFIGExact JSON release manifest with service, image and URL references
AWS_RELEASE_ENABLEDSet 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, and X-Krawl-Revision equal to the release SHA.
  • Web /release.json: matching revision and the expected api_url.
  • Docs /release.json: matching revision. The root redirects to /docs; the load balancer probes /docs for 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.

On this page