DEV Community

Cover image for Server-Side Rendering (SSR) and Hydration: How Modern Web Applications Become Fast and Interactive
Abanoub Kerols
Abanoub Kerols

Posted on

Server-Side Rendering (SSR) and Hydration: How Modern Web Applications Become Fast and Interactive


Modern frontend frameworks have changed dramatically.

Applications that once rendered everything in the browser can now render HTML on the server, send meaningful content to the user immediately, and then transform that static HTML into a fully interactive application.

Two concepts are at the center of this architecture:

  • Server-Side Rendering (SSR)
  • Hydration

They are often mentioned together, but they solve different problems.

Understanding how they work internally is important if you work with Angular, React, Next.js, Nuxt, or modern full-stack applications.

In this article, we will build the concepts from first principles, understand the browser lifecycle, compare CSR vs SSR, understand hydration, explore common problems, and finally build a complete SSR + hydration project.


1. The Traditional Client-Side Rendering Model

Before understanding SSR, let's start with the traditional approach.

In a typical Client-Side Rendering (CSR) application:

Browser
   |
   | GET /
   v
Server
   |
   | HTML + JavaScript bundles
   v
Browser
   |
   | Download JS
   v
JavaScript executes
   |
   v
Application renders UI
   |
   v
User sees the page
Enter fullscreen mode Exit fullscreen mode

For example, the server might initially return:

<!DOCTYPE html>
<html>
<head>
  <title>My App</title>
</head>

<body>
  <div id="root"></div>

  <script src="/assets/main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

The important part is:

<div id="root"></div>
Enter fullscreen mode Exit fullscreen mode

There isn't much actual application content in the initial HTML.

JavaScript must execute before the user gets the real UI.


2. What Happens During CSR?

Let's imagine this Angular/React-style application:

function App() {
  return (
    <main>
      <h1>Hello World</h1>
      <p>Welcome to my application.</p>
    </main>
  );
}
Enter fullscreen mode Exit fullscreen mode

The browser initially receives:

<div id="root"></div>
Enter fullscreen mode Exit fullscreen mode

Then:

Download JavaScript
       ↓
Parse JavaScript
       ↓
Execute JavaScript
       ↓
Create components
       ↓
Fetch data
       ↓
Render DOM
       ↓
User sees content
Enter fullscreen mode Exit fullscreen mode

This can be perfectly fine.

But there is a problem.

The browser has to do a lot of work before the user sees meaningful content.

This becomes especially noticeable on:

  • slow networks
  • low-end mobile devices
  • large JavaScript applications
  • content-heavy websites
  • SEO-sensitive applications

3. The Idea Behind Server-Side Rendering

SSR changes the responsibility.

Instead of asking the browser to construct the initial HTML, we ask the server to render the application first.

The architecture becomes:

Browser
   |
   | GET /
   v
Application Server
   |
   | Render application
   v
HTML
   |
   | Send HTML
   v
Browser
   |
   | Display HTML immediately
   v
User sees content
Enter fullscreen mode Exit fullscreen mode

For example, instead of:

<div id="root"></div>
Enter fullscreen mode Exit fullscreen mode

the browser receives:

<div id="root">
  <main>
    <h1>Hello World</h1>
    <p>Welcome to my application.</p>
  </main>
</div>
Enter fullscreen mode Exit fullscreen mode

The browser can display this content immediately.

But there is another problem.

The HTML is visible...

but is it interactive?

Not necessarily.

That brings us to hydration.


4. SSR Is Not the Same as Hydration

This distinction is extremely important.

SSR answers:

Who generates the initial HTML?

Answer:

The server.
Enter fullscreen mode Exit fullscreen mode

Hydration answers:

How does the browser turn server-generated HTML into an interactive application?

Answer:

Client-side JavaScript attaches to the existing HTML.
Enter fullscreen mode Exit fullscreen mode

So:

SSR
 ↓
Generate HTML on server
 ↓
Send HTML to browser
 ↓
Browser displays HTML
 ↓
Hydration
 ↓
JavaScript takes over
 ↓
Application becomes interactive
Enter fullscreen mode Exit fullscreen mode

SSR and hydration are complementary concepts.


5. A Simple Analogy

Think about a restaurant.

CSR

The restaurant gives you:

Ingredients + recipe
Enter fullscreen mode Exit fullscreen mode

You must cook the meal yourself.

SSR

The restaurant gives you:

A finished meal
Enter fullscreen mode Exit fullscreen mode

You can immediately eat it.

