Skip to content

Migrate to Strawberry / FastAPI / Mangum (final sibling: container + PynamoDB) #86

Description

@chrisbc

Summary

Migrate solvis-graphql-api from Graphene 3 / Flask / serverless-wsgi to Strawberry / FastAPI / Mangum — the 4th and final sibling, run last because it adds the two biggest deltas: a container (ECR) Lambda and a PynamoDB ORM.

Epic: GNS-Science/nshm-toshi-api#359
Runbook: nshm-toshi-api/docs/MIGRATION_RUNBOOK.md
Worked log: docs/MIGRATION_LOG.md (branch migrate/strawberry)
Owner: @chrisbc

Phase 0 inventory — done

Captured in docs/MIGRATION_LOG.md. Key findings (several easier than the runbook's §A4 framing):

  • PynamoDB is a single model — BinaryLargeObjectModel (5 attrs) already wrapped by a hand-written BinaryLargeObject class. Convert to pydantic + boto3 behind the unchanged wrapper API.
  • Container entry is the serverless-wsgi handler.py workaround → Mangum replaces it; update Dockerfile CMD + serverless image.command.
  • Repo already ships a cross-stage differential validator (ab_test/ + cli_ab_test, 9 query checks) → reuse as the Phase 5 validation tool and corpus seed.
  • moto-based tests already exist → no testcontainers.
  • Still on poetry; .yarnrc.yml lacks the age gate; both serverless-s3-local + serverless-dynamodb load at boot (runbook §4.7 risk); heavy container image (matplotlib/solvis/shapely).
  • Secrets posture = repo-level static AWS keys + single TEST env (the Model §4.2 caveat, not AWS_TEST/AWS_PROD).

Plan (tailored — full detail in the log)

  • Phase 0 — inventory, branch migrate/strawberry
  • poetry → uv via the dockerbash poetry2uv skill (running externally on the branch)
  • Phase 0 artifacts — legacy SDL baseline (guard stdout) + vendor the A/B query set as corpus
  • Phase 1 — FastAPI/Mangum + container entry swap; .yarnrc.yml age gate; drop serverless-wsgi
  • Phase 2 — PynamoDB→pydantic+boto3 (keep wrapper API); port ~25 graphene types to Strawberry at parity
  • Phase 3 — tests to Strawberry (keep moto); CI → -uv workflows; remove branches: filter
  • Phase 4 — container build/dep-install path; yarn resolutions hygiene; vuln bumps; image-size pass
  • Phase 5 — deploy to test; cli_ab_test prod-vs-new differential validation; promote + prod watch; file runbook feedback PR

Status

Phase 0 inventory complete; branch pushed and awaiting the external poetry2uv run before Phase 1 code begins.

Activity

  1. chrisbc commented on Jun 24, 2026

    @chrisbc
    MemberAuthor

    Migration engineering complete — stacked PRs #88–#94

    All phases implemented + verified; only the prod cutover (AWS creds + go-ahead) remains.

    Phase PR State
    0 — pre-flight (poetry→uv, SDL baseline, corpus incl. kororaa) #88 ✅
    1 — FastAPI/Mangum + container entry swap #89 ✅
    2a — PynamoDB → pydantic + boto3 (wrapper API kept) #90 ✅
    2b — schema port, SDL byte-identical #91 ✅
    3 — runtime resolvers, 11 differential-parity checks #92 ✅
    4 — deploy/CI/deps hardening (360MB image, pip-audit clean) #93 ✅
    5 — cutover plan (pre-staged) #94 🟡 deploy held

    Verified: SDL byte-identical to legacy; full surface runtime-equivalent (in-process differential harness caught real bugs — relay global-id, float defaults, coercion); amd64 container builds + handler imports in-image; no runtime vulns.

    Remaining (needs you): deploy to test → cli_ab_test prod-vs-test → promote → post-healthy legacy cleanup. See docs/PHASE5_CUTOVER.md.

  2. chrisbc commented on Jun 24, 2026

    @chrisbc
    MemberAuthor

    ✅ Merged to deploy-test + deployed to the TEST stage

    Combined PR #95 merged (one merge → one clean deploy, per runbook G7; #88–#94 landed via it). The deploy-aws-lambda run succeeded:

    • tests + ruff + mypy ✓
    • ECR container build + test-stage deploy ✓
    • deploy smoke query QueryRoot{about} ✓

    The Strawberry app is live on test — container packaging, Mangum entry, and the full schema verified in the real Lambda env.

    Folded in at merge: a CI fix (drop the follow_untyped_imports regression poetry2uv added + a SetOperationEnum type stub → whole package mypy-clean), and a rebase over 3 concurrent deploy-test commits (#81/#82/#84).

    Remaining (needs you — AWS creds + prod go-ahead)

    1. cli_ab_test WORK/ab.toml -A prod -B test -v — differential prod-vs-test (the built-in harness).
    2. Promote deploy-test → main (prod) with the pre-staged revert PR + ~30-min watch.
    3. Post-healthy legacy cleanup (delete graphene schema.py/Flask/handler.py, rename strawberry_schema.py → schema.py, drop legacy deps). See docs/PHASE5_CUTOVER.md.
  3. chrisbc commented on Jun 26, 2026

    @chrisbc
    MemberAuthor

    Done — migrated to Strawberry/FastAPI/Mangum and live in prod (2026-06-26, promote PR #97, merge 5ed85863).

    Tracked under epic GNS-Science/nshm-toshi-api#359 (item 4).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions