Pull Requests: GitHub API rate limit exceeded from redundant refetching
Author: FinndersenCreated Sep 15, 2026Updated Sep 15, 2026
Summary
- Using the Pull Requests view produces GitHub "API rate limit exceeded" errors.
- The view appears to refetch far more than necessary: every filter change invalidates all loaded pages, and each page costs a search call plus a paginated GraphQL check-rollup query per repo.
- Worse with several connected repos (per-repo fan-out) and with repos that have many CI contexts per PR (check-rollup pagination).
Steps to reproduce
- Connect several GitHub repos as projects.
- Open the Pull Requests view and scroll a few pages.
- Change the search text / author / review / state filters a few times, and open a PR or two.
- Observe rate-limit errors from GitHub.
Cause
Per page of results (PAGE_SIZE = 30), per repo target, the view issues:
workspaceCreation.searchPullRequests— a GitHub search request.enrichPageWithChecks→ghGetPullRequestChecks→getPullRequestChecksViaGraphql, a GraphQL check-rollup query per project. That one is cursor-paginated per PR, so PRs with many check contexts cost several extra round-trips (the code has explicithasNextPage/ "Missing check-rollup cursor for PR #n" handling).
Amplifiers:
- The query key includes
page:["pullRequests","searchPullRequests", target.key, target.hostUrl, query, author, review, includeClosed, mergedOnly, page]so changing any filter changes every page's key. An infinite list scrolled to page 5 re-issues 5 searches and 5 check-rollup enrichments. staleTimeis only3e4(30s) withgcTime10 min, so coming back to the view or refocusing after half a minute refetches search + checks again.useProjectQueryTargets(projectFilters)fans out one query per target, so with no project filter the above is multiplied by the number of connected repos.- The forced navigation described in the companion filter issue means ordinary filter interaction triggers extra route changes, churning these keys.
GitHub's authenticated search endpoint is limited to ~30 requests/minute, which is the tightest budget here, and GraphQL check-rollups draw on the points budget — so this pattern hits limits quickly.
Suggested fixes
- Don't include
pagein a key that filter changes invalidate — or reset the infinite query without refetching already-cached pages. - Raise
staleTimesubstantially for PR search/checks, and avoid refetch on focus/mount for this view. - Make the check-rollup enrichment lazy: fetch checks only for rows actually visible, and cache them per (repo, PR, headSha) so they survive filter changes.
- Batch or debounce the per-repo fan-out, and surface remaining rate-limit budget rather than failing the whole list.
Related
- Companion issue: PR selection locks the list's repo filter (filed separately) — its forced navigation contributes to the refetch churn.
- Possibly in scope of the #5596 GitHub & PR integration tracker (cf. stale #2845 "Batch GitHub PR status fetching via GraphQL", #4275 "GraphQL 504 on large repos").
Environment
Superset 1.26.0, macOS Darwin arm64
Source: superset-sh/superset