But the restaurant still needs to give you:

Fork + knife
Enter fullscreen mode Exit fullscreen mode

so you can interact with it.

That's hydration.

SSR = prepare the meal

Hydration = make the meal usable
Enter fullscreen mode Exit fullscreen mode

6. What Exactly Is Hydration?

Suppose the server sends:

<button id="increment">
  Count: 0
</button>
Enter fullscreen mode Exit fullscreen mode

The browser can display the button.

But the browser doesn't automatically know:

button.onclick = incrementCounter;
Enter fullscreen mode Exit fullscreen mode

The server generated HTML.

The client application must now connect its JavaScript behavior to that existing DOM.

Conceptually:

Server HTML
     |
     v
<button>Count: 0</button>
     |
     | Hydration
     v
Existing DOM + JavaScript behavior
     |
     v
Interactive application
Enter fullscreen mode Exit fullscreen mode

The framework doesn't necessarily throw away the existing DOM and recreate everything.

Instead, it attempts to reuse the server-rendered DOM.


7. SSR + Hydration Lifecycle

A simplified lifecycle looks like this:

             SERVER
               |
               v
        Application Code
               |
               v
        Render Components
               |
               v
           HTML Output
               |
               |
        HTTP Response
               |
               v
             BROWSER
               |
               v
        Parse HTML
               |
               v
       Display Content
               |
               v
       Download JS
               |
               v
          Hydration
               |
               v
       Attach Behavior
               |
               v
      Fully Interactive App
Enter fullscreen mode Exit fullscreen mode

This is the fundamental architecture.


8. Why SSR Improves Perceived Performance

Imagine an application that takes:

HTML request             100ms
JavaScript download      500ms
JavaScript execution     300ms
API requests              300ms
Rendering                 100ms
Enter fullscreen mode Exit fullscreen mode

With pure CSR, the user may wait for several of these stages before meaningful content appears.

With SSR, the server can generate the initial HTML:

Request
  ↓
Server renders HTML
  ↓
HTML arrives
  ↓
User sees content
Enter fullscreen mode Exit fullscreen mode

JavaScript still needs to load.

But the user doesn't necessarily stare at an empty page while waiting.

This can improve metrics such as:

  • First Contentful Paint (FCP)
  • Largest Contentful Paint (LCP)
  • perceived performance

However, SSR is not automatically faster in every situation.

The server now has more work to perform.


9. SSR vs CSR

Let's compare them.

Feature CSR SSR
Initial HTML Mostly empty shell Meaningful HTML
Rendering Browser Server
Initial JS dependency High Lower for initial display
SEO Can be harder Usually easier
Server workload Lower Higher
Initial content Usually later Usually earlier
Hydration Not applicable Usually required
Scalability concerns Mostly client-side Server rendering required

A common misconception is:

SSR means there is no client-side JavaScript.

That's false.

Modern SSR applications are usually:

Server-rendered
+
Client-enhanced
Enter fullscreen mode Exit fullscreen mode

10. The Most Important Concept: The Same UI Must Exist on Both Sides

Consider this component:

function App() {
  return <h1>Hello World</h1>;
}
Enter fullscreen mode Exit fullscreen mode

The server renders:

<h1>Hello World</h1>
Enter fullscreen mode Exit fullscreen mode

The browser then loads the client application.

The client expects:

<h1>Hello World</h1>
Enter fullscreen mode Exit fullscreen mode

Everything matches.

Hydration can proceed normally.

But imagine the server renders:

<h1>Hello World</h1>
Enter fullscreen mode Exit fullscreen mode

while the browser expects:

<h1>Hello Abanoub</h1>
Enter fullscreen mode Exit fullscreen mode

Now we have a mismatch.

This is called a:

Hydration Mismatch


11. Hydration Mismatches

Hydration mismatches occur when the server-generated HTML doesn't match what the client expects.

For example:

function App() {
  return (
    <p>
      {Math.random()}
    </p>
  );
}
Enter fullscreen mode Exit fullscreen mode

The server might generate:

<p>0.3214</p>
Enter fullscreen mode Exit fullscreen mode

The browser might calculate:

<p>0.8421</p>
Enter fullscreen mode Exit fullscreen mode

The DOM no longer matches.

Another common example:

const now = new Date();

return <p>{now.toLocaleTimeString()}</p>;
Enter fullscreen mode Exit fullscreen mode

The server and browser may execute at different times.

Result:

Server:
10:30:01

Client:
10:30:02
Enter fullscreen mode Exit fullscreen mode

