fix(edxapp): source Granian concurrency per install from stack config - #5636
Open
blarghmatey wants to merge 2 commits into
Open
fix(edxapp): source Granian concurrency per install from stack config#5636blarghmatey wants to merge 2 commits into
blarghmatey wants to merge 2 commits into
Conversation
k8s_resources.py is shared by mitx, mitx-staging, mitxonline and xpro, so a concurrency value written there is written for all four at once. That is how the 2026-08-26 CMS regression reached mitxonline Studio: defaults sized against a 0.25 rps authoring instance dropped per-pod backpressure 8x, pods pinned at 16 active connections, and APISIX p95/p99 hit the 60s ceiling while Django spans stayed at 0.2-1.1s. #5607 restored the holding pins in shared code, which also un-does mitx and mitx-staging CMS on their next deploy -- both have run 1 worker x 8 threads since 2026-08-24T17:18Z with a peak blocking queue of 5 and 0, and zero container restarts over 3 days. Verified by preview: on origin/main, mitx.Production shows a 4th Deployment update reinserting --runtime-mode mt and workers 1->2 on CMS; with this change it does not. Both webapps now read edxapp:k8s_granian.{lms,cms}, required rather than defaulted, alongside k8s_replicas and k8s_resources. An install's concurrency is readable in its own stack file, and a new install has to state a value rather than inherit whatever was last written into shared code. mitx and mitx-staging take 1 x 8 / backpressure 16; mitxonline and xpro take the pre-overhaul 2 x 32 / backpressure 64. Every value matches what is live as of 2026-08-28. pulumi preview: mitxonline.Production 238 unchanged, 0 changes; mitx.Production and mitx-staging.Production show no Granian arg diff. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HgKWpUsasvv1pLGBDhyBo5
Contributor
There was a problem hiding this comment.
Pull request overview
Moves Open edX LMS and CMS Granian concurrency from shared code into per-stack configuration, preserving install-specific production capacity.
Changes:
- Requires separate LMS and CMS Granian settings.
- Configures all 12 edxapp stacks with appropriate concurrency.
- Documents the rollout and operational rationale.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
Pulumi.xpro.QA.yaml |
Adds xpro QA concurrency pins. |
Pulumi.xpro.Production.yaml |
Adds xpro production concurrency pins. |
Pulumi.xpro.CI.yaml |
Adds xpro CI concurrency pins. |
Pulumi.mitxonline.QA.yaml |
Adds mitxonline QA concurrency pins. |
Pulumi.mitxonline.Production.yaml |
Preserves production holding pins. |
Pulumi.mitxonline.CI.yaml |
Adds mitxonline CI concurrency pins. |
Pulumi.mitx.QA.yaml |
Adds CMS settings alongside LMS settings. |
Pulumi.mitx.Production.yaml |
Preserves tuned mitx concurrency. |
Pulumi.mitx.CI.yaml |
Adds tuned CMS concurrency. |
Pulumi.mitx-staging.QA.yaml |
Adds tuned CMS concurrency. |
Pulumi.mitx-staging.Production.yaml |
Preserves tuned staging concurrency. |
Pulumi.mitx-staging.CI.yaml |
Adds tuned CMS concurrency. |
k8s_resources.py |
Sources both webapps’ Granian configuration per stack. |
granian-configuration-overhaul.md |
Records the per-install design and rollout status. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
The comment was copied from mitxonline, so it attributed mitxonline's measurements -- LMS p99 17.7, the 2026-08-26 CMS backpressure saturation -- to xpro, which has neither. xpro-openedx still runs the hand-rolled pre-OLApplicationK8s Deployments and emits no granian_* series at all, so its pins are retained for want of a measurement, not because of one. Values unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HgKWpUsasvv1pLGBDhyBo5
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 are the relevant tickets?
tk-stage-3-adopt-new-granian-defaults-for-mitxonlin-16de40, projectwp-granian-configuration-overhaul-expose-blocking-t-3debc2. Follows #5607.Description (What does this do?)
k8s_resources.pyis shared by four Open edX installs (mitx, mitx-staging, mitxonline, xpro), so a concurrency value written there is written for all four at once. That is how the 2026-08-26 CMS regression reached mitxonline Studio. Per #5607's post-mortem, the rollout cut per-pod backpressure 8x (2 workers x 64 to 1 x 16), APISIX p95/p99 reached the 60s histogram ceiling, and Tempo placed 30-59s ahead of a Django span that itself took 0.2-1.1s.granian_connections_activefor mitxonline CMS pinned at 15-16 through that window and has been back at 50 (p99, 3d) since the rollback.#5607 mitigated it by restoring the holding pins in shared code. That is correct for mitxonline and collateral damage for the other two: mitx and mitx-staging CMS have run 1 worker x 8 threads since 2026-08-24T17:18Z and would be dragged back to 2 workers on their next deploy.
Both webapps now read
edxapp:k8s_granian.{lms,cms}from stack config, alongside the existingk8s_replicasandk8s_resources. The key is required rather than defaulted, so an install's concurrency is readable in its own stack file and a new install has to state a value rather than inherit whatever was last written into shared code.mitx,mitx-stagingmitxonline,xproEvery value matches what is live as of 2026-08-28, read from the container args on
applications-productionandresidential-production.How can this be tested?
pulumi previewagainst each Production stack:238 unchanged, zero changes. The holding pins are preserved exactly.--disable-prefetch, from fix(edxapp): add --disable-prefetch to all celery workers to fix KEDA scaling #5598) plus 2 RDS alarm deletions. No Granian arg diff. Previewing the same stack againstorigin/maininstead shows a 4th Deployment update, on CMS:[7]: "1" => "2"(workers),--runtime-mode mtreinserted, blocking-threads8 => 32, backpressure16 => 64, workers-max-rss1843 => 921. That is the collateral revert this PR prevents.--disable-prefetch, 2 RDS alarm deletions. No Granian arg diff.--blocking-threads 32 --backpressure 64. Its 127 changes are dominated by the pre-existing ~6-month drift on that stack (it still runs the hand-rolledxpro-production-edxapp-{cms,lms}-webappDeployments), unrelated to this PR.pre-commit runover the changed files passes, mypy included.Additional notes
mitx CMS does touch its backpressure ceiling of 16, for 52 minutes out of 3 days (
granian_connections_active >= 16, 1m resolution), with a peakgranian_blocking_queueof 5 and zero container restarts. mitx-staging CMS: 33 minutes, peak queue 0. Healthy, but the ceiling is the signal to watch if authoring traffic on either grows.Raising mitxonline off the holding pins still needs concurrency sizing that accounts for burst shape, plus a scaling or alerting signal that sees connection saturation -- CPU and request rate did not.
🤖 Generated with Claude Code
https://claude.ai/code/session_01HgKWpUsasvv1pLGBDhyBo5