We Removed React Server Components from TanStack.com | TanStack Blog*]:transition-opacity [&>*]:duration-1000"><br>TanStack
SearchAIAsk AILog In
Log In
BlogOn this page
We Removed React Server Components from TanStack.com<br>Copy page
by Tanner Linsley on Jul 24, 2026.<br>Earlier this year, tanstack.com became one of my favorite examples for React Server Components. Our content-heavy pages were shipping a giant markdown and syntax highlighting stack to the browser, we moved that work to the server, a meaningful amount of JavaScript disappeared, and the site got faster. We wrote about it, measured it, and felt pretty good about the result because it was exactly the kind of problem RSC is supposed to solve.<br>The performance win was real, but after living with the architecture for a while, I kept noticing how long it took to explain what should have been a pretty boring content pipeline.<br>Markdown became JSX in server-only files, JSX became a Flight payload, route code received contentRsc, and every change had to understand which side of the runtime boundary it was allowed to touch. The RSC APIs themselves did what we asked them to do, but the code around them kept collecting context, bundler configuration, dependency resolution, manual chunking, serialization boundaries, special files, and values that stopped looking like content by the time they reached the route.<br>That was still a reasonable trade when the alternative was shipping Shiki and our old markdown stack to every docs reader, but it also left me wondering whether RSC was solving a hard application problem or mostly keeping a needlessly large dependency out of the browser.<br>RSC solved the problem we actually had#<br>The first performance pass came after we removed third-party ads from tanstack.com. Once the ad stack was gone, the remaining first-party cost was much easier to see, and docs were the obvious problem.<br>At the time, one docs page was transferring about 1.1 MiB of script, with about 358 KiB clearly tied to syntax highlighting alone, mostly Shiki, its runtime pieces, themes, and language chunks. Markdown was still in the client path too, so the browser was basically downloading a small publishing system just to read the docs.<br>RSC fixed that in the most direct way possible, render markdown and highlighted code on the server, send the result to the client as Flight data, and stop shipping the big renderer to every reader.<br>The client bundle changes from that first move were substantial:<br>Page typeClient JS graph changeBlog post pages-153 KB gzippedDocs pages-153 KB gzippedDocs example pages-40 KB gzipped<br>The production pages moved too. /blog/react-server-components went from 52 to 74 in Lighthouse, Total Blocking Time dropped from 1,200ms to 260ms , and transfer size dropped from 1,101 KiB to 785 KiB . /router/latest/docs/overview went from 78 to 81 , TBT dropped from 280ms to 200ms , and transfer size dropped from 917 KiB to 777 KiB .<br>I don't want to rewrite that history to make the rest of this post cleaner. RSC worked, heavy client code stopped shipping to the client, and the browser had less to do, but once we saw how much of the win came from markdown and syntax highlighting, a more obvious question started bothering me.<br>Why did rendering markdown and highlighting code need 358 KiB in the first place?<br>RSC gave us a good way to keep that cost out of the browser, but it didn't make the underlying renderer any smaller. We still had a huge general-purpose content stack, and now we also had an architecture built around keeping it on the server. If we could make that stack small enough to ship, would we still choose RSC?<br>Would anyone?<br>I knew tanstack.com couldn't answer that for every app, and I'm still happy to be proven wrong, but it felt pretty existential at the time. Once you strip away the routing, data loading, and colocation story that tends to get bundled into RSC, the concrete technical benefit I kept coming back to was much simpler, server components can use logic and dependencies that never ship to the browser. That matters a ton when the dependency is a giant markdown and syntax highlighting stack. I was having a harder time finding places where it mattered enough to justify the same machinery without one.<br>So we decided to find out whether the huge dependency was the use case.<br>We made the expensive part small#<br>We replaced the old stack with @tanstack/markdown and @tanstack/highlight, small packages built around the exact markdown and code rendering contract tanstack.com needs. Introducing TanStack Markdown and TanStack Highlight covers why they're separate libraries, what each one does, and the deliberately narrow contracts that keep them small.<br>The result wasn't zero JavaScript, but it was small enough that shipping it stopped feeling irresponsible. On the production routes we measured, the explicit markdown and code renderer is about 27 KiB transferred , roughly 18 to 19 KiB more than the RSC version.<br>That's the part that changed the whole...