Mismatch.


12. Browser-Only APIs Can Also Cause Problems

Consider:

const width = window.innerWidth;
Enter fullscreen mode Exit fullscreen mode

The browser has:

window
document
localStorage
navigator
Enter fullscreen mode Exit fullscreen mode

But the server doesn't have a browser DOM.

So this can fail during SSR:

window.innerWidth
Enter fullscreen mode Exit fullscreen mode

or:

localStorage.getItem("theme");
Enter fullscreen mode Exit fullscreen mode

or:

document.querySelector(...)
Enter fullscreen mode Exit fullscreen mode

SSR code must distinguish between:

Server environment
Enter fullscreen mode Exit fullscreen mode

and:

Browser environment
Enter fullscreen mode Exit fullscreen mode

Modern frameworks provide APIs for handling this safely.


13. Data Fetching Is Another SSR Challenge

Suppose your application displays:

Product: MacBook Pro
Price: $1999
Enter fullscreen mode Exit fullscreen mode

The server needs the data before rendering.

So:

Browser
   |
   | GET /products/1
   v
Server
   |
   | Fetch product
   v
Database / API
   |
   v
Product data
   |
   v
Render HTML
   |
   v
Browser
Enter fullscreen mode Exit fullscreen mode

The generated HTML could contain:

<h1>MacBook Pro</h1>
<p>$1999</p>
Enter fullscreen mode Exit fullscreen mode

This is excellent for the initial render.

But now we have another question:

Does the browser need to fetch the same data again during hydration?

Ideally, we want to avoid unnecessary duplicate requests.


14. Server-to-Client Data Transfer

A sophisticated SSR application often transfers server-fetched state to the client.

Conceptually:

Server

Fetch API
   ↓
Product data
   ↓
Render HTML
   ↓
Transfer state
   ↓
Browser
   ↓
Hydrate
   ↓
Reuse existing data
Enter fullscreen mode Exit fullscreen mode

Without state transfer:

Server → API
Browser → API
Enter fullscreen mode Exit fullscreen mode

The same data might be fetched twice.

With state transfer:

Server → API
        ↓
     Transfer
        ↓
     Browser
Enter fullscreen mode Exit fullscreen mode

The browser can reuse the result.

This concept appears in different forms across frameworks.


15. Angular SSR

Angular provides first-class support for SSR.

A traditional Angular application might be rendered entirely in the browser:

Browser
  ↓
Angular Bootstrap
  ↓
Components
  ↓
DOM
Enter fullscreen mode Exit fullscreen mode

With SSR:

Node.js Server
      ↓
Angular Application
      ↓
Rendered HTML
      ↓
Browser
      ↓
Angular Hydration
      ↓
Interactive Application
Enter fullscreen mode Exit fullscreen mode

Modern Angular applications can use:

ng add @angular/ssr
Enter fullscreen mode Exit fullscreen mode

This configures the project for server-side rendering.


16. A Complete Angular SSR Example

Let's create a small product application.

angular-ssr-demo/
│
├── src/
│   ├── app/
│   │   ├── app.ts
│   │   ├── app.html
│   │   └── product.service.ts
│   │
│   ├── main.ts
│   └── main.server.ts
│
├── server.ts
├── angular.json
└── package.json
Enter fullscreen mode Exit fullscreen mode

The application will display:

Product Catalog

MacBook Pro
$1999

Add to Cart
Enter fullscreen mode Exit fullscreen mode

17. Create the Application

Start with:

ng new angular-ssr-demo
Enter fullscreen mode Exit fullscreen mode

Then:

cd angular-ssr-demo
Enter fullscreen mode Exit fullscreen mode

Add SSR:

ng add @angular/ssr
Enter fullscreen mode Exit fullscreen mode

Angular will configure the required server-side infrastructure.


18. Create a Product Service

import { Injectable } from '@angular/core';

export interface Product {
  id: number;
  name: string;
  price: number;
}

@Injectable({
  providedIn: 'root'
})
export class ProductService {

  getProduct(): Product {
    return {
      id: 1,
      name: 'MacBook Pro',
      price: 1999
    };
  }
}
Enter fullscreen mode Exit fullscreen mode

19. Create the Component

import { Component, inject } from '@angular/core';
import { ProductService } from './product.service';

@Component({
  selector: 'app-root',
  template: `
    <main>
      <h1>Product Catalog</h1>

      <section>
        <h2>{{ product.name }}</h2>

        <p>
          Price: ${{ product.price }}
        </p>

        <button (click)="addToCart()">
          Add to Cart
        </button>

        <p>{{ message }}</p>
      </section>
    </main>
  `
})
export class AppComponent {

