Skip to content

Gatsby SSR and DSG — Server-Side Rendering and Deferred Static Generation

DodaTech Updated 2026-06-28 5 min read

In this tutorial, you will learn about Gatsby SSR and DSG. We cover key concepts, practical examples, and best practices to help you master this topic.

Learn Gatsby Server-Side Rendering (SSR) and Deferred Static Generation (DSG) for dynamic content and faster builds with the Gatsby rendering options.

In this lesson, you'll understand SSR for real-time data, DSG for deferring page generation, and when to use each rendering mode.

What You'll Learn

How to use SSR for pages with user-specific or real-time data, DSG for deferring non-critical page generation, and the Gatsby Function API for Serverless backends.

Why It Matters

Not all pages need static generation. SSR handles dynamic data, DSG reduces build times for large sites, and Functions provide backend logic without a separate server.

flowchart TD
    A[Gatsby Rendering Modes] --> B[Static SSG]
    A --> C[SSR]
    A --> D[DSG]
    B --> E[Pre-built HTML]
    C --> F[Real-time per Request]
    D --> G[Lazy Deferred Build]
    style B fill:#639,color:#fff
    style C fill:#4a148c,color:#fff
    style D fill:#7b1fa2,color:#fff

Enabling SSR

Create server-side rendered pages:

// src/pages/user-profile.js
import React from 'react';

export async function getServerData(context) {
  // context includes: headers, method, url, query, params
  const userId = context.query.id;

  const response = await fetch(`https://api.example.com/users/${userId}`);
  const user = await response.json();

  return {
    props: { user },
    status: 200
  };
}

export default function UserProfile({ serverData }) {
  const { user } = serverData;

  return (
    <div>
      <h1>{user.name}</h1>
      <p>Email: {user.email}</p>
      <p>Role: {user.role}</p>
    </div>
  );
}

Output: Each request to /user-profile?id=42 fetches fresh data from the API and renders the page server-side. The page is not pre-built.

SSR with Cookies and Headers

Access request details for authentication:

export async function getServerData({ headers, query }) {
  const authHeader = headers.get('authorization');
  const token = authHeader?.replace('Bearer ', '');

  if (!token) {
    return {
      props: { user: null },
      status: 401,
      headers: {
        'WWW-Authenticate': 'Bearer'
      }
    };
  }

  const user = await verifyToken(token);
  return {
    props: { user },
    status: 200
  };
}

Output: The SSR page checks the authorization header. Unauthenticated requests receive a 401 response.

Deferred Static Generation (DSG)

Defer non-critical pages to reduce build time:

// gatsby-node.js
exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions;

  const result = await graphql(`
    query {
      allMarkdownRemark(filter: { frontmatter: { type: { eq: "archived" } } }) {
        nodes { fields { slug } }
      }
    }
  `);

  result.data.allMarkdownRemark.nodes.forEach(node => {
    createPage({
      path: node.fields.slug,
      component: path.resolve('./src/templates/archived-post.js'),
      context: { slug: node.fields.slug },
      defer: true  // This page is deferred — not built during initial build
    });
  });
};

Output: Archived posts are not built during gatsby build. Instead, they're generated on-demand when first requested, then cached.

Configuring DSG

DSG requires the gatsby-plugin-gatsby-cloud or hosting with DSG support:

// gatsby-config.js
module.exports = {
  trailingSlash: 'always',
  plugins: ['gatsby-plugin-gatsby-cloud']
};

Only pagess with defer: true on createPage are deferred. All other pages are statically generated as usual.

Gatsby Functions

Serverless backend logic in your Gatsby project:

// src/api/contact.js
export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { name, email, message } = req.body;

  if (!name || !email || !message) {
    return res.status(400).json({ error: 'Missing required fields' });
  }

  // Send email or store in database
  await sendEmail({ name, email, message });

  return res.status(200).json({ success: true });
}

Output: The function is available at /api/contact. Form submissions are processed server-side without exposing API keys.

Function with Authentication

// src/api/subscribe.js
export default async function handler(req, res) {
  const apiKey = req.headers['x-api-key'];

  if (apiKey !== process.env.NEWSLETTER_API_KEY) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const { email } = req.body;

  if (!email) {
    return res.status(400).json({ error: 'Email required' });
  }

  // Add to newsletter service
  const result = await addSubscriber(email);

  return res.status(201).json(result);
}

Common Mistakes

  1. Using SSR for everything: Most pages should be static. Use SSR only for pages that need real-time or user-specific data.
  2. Not handling errors in getServerData: Always wrap API calls in try-catch. Return appropriate status codes and fallback data.
  3. Deferring important pages: Only defer pages that aren't critical for initial SEO or user experience (archived content, old posts).
  4. Missing DSG hosting support: Not all hosting providers support DSG. Gatsby Cloud, Netlify, and Vercel support it.
  5. Using Functions for long-running tasks: Gatsby Functions have timeout limits (typically 10-30s). Use them for quick operations only.

Practice Questions

  1. What is the difference between SSR and SSG? Answer: SSG builds HTML at build time. SSR generates HTML per request with fresh data. SSR is slower but handles dynamic content.

  2. How do you make a page server-side rendered in Gatsby? Answer: Export an async getServerData function from the page component. It receives request context and returns props.

  3. What does defer: true do in createPage? Answer: Itmarks the page for DSG — it's not built during the initial build but is generated on first request.

  4. Where do Gatsby Functions live? Answer: In src/api/. Each file becomes a serverless function at /api/filename.

Challenge

Build a dashboard page that uses SSR to fetch real-time analytics data, a deferred archive page for old blog posts, and a Gatsby Function for newsletter subscription.

Mini Project

Create a site with three rendering modes: a static homepage, SSR user dashboard with real-time data, DSG archive pages for old content, and Gatsby Functions for contact form submission.

FAQ

Can I use SSR with client-side state?

: Yes. SSR generates the initial HTML. Client-side JavaScript hydrates the page, and hooks/context work normally.

Does DSG work with incremental builds?

: Yes. DSG is compatible with incremental builds. Only changed deferred pages are rebuilt.

Can I have both SSR and SSG in the same site?

: Yes. Each page can choose its rendering mode. Static pages, SSR pages, and DSG pages coexist.

How do I debug Gatsby Functions locally?

: Run gatsby develop. Functions are available at /api/*. Use console.log to debug — output appears in the terminal.

What's Next

Learn about Gatsby Image Optimization for advanced image handling and performance optimization techniques.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro