Build1 publisher2 min readPublished
GitHub cut server render time 55% by moving Primer off CSS-in-JS
GitHub says moving its Primer design system from CSS-in-JS to CSS Modules cut server-side render time by 55% and component initialization time by 25%. The switch took styling work out of the browser and server at runtime, one feature-flagged component at a time.
The Engineer · Build desk
Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened
- Component counts on some GitHub pages surged in 2023, and the CSS-in-JS setup slowed first page loads, server rendering and style updates as they grew.
- GitHub required that no Primer update break the live site, and the old CSS-in-JS technique had to keep working for any GitHub component still using it.
- Every component in Primer had been moved to CSS Modules by December 2024.
- One of the trickiest parts of removing CSS-in-JS from Primer was the sx prop, the standard way teams styled and customized Primer components.
Compiled by The EngineerSomething wrong?How this is made
Why it matters
- decision Teams running a runtime CSS-in-JS library on server-rendered, component-heavy pages now have a production case to weigh when deciding whether a build-time CSS migration is worth budgeting.
- cost The bill scales with usage: GitHub had to rewrite every Primer component plus every in-house component styled the same way, so heavier CSS-in-JS adoption means a larger job.
- constraint Finishing Primer left CSS-in-JS support in place across GitHub, so pages built from in-house CSS-in-JS components keep paying for that runtime until a second, company-wide removal lands.
CSS Modules moves the styling work to build time. Each component's styles sit in a CSS file next to its JavaScript. Class names are local by default, and the build rolls everything into stylesheets sent with the page HTML [2]. In the post's words, the format "removes the need for any client or server runtime behavior" [2]. The browser receives finished CSS, and the server renders markup without collecting styles [2]. Josh Black, a GitHub software engineer, wrote: "It became clear that the Primer team needed to address the issue at the source." [12]
The migration went one component at a time, with the same four steps for each [5]:
1. Add a file translating the existing styles to CSS Modules. 2. Put the component behind a feature flag that switches between old and new styles. 3. Run the existing visual regression tests and require identical snapshots from both versions. 4. Roll the flag out to the Primer team, then GitHub staff, then all users.
The regression suite already existed before the migration started [5]. It is the least exciting detail in the post, and I think it is the one that made the plan safe. Step 3 set the bar at identical snapshots, so a migrated component had to render exactly what the old one did [5].
The flag had a second use. According to the post, it kept the migration safe and gave the team "clear signals on the performance benefits of CSS Modules" [6]. Both style paths were live behind one switch, so the same flag handled rollback and measurement [5]. Black wrote that this loop flagged issues early, while Primer kept shipping changes to GitHub [6].
Taken at face value, server rendering now takes 45% of its old time and component initialization takes 75% [1][2]. GitHub did not publish baseline times, the pages it measured, or the percentiles behind the figures. I'd expect the gain to transfer only to pages that look like GitHub's did in 2023. That means many components, rendered on the server, styled by a library that initializes styles in the browser and collects them during server rendering [1]. A page with a handful of components does less of that work per request, so it has less to remove.
The build model explains why sx was hard. Callers passed an inline style object when they rendered a component [10]. A build step cannot see styles that exist only at render time. Black wrote that sx "represented the best and worst parts of CSS-in-JS" [11]. The first strength he listed was TypeScript support integrated with GitHub's design tokens [11].
What to watch
- Whether GitHub publishes how it replaced the sx prop and sets a date for dropping CSS-in-JS support across the company.
- Absolute render times and a list of the pages GitHub measured; those would show how much of the 55% depends on component-heavy pages.