  private productService = inject(ProductService);

  product = this.productService.getProduct();

  message = '';

  addToCart() {
    this.message = 'Product added to cart!';
  }
}
Enter fullscreen mode Exit fullscreen mode

Now notice something important.

The server can render:

<h1>Product Catalog</h1>

<h2>MacBook Pro</h2>

<p>Price: $1999</p>

<button>Add to Cart</button>
Enter fullscreen mode Exit fullscreen mode

The user can see the content before the client application becomes interactive.


20. What Happens During Hydration?

The server produces:

<button>Add to Cart</button>
Enter fullscreen mode Exit fullscreen mode

The browser displays it.

Then Angular loads.

Angular sees the existing DOM:

<button>Add to Cart</button>
Enter fullscreen mode Exit fullscreen mode

and hydrates it.

Conceptually:

Existing DOM
     |
     v
Angular
     |
     v
Match component structure
     |
     v
Attach event behavior
     |
     v
Interactive button
Enter fullscreen mode Exit fullscreen mode

Now when the user clicks:

Click
 ↓
Angular event handler
 ↓
addToCart()
 ↓
message changes
 ↓
UI updates
Enter fullscreen mode Exit fullscreen mode

This is the transition from:

Static HTML
Enter fullscreen mode Exit fullscreen mode

to:

Interactive application
Enter fullscreen mode Exit fullscreen mode

21. Hydration Does Not Mean "Render Everything Again"

This is one of the most important mental models.

A naive mental model would be:

Server HTML
   ↓
Delete it
   ↓
Render application again
Enter fullscreen mode Exit fullscreen mode

Modern hydration aims to do:

Server HTML
   ↓
Keep existing DOM
   ↓
Connect framework runtime
   ↓
Reuse DOM
   ↓
Interactive application
Enter fullscreen mode Exit fullscreen mode

The goal is to avoid unnecessary DOM reconstruction.


22. Hydration and Event Handlers

Consider:

<button>
  Add to Cart
</button>
Enter fullscreen mode Exit fullscreen mode

Before hydration:

Visible: YES
Interactive: NO
Enter fullscreen mode Exit fullscreen mode

After hydration:

Visible: YES
Interactive: YES
Enter fullscreen mode Exit fullscreen mode

This creates an important performance concept:

Time to Interactive

There can be a period where the user sees the application but JavaScript hasn't finished loading and hydrating.

For example:

0ms
 |
 | HTML arrives
 v
100ms
 |
 | User sees content
 v
300ms
 |
 | JavaScript downloaded
 v
500ms
 |
 | Hydration
 v
600ms
 |
 | Application interactive
Enter fullscreen mode Exit fullscreen mode

The application can look ready before it is actually ready.

This is sometimes called the:

Hydration Gap


23. The Hydration Gap

Suppose the user sees:

[ Add to Cart ]
Enter fullscreen mode Exit fullscreen mode

and immediately clicks it.

But hydration hasn't completed yet.

The click might not be handled.

This creates a UX problem.

Modern frameworks have developed techniques to reduce this problem.

One important approach is:

Partial Hydration

Instead of hydrating the entire application immediately, hydrate only the parts that need to become interactive.


24. Partial Hydration

Imagine a page:

------------------------------------------------
Header
------------------------------------------------
Hero Section
------------------------------------------------
Article Content
------------------------------------------------
Comments Widget
------------------------------------------------
Shopping Cart
------------------------------------------------
Footer
------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

Only these components may need JavaScript:

Comments Widget
Shopping Cart
Enter fullscreen mode Exit fullscreen mode

Why hydrate the entire page?

Instead:

Static HTML
     |
     +---- Header
     |
     +---- Article
     |
     +---- Footer
     |
     +---- Hydrate Comments
     |
     +---- Hydrate Cart
Enter fullscreen mode Exit fullscreen mode

This can significantly reduce client-side JavaScript work.


25. Angular Hydration Concepts

Angular supports hydration so that the server-rendered DOM can be reused on the client.

A typical setup uses:

provideClientHydration()
Enter fullscreen mode Exit fullscreen mode

For example:

import {
  ApplicationConfig
} from '@angular/core';

import {
  provideClientHydration
} from '@angular/platform-browser';

export const appConfig: ApplicationConfig = {
  providers: [
    provideClientHydration()
  ]
};
Enter fullscreen mode Exit fullscreen mode

