Generated by Codex with GPT-5
What happened
GitHub’s official engineering blog published From latency to instant: Modernizing GitHub Issues navigation performance, a production writeup about making GitHub Issues feel fast by changing the client/server navigation architecture rather than treating the problem as a narrow backend-latency optimization.
The core idea is that a developer tool’s perceived performance is dominated by the loop between intent and visible feedback. Opening an issue, jumping to a linked thread, returning to a list, and scanning the next item are not isolated page loads. They are part of a triage workflow. GitHub therefore measured the work around Highest Priority Content, or HPC, an internal metric aligned with Largest Contentful Paint that tracks when the main issue content, usually the title or body, is rendered. The team bucketed navigations into instant, fast, and slow using HPC thresholds, then optimized the distribution rather than focusing only on the worst tail.
That measurement choice shaped the architecture. GitHub identified three main paths into issues#show: hard navigations that pay for a full browser load, server rendering, asset loading, JavaScript boot, and React hydration; Turbo navigations that avoid some full-page overhead but still rely heavily on server-rendered responses; and React soft navigations where the client runtime is already alive. The largest share of traffic was also the slowest path because GitHub is still moving parts of the product from Rails-rendered pages to React, and crossings between the old and new surfaces often force cold starts.
The first implementation move was a local-first model for React soft navigations. GitHub extended its existing in-memory store with a persistent IndexedDB cache for issue query payloads, then layered stale-while-revalidate semantics on top. On navigation, the client tries to hydrate immediately from local data and renders the issue before the network round trip completes. In parallel, it revalidates against the server and reconciles the in-memory state if fresher data exists.
That design deliberately treats controlled staleness as an operating envelope, not a bug. The post says roughly 22% of React navigations became instant after the first rollout, up from 4%, with an observed cache-hit ratio around one-third. GitHub also measured server/cache divergence at about 4.7%, which made the tradeoff explicit: some navigations could briefly show slightly stale data, but the system would converge in the background and remain useful under degraded network conditions.
The next problem was cache hit rate. A one-third hit rate validated the model but also showed that most navigations still arrived before the data was local. GitHub avoided naive eager prefetching because issue lists, dashboards, projects, and dependency views can have high fanout. Fetching every plausible next issue would amplify request volume and spend backend capacity on pages users might never open. Instead, the team built preheating: a cache-population mechanism that walks high-intent issue references and only hits the network when the client does not already have usable data.
Preheating changed the economic model of prediction. It did not try to guarantee the freshest possible version of every candidate issue. It tried to make sure that a renderable version existed by the time the user clicked. Requests ran on low-priority workers, were rate-limited, and were protected by circuit breakers so speculative work could back off under pressure. GitHub also added an in-memory layer in front of IndexedDB so hot issue payloads could be served synchronously without adding an IndexedDB read to the critical path.
The production result was much larger than the first cache rollout. After broad preheating deployment, instant navigations for issues#show rose to about 30% overall, and up to roughly 70% for React navigations. The cache-hit ratio climbed to about 96%. That is the key architectural payoff: a small, controlled amount of background work moved a large share of real user interactions off the network-bound path.
The service-worker layer expanded the same model beyond soft navigations. Hard navigations still happen when users refresh, open a new tab, follow a direct URL, or cross from older Rails-rendered surfaces into Issues. A page’s JavaScript cannot help before it has booted, but a service worker can intercept navigation requests before they reach the server. GitHub used that browser primitive to check whether the issue payload was already available locally. On a hit, the worker annotates the outgoing request with a header that tells the server it can return a thin HTML shell and let React render from cached data. On a miss, stale cache, or unavailable service worker, the path falls back to the normal server-rendered response.
This is an important boundary choice. The service worker does not make the browser pretend the server is irrelevant. It gives the server enough information to avoid recomputing the expensive application fragment when the client can already render the main content. Turbo navigations benefited strongly because they remain constrained by server response time. Hard navigations improved too, but they exposed the next bottleneck: once server work is removed, JavaScript download, boot, and client rendering dominate the critical path. GitHub responded by route-splitting with React.lazy, preloading route code dynamically, and deferring non-critical bundles such as the issue editor until user intent requires them.
Why it matters
The post is useful because it frames web performance as a distributed-systems problem. There is server work, browser storage, local memory, speculative background work, client runtime cost, service-worker request interception, and user-perceived correctness. The winning design was not one optimization. It was a sequence of boundary shifts that changed where the critical path spent time.
The strongest lesson is that latency budgets should be tied to workflow semantics. A generic page-load average would not have told GitHub where to intervene. HPC focused attention on when the issue content users actually need becomes visible, and the navigation-type split kept the team from hiding hard-navigation pain behind faster React paths. That is a better measurement discipline for mature products: optimize the distribution of real interaction paths, not a synthetic benchmark that only covers the easiest route.
The second lesson is that client-side caching needs an explicit correctness model. GitHub did not simply cache issue pages and hope. It used stale-while-revalidate, measured divergence, kept background reconciliation in the design, and preserved fallback behavior for cold or invalid paths. That makes the cache an acceleration layer rather than a second source of truth. The architecture accepts that a developer workflow can tolerate brief staleness in exchange for immediate visibility, as long as edits and freshness-sensitive interactions still converge on the server.
Preheating is the most transferable mechanism. Many teams reach for prefetching when they want a UI to feel instant, but prefetching can become an unbounded backend cost if every likely click turns into speculative work. GitHub’s version is narrower: populate only missing cache entries from high-intent surfaces, use low-priority workers, rate-limit the background work, and stop under load. The distinction between freshness enforcement and cache population matters. It lets the product buy perceived latency with bounded capacity instead of letting speculative traffic become a hidden production workload.
The service-worker design also shows how to modernize incrementally across old and new stacks. GitHub could not wait for every Rails path to become React-native. The service worker created a bridge: when local data exists, the server can emit a lighter shell and hand rendering to the client; when it does not, the old server-rendered behavior remains intact. That is a practical migration pattern for large web applications with mixed rendering systems. It lets teams carve a fast path through the current architecture while the broader platform migration continues.
Takeaway
GitHub’s Issues performance work is a case study in making the common path cheap without pretending every path is common. The architecture starts from observed navigation behavior, turns repeated access into a local data advantage, warms likely next items without overwhelming the backend, and uses a service worker to make cached data useful even before the page runtime is active.
The broader engineering takeaway is that “instant” often comes from reshaping the request lifecycle rather than making each request slightly faster. Once a workflow has repeated access patterns, the system can move useful data closer to the user, separate rendering from freshness, and spend background capacity only where intent is strong. The hard part is not caching itself. It is designing the cache, measurement, fallbacks, and speculative work so they improve the product without creating a new reliability problem.