diff --git a/app/cloudbuild.yaml b/app/cloudbuild.yaml index 4e820ffbfb..0814b2f307 100644 --- a/app/cloudbuild.yaml +++ b/app/cloudbuild.yaml @@ -83,15 +83,29 @@ steps: # Measurements behind this: #10812. - '--min-instances' - '0' + # max=1, with concurrency 80 below: one nginx is the whole capacity, and + # that is plenty — static files answer in milliseconds, memory sits at + # 15 MiB p99 of 512Mi, and the only requests that ever held a slot for + # long were bot requests proxied to the API while the API cold-started (~11 s; + # api/cloudbuild.yaml explains why that is gone). Under the old 15-slot + # limit one forged-UA burst on 2026-09-09 filled the instance and started + # two more, each a 0.26 s cold start nobody needed (50 AUTOSCALING starts + # in the ten days to 2026-09-10). A second instance was never for + # capacity; with max=1 a burst queues here for milliseconds instead of + # spreading over instances. Owner decision 2026-09-11: one instance per + # service in both projects. - '--max-instances' - - '3' + - '1' - '--port' - '8080' - '--execution-environment' - 'gen2' - '--cpu-throttling' + # 80, not 15: nginx serves static files and proxies the rest, and the API + # behind it caps its own work at 40 in flight. 15 was a default that + # turned every crawler burst into a scale-out (see --max-instances above). - '--concurrency' - - '15' + - '80' # Deploy WITHOUT routing traffic: the smoke step probes this revision on # its tag URL first, and only the promote step below shifts traffic — so # a broken nginx.conf never serves visitors or crawlers, not even between diff --git a/changelog.d/app-single-instance.md b/changelog.d/app-single-instance.md new file mode 100644 index 0000000000..b2c204b41e --- /dev/null +++ b/changelog.d/app-single-instance.md @@ -0,0 +1,11 @@ +### Changed + +- **`anyplot-app` runs as a single instance with concurrency 80 (was max 3, + concurrency 15).** A static nginx never needed a second instance for capacity — + its files answer in milliseconds and it sits at 15 MiB of memory — yet every + crawler burst filled the 15 slots and started one or two more instances (50 + AUTOSCALING starts in the ten days to 2026-09-10), because nginx holds a + proxied bot request open for as long as the API takes to answer. With the API + on one warm instance those waits are milliseconds, and one nginx with 80 slots + absorbs the burst without a cold start. `min-instances` stays 0; the API behind + it caps its own work at 40 in flight. (#11829)