The exact generated configuration depends on the Angular version and SSR setup, but the fundamental idea is:

Server rendering
      +
Client hydration
      =
Fast initial HTML + interactivity
Enter fullscreen mode Exit fullscreen mode

26. SSR Architecture in Production

A production SSR architecture might look like:

                 ┌──────────────┐
                 │    Browser   │
                 └──────┬───────┘
                        │
                        │ HTTP
                        ▼
                ┌───────────────┐
                │     Nginx     │
                └───────┬───────┘
                        │
                        ▼
                ┌───────────────┐
                │ Node.js SSR   │
                │    Server     │
                └───────┬───────┘
                        │
            ┌───────────┴───────────┐
            ▼                       ▼
      ┌───────────┐           ┌───────────┐
      │   API     │           │ Database  │
      └───────────┘           └───────────┘
Enter fullscreen mode Exit fullscreen mode

The server:

  1. receives the request
  2. loads required data
  3. renders the application
  4. returns HTML
  5. browser displays it
  6. client JavaScript loads
  7. hydration occurs
  8. application becomes interactive

27. SSR With a Backend API

A common architecture is:

Browser
   |
   | GET /
   v
Angular SSR Server
   |
   | GET /api/products
   v
Node.js API
   |
   v
PostgreSQL
Enter fullscreen mode Exit fullscreen mode

The SSR server receives the product data and generates:

<h1>Products</h1>

<article>
  <h2>MacBook Pro</h2>
  <p>$1999</p>
</article>
Enter fullscreen mode Exit fullscreen mode

The browser gets meaningful HTML.

Then:

Angular JS
    ↓
Hydration
    ↓
Existing DOM reused
    ↓
Interactive application
Enter fullscreen mode Exit fullscreen mode

28. SSR Is Not Free

SSR provides benefits, but it introduces costs.

The server now needs to render every request.

For CSR:

Server:
Return static assets
Enter fullscreen mode Exit fullscreen mode

For SSR:

Server:
Execute application
Fetch data
Render HTML
Return response
Enter fullscreen mode Exit fullscreen mode

Therefore SSR can increase:

  • CPU usage
  • memory usage
  • server response complexity
  • infrastructure cost

This is why architecture matters.


29. SSR and Caching

Caching becomes extremely important.

Suppose 10,000 users request:

/products/123
Enter fullscreen mode Exit fullscreen mode

Rendering the exact same page 10,000 times may be wasteful.

You can introduce caching:

Browser
   |
   v
CDN / Cache
   |
   +---- Cache HIT → HTML
   |
   +---- Cache MISS
             |
             v
          SSR Server
Enter fullscreen mode Exit fullscreen mode

This allows SSR and caching to work together.


30. SSR + CDN

A powerful architecture can look like:

                 Browser
                    |
                    v
                  CDN
               /       \
              /         \
       Cache HIT       Cache MISS
          |                |
          v                v
        HTML           SSR Server
                           |
                           v
                          API
Enter fullscreen mode Exit fullscreen mode

The first request may require server rendering.

Later requests can potentially receive cached HTML.

This gives you:

SSR benefits
+
CDN performance
Enter fullscreen mode Exit fullscreen mode

31. SSR and SEO

One of the major reasons SSR became popular is SEO.

Search engines need to understand your content.

A CSR application might initially return:

<div id="root"></div>
Enter fullscreen mode Exit fullscreen mode

while SSR can return:

<h1>Best Programming Courses</h1>

<p>
  Learn Angular, React, Node.js and TypeScript.
</p>
Enter fullscreen mode Exit fullscreen mode

The content exists directly in the initial HTML.

This is especially useful for:

  • blogs
  • documentation
  • e-commerce
  • news websites
  • landing pages
  • content platforms

However, SEO is more complicated than simply saying:

SSR = good SEO.

Modern search engines can execute JavaScript.

SSR mainly helps by making meaningful content available earlier and more reliably.


32. SSR vs SSG

SSR is not the only server-rendering strategy.

There is also:

Static Site Generation

SSG generates HTML during the build process.

Build Time
   ↓
Generate HTML
   ↓
Deploy static files
   ↓
CDN
   ↓
User
Enter fullscreen mode Exit fullscreen mode

SSR:

Request Time
   ↓
Render HTML
   ↓
Response
Enter fullscreen mode Exit fullscreen mode

SSG:

Build Time
   ↓
Generate HTML
   ↓
Serve HTML
Enter fullscreen mode Exit fullscreen mode

