fix(deploy): prevent App Engine request starvation under burst load - #753
Merged
Conversation
Prod cycled between 0-1 instances and returned site-wide 500/503 with "Request was aborted after waiting too long to attempt to service your request." Requests died in the pending queue (blank instanceId, ~2ms latency), not in app code — App Engine never scaled out past one instance despite max_instances=10. Root cause: the scheduler had no visibility into real per-instance concurrency (gunicorn -w 4), so it kept routing bursts to a single saturated instance instead of spinning up more. min_instances=0 added cold-start pile-ups on top. - app.template.yaml: add max_concurrent_requests: 6 so the scheduler scales out before an instance saturates (2-worker headroom for bursts) - CD_production.yml: MIN_INSTANCES 0 -> 1 to kill cold-start pile-ups - CD_production.yml: gunicorn -w 4 -> -w 8 for more concurrency per F4 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Three App Engine scaling fixes to stop site-wide 500/503 outages under burst load:
app.template.yaml— addmax_concurrent_requests: 6CD_production.yml—MIN_INSTANCES0→1CD_production.yml— gunicorn-w 4→-w 8Why
Prod cycled between 0 and 1 instances and returned site-wide 500/503 — including
/and/health. Every failing request logged:Status 500/503, latency ~2ms, blank
instanceId= App Engine killed the request in the pending queue; it never reached app code. Not OOM (zero "Exceeded soft memory limit" lines), not a code crash (same-instance requests returned 200).Root cause: the scheduler had no visibility into real per-instance concurrency (gunicorn
-w 4), so under a burst (map UI firing many?f=json&limit=10000collection requests at once) it kept routing to a single saturated instance instead of scaling out towardmax_instances=10.min_instances=0added cold-start pile-ups.How the fixes address it
max_concurrent_requests: 6gives the scheduler an explicit per-instance ceiling → scales out before an instance saturates. Set below the 8 workers on purpose: 2-worker headroom absorbs bursts (safer than packing to 8).MIN_INSTANCES=1keeps one warm instance → no cold-start pile-ups.-w 8doubles concurrency per F4 (1GB) instance.Reviewer notes
KeyError: '@iot.id'500s seen in logs are not addressed here (unrelated per-item bug).🤖 Generated with Claude Code