Skip to content

SYSTEM Cited by 1 source

GitHub Issues (issues#show navigation)

issues#show is the GitHub Issues route that renders a single issue page. It is one of the highest-traffic surfaces on github.com — "every week millions of people around the world rely on Issues" — and the focus of GitHub's 2026 perceived- latency rewrite covered in sources/2026-05-14-github-from-latency-to-instant-modernizing-github-issues-navigation-performance.

This page is the system-altitude record of the post-rewrite architecture. The sibling page systems/github-issues is scoped to the 2025 search rewrite (parse → query → normalize, PEG grammar, AST traversal). This page is scoped to the 2026 navigation-performance rewrite of the issue-show route specifically.

Pre-rewrite shape

Three navigation classes reach issues#show, with measured distribution and HPC at the start of the workstream (see HPC / navigation mix):

Class Share HPC median
Hard navigation 57.6 % 2.05 s
Turbo navigation (~5 %) 1.76 s
Soft navigation (React) 37.5 % 1.04 s

The structural reason hard navigations dominate is the in-flight Rails-to-React frontend migration: cross-frontend transitions force a full cold boot. "That distribution made one thing obvious: the dominant path was also the slowest." (Source: sources/2026-05-14-github-from-latency-to-instant-modernizing-github-issues-navigation-performance)

Post-rewrite architecture

The architecture is a local-first application model with stale-while-revalidate — render immediately from locally available data, then asynchronously revalidate.

Three storage tiers (read path, fastest first)

  1. In-memory store — React state holding the actively- rendered issue payload.
  2. In-memory cache — synchronous read tier in front of IndexedDB; "removes another async boundary from soft navigation and materially increases the probability of rendering directly from memory." Generalises the wiki's pair fast small cache with slow large storage pattern at the browser altitude.
  3. IndexedDB — durable, persistent browser storage that survives tab closes and browser restarts. Object-store model with key-based lookups for issue query payloads. Larger practical quota than localStorage.

Stale-while-revalidate semantics on the read path: hydrate from local cache first, render immediately, kick off a background revalidation request, reconcile the in-memory store if data changed.

Preheating substrate

Preheating proactively walks issue references on high-intent surfaces (issue lists, dashboards, projects, dependency views). It is cache- population logic, not freshness-enforcement logic: if the issue is already in the client cache, preheating no-ops.

Operational discipline:

  • Low-priority workers — preheat work runs out of band of the user-initiated request path.
  • Strict rate limiting — preheat capacity is bounded.
  • Circuit breakers — preheat backs off under upstream pressure.
  • User-initiated traffic always pre-empts speculative preheat traffic.

This avoids the noisy-neighbor problem that eager prefetch would create on high-fanout surfaces.

Service-worker cache-hint path (hard navigations)

A service worker intercepts hard navigation requests for issues#show. If the issue payload is already in the local cache, the worker annotates the request with a custom header signaling cache-hit; the server returns a thin HTML shell (layout + minimal markup + JS) and React renders from the local cache. On cache miss / stale / no-SW, the request falls through to the standard SSR path. See patterns/service-worker-cache-hint-header.

JavaScript boot-time mitigations

Hard-navigation cache hits trade SSR time for client-side rendering, so the JS boot path becomes the bottleneck. GitHub addresses this with:

  • Route-level code splitting via React.lazy + dynamic route preloading.
  • Component-level lazy loading"we only fetch the issue editor bundle when a user enters edit mode."
  • Intent-based prefetching (e.g. hover) to pre-fetch bundles that are about to be needed without bloating initial payload.

See patterns/code-split-by-route-and-intent-prefetch.

Measurement: HPC + distribution quality

The driving metric is HPC (Highest Priority Content) — an internal LCP-aligned metric anchored to the browser-selected primary content element (typically the issue title or body). See concepts/highest-priority-content-hpc.

HPC bucket thresholds:

  • Instant: HPC < 200 ms
  • Fast: HPC < 1000 ms
  • Slow: HPC ≥ 1000 ms

The team-philosophy shift was from minimising p99 to maximising the share of navigations in the fast/instant buckets — see concepts/distribution-quality-vs-p99-tail.

Quantified outcomes

Phase React-soft instant Overall instant Cache-hit ratio
Pre-rewrite 4 % (n/a) (no client cache)
After IndexedDB SWR 22 % (n/a) ~33 %
After preheating + memcache ~70 % ~30 % ~96 %

The cache rollout took React-soft-nav instant share from 4 % to 22 % at a ~33 % cache-hit ratio, with an explicit 4.7 % server/cache divergence rate. Preheating + the in-memory tier brought instant share to ~70 % of React navigations and ~30 % of all issues#show traffic, with cache-hit ratio rising to ~96 %.

Cumulative HPC percentile shifts on the full traffic distribution:

Percentile Pre Post Delta
P10 ~600 ms 70 ms -88 %
P25 ~800 ms 120 ms -85 %
P50 ~1200 ms 700 ms -42 %
P75 1800 ms 1400 ms -22 %
P90 2400 ms 2100 ms -12.5 %

The lower percentiles compress dramatically (cached / preheated navigations dominate that part of the distribution); the upper tail improves less because hard-navigation JS-boot cost is now the dominant factor — "exactly the area we are targeting next."

Tradeoffs (named)

  • Controlled staleness vs latency. "This is not 'cache or correctness.' It is latency-first rendering with asynchronous consistency checks on the same navigation." The 4.7 % cache/server divergence is treated as an explicit operating envelope, not a target.
  • Capacity vs cache-hit ratio. Preheating is preferred over eager prefetch precisely because eager prefetch "amplifies request volume, creates N+1-style access patterns and pushes unnecessary compute onto the system for pages a user may never open."
  • SSR time vs JS boot. On hard-navigation cache hits the perf bottleneck moves from server SSR cost to client JS download + execution. The code-splitting + intent-prefetch work is the mitigation; the upper-tail HPC percentiles (P75 / P90) are still bounded by this.

Stated next steps

  • "Targeted rewrites of parts of our backend stack optimized explicitly for low-latency delivery."
  • "A modern UI delivery layer closer to the edge to reduce round trips and improve response time further."

(No detail on which CDN, whether SSR moves to the edge, or how that interacts with the IndexedDB + service-worker substrate.)

Seen in

Last updated · 542 distilled / 1,571 read