33. SSR vs SSG vs CSR

Strategy Rendering Time Best For
CSR Browser Dashboards, internal apps
SSR Request Dynamic content
SSG Build Blogs, documentation
ISR / Revalidation Periodically Large content sites

For example:

Admin Dashboard

CSR
Enter fullscreen mode Exit fullscreen mode

because SEO is usually irrelevant.

Blog

SSG
Enter fullscreen mode Exit fullscreen mode

because articles don't change every second.

E-commerce Product Page

SSR / ISR
Enter fullscreen mode Exit fullscreen mode

because product information can be dynamic.


34. SSR + Hydration + API Data

Let's design a complete flow.

Suppose the user visits:

/products/123
Enter fullscreen mode Exit fullscreen mode

The process becomes:

                Browser
                   |
                   | GET /products/123
                   v
              SSR Server
                   |
                   | Fetch product
                   v
                Backend
                   |
                   v
               Database
                   |
                   v
             Product Data
                   |
                   v
            Render Angular
                   |
                   v
                 HTML
                   |
                   v
                Browser
                   |
                   v
             Display HTML
                   |
                   v
          Download JavaScript
                   |
                   v
              Hydration
                   |
                   v
         Interactive Product
Enter fullscreen mode Exit fullscreen mode

This is the architecture you should have in mind when thinking about SSR.


35. A More Realistic Product Example

Imagine the server receives:

GET /products/123
Enter fullscreen mode Exit fullscreen mode

The API returns:

{
  "id": 123,
  "name": "MacBook Pro",
  "price": 1999,
  "description": "Powerful laptop for developers"
}
Enter fullscreen mode Exit fullscreen mode

SSR generates:

<article>
  <h1>MacBook Pro</h1>

  <p>$1999</p>

  <p>
    Powerful laptop for developers
  </p>

  <button>
    Add to Cart
  </button>
</article>
Enter fullscreen mode Exit fullscreen mode

The user immediately sees:

MacBook Pro
$1999
Powerful laptop for developers

[ Add to Cart ]
Enter fullscreen mode Exit fullscreen mode

Then hydration connects:

button click
     ↓
Angular event listener
     ↓
addToCart()
     ↓
application state
     ↓
UI update
Enter fullscreen mode Exit fullscreen mode

36. Common SSR Mistakes

Mistake #1: Using window Everywhere

Bad:

const width = window.innerWidth;
Enter fullscreen mode Exit fullscreen mode

During server rendering:

window = undefined
Enter fullscreen mode Exit fullscreen mode

Use platform-aware APIs or execute browser-only logic after the application is running in the browser.


Mistake #2: Using localStorage During SSR

Bad:

const token = localStorage.getItem('token');
Enter fullscreen mode Exit fullscreen mode

The server doesn't have browser localStorage.

You need a server-safe strategy.


Mistake #3: Random Values

Bad:

const id = Math.random();
Enter fullscreen mode Exit fullscreen mode

The server and client can produce different values.


Mistake #4: Current Time

Bad:

new Date()
Enter fullscreen mode Exit fullscreen mode

when its result becomes part of rendered markup.

The server and client can disagree.


Mistake #5: Different Data

Server:

{
  "price": 100
}
Enter fullscreen mode Exit fullscreen mode

Client:

{
  "price": 110
}
Enter fullscreen mode Exit fullscreen mode

The DOM can mismatch.


37. How to Think About SSR Code

When writing code for SSR, ask:

Can this code execute on a server?

If the answer is no, isolate it.

Examples:

window
document
localStorage
sessionStorage
navigator
geolocation
Web APIs
Enter fullscreen mode Exit fullscreen mode

These are browser-specific capabilities.

The application should have a clear boundary between:

Universal Code
Enter fullscreen mode Exit fullscreen mode

and:

Browser-only Code
Enter fullscreen mode Exit fullscreen mode

38. The Universal JavaScript Model

SSR applications often follow this model:

             Application Code
                    |
           ┌────────┴────────┐
           │                 │
           ▼                 ▼
        Server             Browser
           │                 │
           ▼                 ▼
        Render             Hydrate
           │                 │
           └────────┬────────┘
                    ▼
              Same Application
Enter fullscreen mode Exit fullscreen mode

The same application logic can participate in two environments.

That's why SSR applications are sometimes described as:

Isomorphic / Universal Applications


39. Hydration Mismatch Debugging Strategy

When you see a hydration error, don't immediately blame the framework.

Check these first:

1. Random values

Math.random()
Enter fullscreen mode Exit fullscreen mode

