Skip to content

feat(converter): ship as a .zip with a free-tier kill switch - #73

Merged
bradwindy merged 4 commits into
mainfrom
feat-converter-zip-kill-switch
Oct 24, 2026
Merged

bradwindy merged 4 commits into
mainfrom
feat-converter-zip-kill-switch

Conversation

@bradwindy

Copy link
Copy Markdown
Owner

Part 1 of moving NZ Images to Cloudflare Free plus a free-tier AWS converter.

What changes

  • The converter is a python3.13 arm64 .zip built by converter/Makefile (Pillow's manylinux_2_28_aarch64 wheel, 22 MB). There's no container image any more, so the ECR repo and its storage cost (~$0.06/month, no free tier left on this account) go away. CI's deploy job imports the built package on arm64 Python 3.13 and fails if JP2 or TIFF decoding is missing. infra/bootstrap.yaml keeps only the artefact bucket.

  • New ConverterGuardFunction (guard/) is a kill switch. It sets the converter's reserved concurrency to 0 in two cases:

    • when the spike alarm fires (now >100 calls in 5 minutes, previously >100 an hour)
    • when month-to-date Lambda usage reaches 320k GB-s, 800k requests or 20k converter calls. The 20k cap keeps data transfer under the free 100 GB.

    An hourly run switches it back on once usage and the alarm are clear. Every switch is emailed to the cost-alarm topic.

  • Converter timeout goes from 60 s to 120 s, plus a 90 s whole-download deadline. NDHA streams some masters at under 1 MB/s, and FL73848659 (45.8 MB, 7356×5010) hit the 60 s timeout with nothing logged.

Deploy notes

  • PackageType Image -> Zip replaces the converter function, so its Function URL changes. The Swift API picks the new URL up through !GetAtt in the same deploy.
  • After merge: redeploy nzimageapi-bootstrap (the repo is Retain, so it is left behind), then delete the nzimageapi/jp2converter repo.

Tested

  • pytest: converter 34 passed, guard 14 passed.
  • sam validate --lint passes. sam build of both functions works and the converter build includes libopenjp2 and libtiff.
  • PutFunctionConcurrency(0) and DeleteFunctionConcurrency both work on this account, whose concurrency quota is 10 (checked live, then restored).

🤖 Generated with Claude Code

bradwindy and others added 4 commits October 24, 2026 17:51
- Converter is now a python3.13 arm64 .zip built by converter/Makefile
  (Pillow's manylinux_2_28_aarch64 wheel), so the ECR repo and its storage
  cost go away. CI imports the built package on arm64 to prove JP2/TIFF
  decoding is present. infra/bootstrap.yaml keeps only the artefact bucket.
- New ConverterGuardFunction (guard/) switches the converter off by setting
  its reserved concurrency to 0 when the 5-minute spike alarm fires, or when
  month-to-date Lambda usage nears the always-free allowance, and back on
  hourly once usage and the alarm are clear. Every switch is emailed.
- Function timeout 60 -> 120 s plus a 90 s whole-download deadline: NDHA
  streams some masters at under 1 MB/s, and FL73848659 (45.8 MB) timed out
  silently.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Hourly run only re-enables once the spike alarm has been quiet for
  GuardSpikeCooldownHours (6): throttled calls aren't invocations, so the
  alarm clears within minutes and couldn't tell a flood had stopped.
- download_image reads with read1 so a trickling source can't hold one
  read past the deadline.
- converter/Makefile fails the build if the wheel lacks OpenJPEG/libtiff.
- Guard timeout 60 s, documented limits, style fixes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…bscription

- Hourly run switches the converter off while the spike alarm is in ALARM,
  covering a failed SNS-triggered run (the alarm won't notify again).
- SNS FilterPolicy so only the spike alarm entering ALARM invokes the guard.
- Reference the alarm name instead of repeating it.
- Converter timeout 180 s: a download can end ~125 s (90 s deadline plus
  one 35 s blocking read), leaving time to decode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- GuardMaxGbSeconds 250,000: about two hours of worst-case converter burn
  below the 400,000 free, since a flood of slow calls can stay under the
  spike threshold and only the hourly check catches it.
- At most 3 redirects, so connection setup can't outlast the timeout.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bradwindy
bradwindy merged commit c599d75 into main Oct 24, 2026
3 checks passed
@bradwindy
bradwindy deleted the feat-converter-zip-kill-switch branch October 24, 2026 05:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant