Skip to content

AWS ops console guide

Quick map for operating LastVet staging and prod on AWS. Infrastructure is defined in infra/.

Account: 525382240840
Region: us-west-2 (Oregon). Pin this in the console top bar. Almost everything lives here.


Sign in

Console console.aws.amazon.com
IAM sign-in URL https://525382240840.signin.aws.amazon.com/console
CLI credentials infra/.aws.credentials.local (gitignored). See infra/.aws.credentials.local.example.

IAM user ryan-worker needs a console password for browser access (IAM → Users → Security credentials → Enable console access). Access keys work for CLI only.

Load CLI credentials:

cd last.vet-api
source ./infra/scripts/load-aws-env.sh
aws sts get-caller-identity

Console Home setup

Widgets (done)

  • AWS Health
  • Cost and usage

Starred services (done)

ECS, RDS, CloudWatch, Secrets Manager, EC2 Load Balancers, ECR, VPC, EFS, S3, Resource Groups & Tag Editor.

Resource groups (done)

Terraform tags every resource:

Tag key Values
Project lastvet
Environment staging, prod, or bootstrap
ManagedBy terraform

Suggested groups:

Group name Query
lastvet-all Project = lastvet
lastvet-prod Project = lastvet AND Environment = prod
lastvet-staging Project = lastvet AND Environment = staging

Create or edit: Resource Groups & Tag EditorCreate resource group.

My Applications tile (Console Home)

Adds a LastVet API tile on Console Home. myApplications does not pick an existing Resource Group on step 1. You name the app first, then on step 2 bulk-add resources by tag (same tags Terraform already applies).

Step 1 — Specify application details (your current screen)

  1. Application name: LastVet API (prod) or LastVet API (staging)
  2. Description (optional): ECS API, RDS, ALB, secrets
  3. Leave Tags and Attribute groups empty.
  4. Click Next.

Step 2 — Add resources

  1. Choose Automatically add resources using tags (not “Search and select resources”).
  2. Role: lastvet-myapplications-tag-sync (dedicated tag-sync role in IAM). Do not use ECS roles (lastvet-*-ecs-exec, lastvet-*-ecs-task) or AWSServiceRoleFor* entries.

If the role is missing from the dropdown, refresh the page. Create it in IAM with trust principal resource-groups.amazonaws.com and the ResourceGroupsTaggingAPITagUntagSupportedResources managed policy if needed. 3. Tag key: Environment 4. Tag value: prod (for prod tile) or staging (for staging tile)

For a single tile with both envs, use Tag key Project, Tag value lastvet instead.

  1. Click Preview resources and confirm you see ECS, RDS, ALB, VPC, etc.
  2. Check I acknowledge that Group Lifecycle Events will be enabled.
  3. Click NextCreate application.

After create

  • myApplications (left sidebar) lists the app.
  • Console HomeApplications widget shows the tile once the app exists (add the widget via Actions → Add widgets if missing).
  • Open the app → Resources tab for drill-down to ECS, RDS, ALB.

If step 2 has no tag options or Preview is empty: confirm region is us-west-2 and resources are tagged (Project=lastvet, Environment=prod|staging). Resource Groups you created are separate; myApplications uses tag-sync, not a Resource Group dropdown.

If “Search and select resources” is the only option: turn on AWS Resource Explorer in us-west-2, or use tag-sync above (preferred for LastVet).


Resource map

Production (api.last.vet)

What Console path / name
Load balancer EC2 → Load Balancers → lastvet-prod-alb
ECS cluster / service ECS → lastvet-prod-clusterlastvet-prod-api
Logs CloudWatch → /ecs/lastvet-prod-api (streams api/api/<task-id>)
Database RDS → lastvet-prod-postgres
App secrets Secrets Manager → lastvet-prod/app
DB URLs lastvet-prod/rds/master, lastvet-prod/rds/lastvet_app
Container images ECR → lastvet-prod-api
Uploads EFS → lastvet-prod-uploads
Network VPC → lastvet-prod-vpc
ALB DNS lastvet-prod-alb-2104741467.us-west-2.elb.amazonaws.com

Staging (api-staging.last.vet)

What Name
ECS lastvet-staging-cluster / lastvet-staging-api
Logs /ecs/lastvet-staging-api
RDS lastvet-staging-postgres
Secrets lastvet-staging/app, lastvet-staging/rds/*
ECR lastvet-staging-api
ALB lastvet-staging-alb-869788297.us-west-2.elb.amazonaws.com

Terraform bootstrap

What Name
State bucket S3 → lastvet-tfstate-525382240840
State lock DynamoDB → lastvet-tf-locks

Terraform outputs (ALB DNS, ECR URL, RDS endpoint):

cd infra/environments/prod && terraform output
cd infra/environments/staging && terraform output

Day-to-day ops

Is the API up?

curl -sS https://api.last.vet/health
curl -sS https://api-staging.last.vet/health

ECS: Running count = Desired count = 1, deployment status PRIMARY.

Prod health bookmark:

https://us-west-2.console.aws.amazon.com/ecs/v2/clusters/lastvet-prod-cluster/services/lastvet-prod-api/health

Logs and errors

CloudWatch → log group /ecs/lastvet-{env}-api → latest stream.
ECS service → Events tab for deployment and health-check failures.

App config / secret rotation

  1. Secrets Manager → lastvet-{env}/app → edit JSON.
  2. ECS → service → UpdateForce new deployment.

Deploy new API image

source ./infra/scripts/load-aws-env.sh
ECR_URL=$(cd infra/environments/prod && terraform output -raw ecr_repository_url)
aws ecr get-login-password --region us-west-2 | docker login --username AWS --password-stdin "$ECR_URL"
docker build --platform linux/amd64 -t "${ECR_URL}:latest" .
docker push "${ECR_URL}:latest"

Then ECS → Force new deployment (or update container_image in terraform.tfvars and apply).

Database migrations (one-off only)

Production never auto-migrates on boot. Migrations run via ECS one-off task:

./infra/scripts/run-ecs-db-setup.sh prod
./infra/scripts/run-ecs-db-setup.sh staging

RDS is private. No direct psql from a laptop unless you add bastion or temporarily open the security group.

RLS / app-role verification

Proves the API uses lastvet_app (not RDS master) and RLS is enforced:

./infra/scripts/run-ecs-verify-db-role.sh prod
./infra/scripts/run-ecs-verify-db-role.sh staging

Expect "pass": true and current_user: "lastvet_app".

Rollback to Railway (prod, 48–72h window)

Point Cloudflare api.last.vet CNAME back to Railway. Railway prod (last.vet-api + postgres-lastvet-prod) stays online as the rollback net. Do not decommission until the window closes.


Not on AWS

System Role
Cloudflare DNS (api.last.vet, api-staging.last.vet), SSL, provider Pages
Railway Prod rollback target; staging API may still exist on Railway
Cloudflare Pages dev.provider.last.vet (staging provider portal)