2. Dates

new Date()
Enter fullscreen mode Exit fullscreen mode

3. Browser APIs

window
document
localStorage
Enter fullscreen mode Exit fullscreen mode

4. Conditional rendering

if (window.innerWidth > 768)
Enter fullscreen mode Exit fullscreen mode

5. Different API results

Server data ≠ Client data
Enter fullscreen mode Exit fullscreen mode

6. Invalid HTML

For example, invalid nesting can cause browsers to normalize the DOM differently.


40. SSR Security Considerations

SSR also introduces security concerns.

Never blindly inject server data into HTML.

Be careful with:

User-generated content
HTML injection
XSS
serialized application state
cookies
authentication data
Enter fullscreen mode Exit fullscreen mode

For example, if server state is serialized into the page:

<script>
  window.__DATA__ = {...}
</script>
Enter fullscreen mode Exit fullscreen mode

that data must be safely serialized.

Never expose secrets such as:

Database passwords
API private keys
Internal credentials
Server-only environment variables
Enter fullscreen mode Exit fullscreen mode

SSR code runs on the server, so you must carefully separate:

PUBLIC configuration
Enter fullscreen mode Exit fullscreen mode

from:

SERVER-ONLY secrets
Enter fullscreen mode Exit fullscreen mode

41. Performance Optimization Strategy

A good SSR architecture should optimize more than rendering.

Consider:

                SSR Performance
                       |
        ┌──────────────┼──────────────┐
        │              │              │
        ▼              ▼              ▼
     Server          Network        Client
      │                │              │
      ▼                ▼              ▼
   Rendering          CDN         Hydration
      │                │              │
      ▼                ▼              ▼
    Caching         Compression    JS Size
Enter fullscreen mode Exit fullscreen mode

Optimize:

  • server rendering
  • API latency
  • database queries
  • HTML size
  • JavaScript bundle size
  • hydration cost
  • caching
  • CDN delivery

SSR isn't a magic performance switch.

It changes where the work happens.


42. The Deeper Architecture

The evolution looks like this:

                 Web Application Evolution

CSR
 │
 │ Browser renders everything
 ▼
SSR
 │
 │ Server renders initial HTML
 ▼
SSR + Hydration
 │
 │ Server HTML + client interactivity
 ▼
Partial / Selective Hydration
 │
 │ Hydrate only what needs JavaScript
 ▼
Streaming / Progressive Rendering
 │
 │ Send HTML progressively
 ▼
Modern Full-Stack Rendering
Enter fullscreen mode Exit fullscreen mode

The goal isn't:

"Move everything to the server."

The goal is:

Put each piece of work where it is most efficient.


43. A Complete Mental Model

When a user opens an SSR application:

1. Browser sends HTTP request
          ↓
2. Server receives request
          ↓
3. Application executes on server
          ↓
4. Server fetches required data
          ↓
5. Components render to HTML
          ↓
6. Server sends HTML
          ↓
7. Browser parses HTML
          ↓
8. User sees content
          ↓
9. Browser downloads JavaScript
          ↓
10. Framework starts
          ↓
11. Hydration begins
          ↓
12. Existing DOM is reused
          ↓
13. Event handlers become active
          ↓
14. Application becomes interactive
Enter fullscreen mode Exit fullscreen mode

If you understand these 14 steps, you understand the core of SSR + hydration.


44. The Key Difference in One Diagram

CSR

Request
   ↓
HTML Shell
   ↓
Download JS
   ↓
Execute JS
   ↓
Render UI
   ↓
Interactive
Enter fullscreen mode Exit fullscreen mode

SSR

Request
   ↓
Server Render
   ↓
HTML
   ↓
Display UI
   ↓
Download JS
   ↓
Hydration
   ↓
Interactive
Enter fullscreen mode Exit fullscreen mode

The critical difference is:

CSR:
Render → Browser

SSR:
Render → Server
Enter fullscreen mode Exit fullscreen mode

And hydration bridges:

Server HTML
     ↓
Client JavaScript
     ↓
Interactive DOM
Enter fullscreen mode Exit fullscreen mode

45. When Should You Use SSR?

SSR is especially useful when you care about:

SEO
+
Initial rendering
+
Content discoverability
+
Social previews
+
Performance on slower devices
Enter fullscreen mode Exit fullscreen mode

Good candidates include:

  • e-commerce
  • blogs
  • documentation
  • marketing websites
  • news platforms
  • public product pages
  • content platforms

46. When CSR May Be Better

