Skip to content

bug: match page re-checks every permission every second - #588

Merged
lukepolo merged 1 commit into
mainfrom
perf/match-subscription-split
Sep 19, 2026
Merged

lukepolo merged 1 commit into
mainfrom
perf/match-subscription-split

Conversation

@lukepolo

@lukepolo lukepolo commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

The match subscription asked for thirteen permission and membership fields plus the organizer's full profile on every tick. Each of those is a function call the database re-runs for the row, and none of them move without a status change or an organizer action.

Measured warm against prod, one match row costs 9.56 ms across just the 19 permission functions I timed, and the worst offenders are the organizer checks this moves out:

function ms/call
is_match_organizer 1.63
match_requested_organizer 1.38
is_captain 0.64
is_coach 0.57

is_match_organizer is the notable one — the subscription requested it directly and can_cancel, can_check_in and can_assign_server each call it internally, so the same three-table join ran several times per row per tick with identical inputs.

Moved to a matchStatic query, merged back into a single match computed so no child component changes: the membership and permission booleans, min/max_players_per_lineup, map_veto_type, organizer (which was pulling elo and three sanction checks), and tournament_brackets.

Refetched on status change, on server assignment, and explicitly after callForOrganizer and a match options save.

can_start and can_check_in deliberately stay in the subscription since they read lineup readiness. can_start is the single most expensive function at 2.98 ms but only in the pre-match states — once a match is Live or over it returns on its first status check.

Verified every moved field is still consumed somewhere, and the full suite passes (111 tests). The two prettier warnings on these files are pre-existing on main and left alone.

Follow-ups this does not touch: the lineup player profiles (about 13 players × elo + sanctions per tick) and the per-round kill/assist payload, which together are the larger share of this query's 16,750 buffers per call.

The match subscription asked for thirteen permission and membership
fields plus the organizer's full profile on every tick. Each is a
function call the database re-runs per row, and none of them move
without a status change or an organizer action.

Splits them into a query and refetches it on those events. can_start
and can_check_in stay live -- they read lineup readiness.
@lukepolo
lukepolo merged commit b6842b2 into main Sep 19, 2026
2 checks passed
@lukepolo
lukepolo deleted the perf/match-subscription-split branch September 19, 2026 20:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant