Fix v3/roles perf regression for regular users#5157
Merged
Conversation
PR #5094 (commit 0068461) reshaped readable_roles to filter via Space.where(...).or(...) which the planner re-runs as a SubPlan once per role-table append in the Role UNION ALL (8x Seq Scan on spaces). Related performance test of capi release v1.236.0: https://github.com/cloudfoundry/cf-performance-tests-pipeline/blob/main/results/rails/postgres/charts/roles-test-results/v1/roles-detailed-chart-with-most-recent-runs.png Changes: - membership.rb: rewrap authorized_spaces/orgs_subquery as `id IN (UNION)` so the OR collapses; benefits every caller of readable_*_query - membership.rb: add authorized_space/org_ids_subquery returning bare-id unions for callers filtering by raw FK columns - permissions.rb: expose readable_space/org_ids_query - roles_controller.rb: use the id-only queries in readable_roles
philippthun
reviewed
Jun 9, 2026
17c8f45 to
04393b5
Compare
philippthun
approved these changes
Jun 9, 2026
ari-wg-gitbot
added a commit
to cloudfoundry/capi-release
that referenced
this pull request
Jun 9, 2026
Changes in cloud_controller_ng:
- Fix v3/roles perf regression for regular users
PR: cloudfoundry/cloud_controller_ng#5157
Author: Johannes Haass <johannes.haass@sap.com>
5 tasks
philippthun
added a commit
to sap-contributions/cloud_controller_ng
that referenced
this pull request
Jun 10, 2026
PR cloudfoundry#5157 introduced authorized_space_ids_subquery and authorized_org_ids_subquery. These methods avoid unnecessary subplans on the spaces / organizations tables on every permission lookup and are now also used by: - Permissions#readable_security_group_guids_query - Permissions#readable_space_quota_guids - Permissions#is_org_manager? - Membership#authorized_space_guids_subquery - Membership#authorized_org_guids_subquery - Service-credential-binding fetchers - Service-offering / service-plan list fetchers The service-offering / service-plan list fetchers now take both *_ids_query and *_query; the id-query feeds the always-executed permission filter, the full query is consulted only on guid-filtered requests. Also removes the now-dead 'membership' helper from v3/application_controller.rb (no V3 controller calls it after cloudfoundry#5094).
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.
Summary
Fixes a ~2x perf regression on
GET /v3/roles(as regular user) introduced by #5094.Related performance tests results of capi release v1.236.0:
https://github.com/cloudfoundry/cf-performance-tests-pipeline/blob/main/results/rails/postgres/charts/roles-test-results/v1/roles-detailed-chart-with-most-recent-runs.png
Root cause:
Membership#authorized_spaces_subqueryreturnsSpace.where(id: ...).or(organization_id: ...), which Postgres compiles as a SubPlan re-evaluated once per branch of theRoleUNION ALL — 8xSeq Scan onspaces.Perf measurements
Local repro: 5k orgs / 20k spaces / 50k users / ~880k role rows. Target user has mixed org + space role memberships. Benchmark calls
RolesController#readable_rolesdirectly viabin/consoleand runsEXPLAIN ANALYZE.Plan and buffer counts match the reverted state exactly.
Fix
membership.rb: rewriteauthorized_spaces_subquery/authorized_orgs_subqueryto push the OR inside a single
id IN (UNION). Same return contract; plannercan now flatten. Benefits every caller of
readable_*_query.membership.rb: addauthorized_space_ids_subquery/authorized_org_ids_subquery+ flat id-only UNIONs without the entity wrapper. Used by callers that filterby a raw
space_id/organization_idFK column (avoids a redundant subplan overspaces/organizations).permissions.rb: exposereadable_space_ids_query/readable_org_ids_query.roles_controller.rb:readable_rolesuses the id-only queries.I have reviewed the contributing guide
I have viewed, signed, and submitted the Contributor License Agreement
I have made this pull request to the
mainbranchI have run all the unit tests using
bundle exec rakeI have run CF Acceptance Tests