SSR isn't always necessary.

For example:

Admin Dashboard
Internal CRM
Back-office application
Private analytics platform
Enter fullscreen mode Exit fullscreen mode

These applications often don't need SEO.

CSR can be simpler:

Browser
   ↓
JavaScript
   ↓
Application
Enter fullscreen mode Exit fullscreen mode

Sometimes simplicity is more valuable than SSR.


47. SSR Is an Architectural Decision

Don't add SSR simply because:

"SSR is faster."

Ask instead:

Do I need SEO?
Do I need fast initial content?
Is my content dynamic?
Can my server handle rendering?
Do I have caching?
How large is my client bundle?
How expensive is hydration?
Enter fullscreen mode Exit fullscreen mode

The answer determines whether SSR is appropriate.


48. Final Architecture

A modern application can look like:

                         USER
                          |
                          v
                       Browser
                          |
                          v
                         CDN
                          |
                 ┌────────┴────────┐
                 │                 │
              Cache HIT         Cache MISS
                 │                 │
                 v                 v
                HTML          SSR Server
                                   |
                     ┌─────────────┼─────────────┐
                     │             │             │
                     v             v             v
                   API          Database       Cache
                     |
                     v
                 Application
                     |
                     v
                Render HTML
                     |
                     v
                  Browser
                     |
                     v
                JavaScript
                     |
                     v
                 Hydration
                     |
                     v
              Interactive UI
Enter fullscreen mode Exit fullscreen mode

This is the architecture behind many modern web applications.


49. Final Takeaways

If you remember only a few things from this article, remember these:

1. CSR

The browser renders the application.

Browser → JavaScript → UI
Enter fullscreen mode Exit fullscreen mode

2. SSR

The server renders the initial HTML.

Server → HTML → Browser
Enter fullscreen mode Exit fullscreen mode

3. Hydration

The client connects JavaScript behavior to the server-rendered HTML.

HTML + JavaScript → Interactive UI
Enter fullscreen mode Exit fullscreen mode

4. SSR does not eliminate JavaScript

It moves the responsibility for the initial render.

5. Hydration should reuse the server DOM

The goal is to avoid unnecessarily rendering the same UI twice.

6. Server and client must agree

Different output can cause hydration mismatches.

7. Browser APIs require special attention

window
document
localStorage
navigator
Enter fullscreen mode Exit fullscreen mode

may not exist on the server.

8. SSR has a cost

You trade some client-side rendering work for server-side rendering work.

9. Caching matters

SSR + CDN + caching can produce a powerful architecture.

10. Modern rendering is not simply CSR vs SSR

Modern frameworks increasingly combine:

SSR
+
Hydration
+
Partial Hydration
+
Streaming
+
Caching
+
Client-side Interactivity
Enter fullscreen mode Exit fullscreen mode

The real goal is to decide where and when each piece of work should happen.


Conclusion

Server-Side Rendering and Hydration are not just framework features.

They represent a fundamental architectural shift in how web applications are delivered.

Instead of forcing the browser to build everything from scratch:

JavaScript
   ↓
Render
   ↓
UI
Enter fullscreen mode Exit fullscreen mode

we can let the server produce meaningful HTML first:

Server
   ↓
HTML
   ↓
Browser
Enter fullscreen mode Exit fullscreen mode

and then use hydration to transform that HTML into a fully interactive application:

Server-rendered HTML
        +
Client JavaScript
        ↓
     Hydration
        ↓
Interactive Application
Enter fullscreen mode Exit fullscreen mode

Once you understand this model, technologies such as Angular SSR, React Server Components, Next.js, Nuxt, streaming SSR, partial hydration, and modern full-stack rendering architectures become much easier to understand.

The most important idea is not simply:

"SSR makes websites faster."

It is:

SSR decides where the initial UI is rendered, while hydration connects that server-rendered UI to the client-side application.

That distinction is the foundation for understanding modern web rendering.


🚀 What to Learn Next

If you're building serious Angular/React applications, the natural progression after SSR and hydration is:

CSR
 ↓
SSR
 ↓
Hydration
 ↓
Transfer State
 ↓
Streaming SSR
 ↓
Partial / Selective Hydration
 ↓
Islands Architecture
 ↓
React Server Components
 ↓
Server Actions
 ↓
Edge Rendering
 ↓
Modern Full-Stack Architecture
Enter fullscreen mode Exit fullscreen mode

Understanding this progression gives you a much deeper understanding of how modern frontend frameworks actually work under the hood.

Top comments (0)