ARM64 (Graviton) Migration Assessment
This note captures what it would take to move the stack from amd64 to arm64 (AWS Graviton), and where the real risk is. Everything here is current-state research, not a plan that's been started.
Current State
Nothing in this repo pins amd64 explicitly except one place - most of the stack is on amd64 today simply because that's Fargate's default and nobody has set it otherwise:
infra/modules/ecs/main.tf'saws_ecs_task_definitionresources set noruntime_platformblock at all, so Fargate defaults toX86_64.docker-bake.hclsets noplatformsfor any target, sodocker buildx bakejust builds for the host builder's native architecture.infra/modules/tracker_restore_host/main.tf's AMI lookup explicitly filtersname = ["debian-13-amd64-*"]- this one is hardcoded.infra/modules/database(the self-managed Postgres/TimescaleDB/PostGIS EC2 host - not RDS) takes an explicitami_idwith no default; whatever's configured today is presumably an amd64 image, but the module itself doesn't pin an architecture.
Straightforward Part: Fargate Services and Jobs
Every application Dockerfile is already on an official, multi-arch base image, so there's no base-image blocker:
| File | Base image |
|---|---|
build/api/Dockerfile, services/docker/Dockerfile, build/dev/Dockerfile |
python:3.13-slim |
build/db/Dockerfile |
postgres:16-bookworm |
tracker-frontend-svelte/docker/*.Dockerfile, tracker-admin-svelte/docker/*.Dockerfile |
node:20-alpine, nginx:alpine |
pyproject.toml's dependencies with native extensions (psycopg, shapely/
geoalchemy2, pillow, orjson, argon2-cffi) all publish arm64 wheels on
PyPI - no expected native-build blockers there. Dragonfly's image is
confirmed multi-arch (Graviton is one of their own marketed use cases).
To move the Fargate side to arm64:
- Add
runtime_platform { cpu_architecture = "ARM64", operating_system_family = "LINUX" }to bothaws_ecs_task_definitionresources ininfra/modules/ecs/main.tf. - Add
platforms = ["linux/arm64"]to each target indocker-bake.hcl(or multi-platform["linux/amd64", "linux/arm64"]if local dev machines and CI/deploy need to stay on different architectures for a transition period). - Rebuild and push images, then apply - this is a normal image-tag rollout like any other deploy, fully reversible via a task-definition revision.
Graviton Fargate is typically ~20% cheaper than x86 at comparable or better performance, so this part is a fairly clean win on its own.
Needs Verification Before Trusting It
build/db/Dockerfileinstalls TimescaleDB and PostGIS from packagecloud and Debian apt repos forbookworm. Both generally publish arm64 packages, but this should be confirmed with an actual arm64 build of this image, not assumed.dadoum/anisette-v3-server(used directly incompose.ymlfor local dev, and mirrored into ECR for staging/prod perinfra/envs/*/main.tf'sanisetteservice) is a small third-party image. Whether it publishes an arm64 variant couldn't be checked from this environment - worth adocker manifest inspect dadoum/anisette-v3-serverbefore committing to this migration. If it's amd64-only, that one service needs either QEMU emulation (acceptable for a low-traffic auth helper) or a rebuilt/forked image.
The Real Risk: the Self-Managed Database Host
This is not Fargate, so it doesn't get the "just add a runtime_platform block" treatment:
infra/modules/tracker_restore_hostexplicitly filters its AMI todebian-13-amd64-*and defaults toinstance_type = "t3.medium"(an x86-only family).infra/modules/databaseprovisions the actual production/staging Postgres+TimescaleDB+PostGIS host the same way - a hand-bootstrapped EC2 instance (via thetracker-opsAnsible repo, not this one), not RDS.
Moving this to Graviton means: a new AMI, switching to a Graviton-compatible
instance family (e.g. t4g/m7g instead of t3/m5), and re-verifying
TimescaleDB, PostGIS, and pgBackRest all have working arm64 builds for that
exact OS release - on the actual database host, not a disposable container.
This is stateful infrastructure where a bad AMI or missing package isn't
fixed by rolling back a task definition revision.
Recommendation
Don't couple these two migrations. Do the Fargate/container side first - it's cheap, low-risk, and fully reversible. Treat the EC2 database host as a separate, later decision, tested in isolation (e.g. against a throwaway Graviton instance running the same bootstrap playbook) before ever pointing it at production data.
Suggested Evaluation Checklist
- Confirm
dadoum/anisette-v3-serverpublishes an arm64 image. - Build
build/db/Dockerfileforlinux/arm64and confirm TimescaleDB + PostGIS install cleanly. - Add
runtime_platform/platformsfor one low-traffic Fargate service first (e.g.mcp-diagnostics, since it's already an on-demand job, not a long-running service) and confirm it runs correctly. - Roll out to the rest of the Fargate services/jobs once (3) is proven.
- Only then evaluate the EC2 database host migration as its own project, tested against a disposable instance first.