You probably don't need SSR

February 19, 2023

In October of last year, Next.js announced the app router with support for React server components.

Since then, I’ve probably seen countless debates over Remix, Next.js, and every other piece of the JS ecosystem obsessing over SSR as if it were a prerequisite for building a good product.

I’m here today with an unpopular take. Your bloated, SSR-first React app is probably slower, harder to reason about, and solving problems you don’t actually have.

The problem is most people are only adopting SSR without fully understanding it because Vercel has told them to, not because their product needs it.

I’m not discounting SSR as useless, only situational. More likely than not though, your app isn’t in the situation where SSR shines.

Introduction

SSR shines when content delivery is your product. So think:

  • Blog
  • News publication
  • Contenty heavy, SEO-driven site

Then SSR absolutely makes sense. In these cases, first paint matters more than interactivity, content must be indexable and immediately viewable, and pages change frequently.

Most apps aren’t content websites

Modern web apps are dashboards, admin panels, CRUD, etc. All data-dense UIs, things behind an auth wall with real client-side state.

In these apps:

  • Users must log in before anything is useful
  • Interactivity > first paint
  • Data is personalized per user

The application behaves more like actual software than a document. Even if you add SSR, you still need client-side data fetching, state, interactivity, and routing.

The hidden costs

SSR introduces a bunch of random complexity:

  • You now have 2 execution environments
  • Hyderation mismatches
  • Worse debugging DX
  • Infra complexity
  • Serialization boundaries

And for what? So your authenticated dashboard can show a loading spinner slightly earlier?

The lies

One of the biggest lies I’ve seen thrown around is that the browser “does less work”. It doesn’t. You still:

  1. Render on the server
  2. Send HTML
  3. Download JS
  4. Parse JS
  5. Hydrate
  6. Reconcile
  7. Attach listeners

Essentially, you’re doing the same work twice.

Conclusion

A lot of people and teams didn’t adopt SSR because they needed it, it’s because:

  • Framework defaults nudged them there
  • SEO fear-mongering
  • Some BS they saw on Twitter
  • “Trust me bro” benchmarks

The result of all that is over-engineered apps that solve edge cases which don’t exist. SSR is a tool to be for certain types of websites, it’s not a badge of technical maturity.