All articles
Deployment · 4 min read · June 24, 2026

The Week Git LFS, TanStack Router, and Deployment Teamed Up Against Me

A real account of an SSR mismatch, a file-size limit, and how I ended up rebuilding in Next.js.

Deployment artwork
Deployment

Every developer has a project that humbles them. This was mine.

It started normally enough: code committed, assets tracked, TanStack Router handling navigation the way it's supposed to. I pushed, set up the deploy, and figured I'd have this live within the hour.

That was not how the day went.


Chapter one: Git LFS and the file-size limit nobody warns you about

Git LFS (Large File Storage) works beautifully on your local machine. You track your large files — images, media, whatever heavy assets your project needs — and everything commits and pushes without complaint.

The problem shows up at deploy time.

Most hosting providers cap LFS bandwidth and storage on free or standard tiers, and that cap is rarely visible until you exceed it. There's no warning beforehand. The build simply fails, often with an error message vague enough that you start second-guessing your own setup before you even get to the real cause.

In my case, it was a straightforward file size limit exceeded — four words that cost me a full Saturday of debugging before I traced it back to LFS quotas rather than anything in my actual code.


Chapter two: the SSR mismatch with TanStack Router

To be clear upfront: TanStack Router is a solid library. This isn't a takedown of the ecosystem — it's an account of how one specific mismatch nearly broke my patience.

An SSR (server-side rendering) mismatch happens when the server renders one version of a page and the client renders a different version of that same page on hydration. React compares the two and, when they don't line up, throws hydration warnings — sometimes cascading into broken UI, sometimes just noisy console errors that mask the real issue underneath.

What made this particularly frustrating was the way it compounded. I'd fix one mismatch — usually traced to a loader returning slightly different data shapes server-side vs. client-side — and a new one would surface somewhere else in the route tree. Each fix exposed another layer. I went through my route definitions, loaders, and component structure more than once trying to isolate exactly where client and server state were diverging.

By the end of it, I knew that loading spinner a little too well.


Chapter three: deployment, where both problems collided

By the time I reached deployment, I'd already fixed the SSR issues and thought I was clear. I wasn't.

Build failed.

I checked environment variables — fine. I checked routes — fine, as far as I could tell. Then I checked the LFS files again, because they were still quietly consuming bandwidth in the background, unrelated to anything I'd just fixed in the router. Two separate problems, same deploy pipeline, each one masking the other's error output.

I pushed again. Failed again. At that point it stopped being a single bug to fix and became a process of isolating which failure belonged to which system — LFS quota issues showing up as generic build failures, SSR mismatches showing up as runtime hydration warnings that only appeared in production, not locally.


Why I moved to Next.js

This wasn't a decision I made mid-crisis. It came after, once I'd actually fixed both issues and had time to weigh whether I wanted to keep solving this category of problem on every project going forward.

To be specific about what changed:

  • File-based routing removed an entire class of configuration I'd been managing manually with TanStack Router.

  • Built-in SSR handling in Next.js meant the client/server data shape mismatches I'd spent days chasing simply weren't something I had to architect myself — the framework's data-fetching patterns (getServerSideProps / App Router server components) are designed around avoiding that exact hydration gap.

  • It didn't eliminate the LFS issue — that's a Git/hosting-level problem independent of framework — but it did mean I was no longer debugging two unrelated failure modes inside the same build pipeline.

TanStack Router vs Next.js

I've deployed three projects since the switch without a single hydration warning. I'm not claiming Next.js is objectively superior to TanStack Router for every use case — but for how I build and where I deploy, it removed a category of friction that TanStack Router's flexibility was costing me.


What I'd tell another developer hitting this

  1. Check your hosting provider's Git LFS bandwidth and storage limits before you commit large files across your history. The failure shows up at deploy time, not commit time, which makes it harder to trace.

  2. Treat every hydration warning as worth investigating immediately, even if the page still renders. They tend to compound rather than resolve on their own.

  3. Isolate failures by system before assuming they're related. I lost time treating the LFS quota issue and the SSR mismatch as one problem when they were two separate failures sharing a build pipeline.

  4. A framework switch is a legitimate engineering decision, not a failure. Choosing Next.js over a more manual TanStack Router setup, for my workflow, removed recurring friction rather than just working around a one-off bug.

If you're dealing with TanStack Router SSR mismatches or LFS-related deploy failures right now, I hope this saves you some of the time it cost me to trace both issues back to their root causes.


Working through a similar setup or have a different take on TanStack Router's SSR model? I'd be glad to hear about it — reach out via the contact page.

Tweet LinkedIn