From 172066860ac6335d161a953ab15927b20e3cc608 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Sun, 30 Aug 2026 00:51:39 +0200 Subject: [PATCH 1/3] infra: scale anyplot-app to zero The frontend service held a permanently warm Cloud Run instance for ~EUR 8.30/month while 99.56 % of the billed time was idle. It is a static nginx image whose cold start is ~0.26 s (p50 258 ms), so the warm instance bought almost nothing. A 7-day request trace at one-minute resolution shows the service is busy in 60 % of all minutes and the longest gap between requests is 11 minutes, against Cloud Run's ~15 minute idle window. The instance is therefore reclaimed rarely if ever, and time to first byte for visitors and crawlers stays where it is. anyplot-api deliberately keeps min-instances=1: its cold start is ~11.6 s and its traffic does leave gaps beyond 15 minutes. The live service was updated in the same breath; this pins the value so the next deploy does not restore it. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61 --- CHANGELOG.md | 10 ++++++++++ app/cloudbuild.yaml | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf9a083bd1..bd4e91de10 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,16 @@ aggregate instead: an italic *Catalog* line at the end of the version section an ## [Unreleased] +### Changed + +- **`anyplot-app` scales to zero** — the frontend service ran a permanently warm + instance for ~EUR 8.30/month while 99.56 % of the paid time was idle. It is a static + nginx image that boots in ~0.26 s, and a 7-day request trace at one-minute resolution + shows the longest gap between requests is 11 minutes, against Cloud Run's ~15 minute + idle window — so the instance is in practice never reclaimed and visitors keep the + same time to first byte. `anyplot-api` keeps `min-instances=1`: its cold start is + ~11.6 s and its traffic does leave gaps over 15 minutes. + ## [3.2.0] — 2026-08-29 — Findable by assistants anyplot 3.2 makes the catalogue findable by assistants, not only legible to them. The sister diff --git a/app/cloudbuild.yaml b/app/cloudbuild.yaml index d749fb7219..44bd0a66d7 100644 --- a/app/cloudbuild.yaml +++ b/app/cloudbuild.yaml @@ -53,8 +53,13 @@ steps: - '1' - '--timeout' - '60' + # Scale to zero. This service is a static nginx that boots in ~0.26 s, and + # measured traffic never leaves it idle long enough to be reclaimed: over + # 7 days the longest gap between requests was 11 min, against Cloud Run's + # ~15 min idle window. A warm instance cost ~EUR 8.30/month for 99.56 % + # idle time. The API keeps min-instances=1 — its cold start is ~11.6 s. - '--min-instances' - - '1' + - '0' - '--max-instances' - '3' - '--port' From 59dd570c8d99c4c07a8de7e9d568b99a9151c1ef Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Sun, 30 Aug 2026 01:02:13 +0200 Subject: [PATCH 2/3] review: trim the inline rationale, fix changelog style Copilot review on #10812: - percent style: the file writes "28%", not "28 %" - the header requires a PR reference on every [Unreleased] bullet - the inline cloudbuild comment carried a 7-day traffic trace and a euro figure that will go stale; keep the durable reasoning there and leave the measurements in the PR Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61 --- CHANGELOG.md | 4 ++-- app/cloudbuild.yaml | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd4e91de10..d7ec65fd59 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,12 +29,12 @@ aggregate instead: an italic *Catalog* line at the end of the version section an ### Changed - **`anyplot-app` scales to zero** — the frontend service ran a permanently warm - instance for ~EUR 8.30/month while 99.56 % of the paid time was idle. It is a static + instance for ~EUR 8.30/month while 99.56% of the paid time was idle. It is a static nginx image that boots in ~0.26 s, and a 7-day request trace at one-minute resolution shows the longest gap between requests is 11 minutes, against Cloud Run's ~15 minute idle window — so the instance is in practice never reclaimed and visitors keep the same time to first byte. `anyplot-api` keeps `min-instances=1`: its cold start is - ~11.6 s and its traffic does leave gaps over 15 minutes. + ~11.6 s and its traffic does leave gaps over 15 minutes. (#10812) ## [3.2.0] — 2026-08-29 — Findable by assistants diff --git a/app/cloudbuild.yaml b/app/cloudbuild.yaml index 44bd0a66d7..83914a107f 100644 --- a/app/cloudbuild.yaml +++ b/app/cloudbuild.yaml @@ -53,11 +53,11 @@ steps: - '1' - '--timeout' - '60' - # Scale to zero. This service is a static nginx that boots in ~0.26 s, and - # measured traffic never leaves it idle long enough to be reclaimed: over - # 7 days the longest gap between requests was 11 min, against Cloud Run's - # ~15 min idle window. A warm instance cost ~EUR 8.30/month for 99.56 % - # idle time. The API keeps min-instances=1 — its cold start is ~11.6 s. + # Scale to zero: this is a static nginx that boots in a fraction of a + # second, and its traffic is dense enough that Cloud Run rarely reclaims + # the instance anyway, so a warm one bought almost nothing. The API keeps + # min-instances=1 — its cold start is orders of magnitude larger. + # Measurements behind this: #10812. - '--min-instances' - '0' - '--max-instances' From 1379a843b92613aac1c344f9ceda6b9b4797b318 Mon Sep 17 00:00:00 2001 From: Markus Neusinger <2921697+MarkusNeusinger@users.noreply.github.com> Date: Sun, 30 Aug 2026 01:06:17 +0200 Subject: [PATCH 3/3] review: hyphenate "15-minute idle window" Compound adjective, consistent with "one-minute resolution" in the same bullet. Copilot review on #10812. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_011qccek5dba72zaizDBGK61 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7ec65fd59..c4f04f8c12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,7 +31,7 @@ aggregate instead: an italic *Catalog* line at the end of the version section an - **`anyplot-app` scales to zero** — the frontend service ran a permanently warm instance for ~EUR 8.30/month while 99.56% of the paid time was idle. It is a static nginx image that boots in ~0.26 s, and a 7-day request trace at one-minute resolution - shows the longest gap between requests is 11 minutes, against Cloud Run's ~15 minute + shows the longest gap between requests is 11 minutes, against Cloud Run's ~15-minute idle window — so the instance is in practice never reclaimed and visitors keep the same time to first byte. `anyplot-api` keeps `min-instances=1`: its cold start is ~11.6 s and its traffic does leave gaps over 15 minutes. (#10812)