Deferred Static Generation in Gatsby: When, How, and What to Watch
Use Gatsby’s Deferred Static Generation (DSG) to cut build times on large sites. Learn the right pages to defer, how data flows, and operational checks to avoid stale content and latency spikes.
20 Oct 2025, 07:00 UTC

Problem & Takeaway
Large Gatsby sites can spend hours rebuilding when a single content change hits the CMS. Deferred Static Generation (DSG) lets you skip rendering a subset of pages at build time and generate them on the first request instead. The key takeaway: defer only low‑traffic, long‑tail pages that can tolerate a brief latency spike and that never need per‑request data.
When to Use DSG
- Pages that are rarely visited (e.g., older blog posts, niche product detail pages).
- Content that changes infrequently or can live a few minutes stale (e.g., static FAQ answers).
- Sites where build times are a bottleneck and you want to keep CI/CD pipelines fast.
High‑traffic landing pages, dashboards, or pages that require user‑specific data should remain fully static or use SSR/Client‑side fetching.
Minimal Design Pattern
The smallest effective DSG setup involves three steps:
- Mark pages as deferred in
gatsby-node.js.exports.createPages = async ({ graphql, actions }) => { const { createPage } = actions; const result = await graphql(` query { allMarkdownRemark { nodes { id, slug } } } `); result.data.allMarkdownRemark.nodes.forEach(node => { createPage({ path: node.slug, component: require.resolve('./src/templates/post.js'), context: { id: node.id }, defer: true // <‑‑ defer the render }); }); }; - Ensure build‑time data is baked in. The page’s GraphQL query runs during the build and the resulting data is stored in the page’s JSON file. No live CMS call happens on the first request.
export const query = graphql` query PostById($id: String!) { markdownRemark(id: { eq: $id }) { frontmatter { title, date } html } } `; - Deploy to a runtime that supports DSG. Gatsby Cloud, Netlify Functions, or a self‑hosted adapter that exposes
gatsby serveare required. Static file hosts (e.g., plain S3) cannot render deferred pages.
Trust Boundaries & Data Flow
Deferred pages still use Gatsby’s GraphQL layer at build time. They cannot access request‑time data such as cookies, query strings, or authentication state. If a page needs real‑time values, move the logic to a client‑side fetch or an SSR route.
Because the data is baked into the JSON file, any change in the CMS requires a rebuild to update the page. A stale page will continue to serve the old content until the next rebuild or cache invalidation.
Operational Checks
- First‑hit latency monitoring – Track the response time of deferred routes. A sudden increase may indicate a cold start or insufficient cache warming.
# Example: latency threshold via Prometheus rate(http_request_duration_seconds_bucket{le="5"}[5m]) - Error rate on deferred routes – Ensure the rendering function has access to all required environment variables. Missing vars often surface as 500 errors on the first hit.
# Example: error rate alert sum(rate(http_errors_total{status=~"5.."}[5m])) - Cache header verification – After the first request, the page should be cached with a long
Cache‑Controlheader.Header Typical Value Cache‑Control public, max-age=31536000, immutable Expires Sun, 01 Jan 2030 00:00:00 GMT - Rebuild webhook validation – Verify that content‑update webhooks trigger a rebuild that invalidates the deferred page. After a CMS change, request the page again and confirm the updated content appears.
Failure Modes
- Cold start latency spike – The first request to a deferred page incurs a rendering cost. Mitigate by pre‑warming key routes or using a CDN edge function that caches the result.
- Stale content – Without a rebuild, the page continues to serve old data. Define a clear rebuild policy (e.g., webhook‑triggered or scheduled nightly) and monitor cache invalidation.
- Environment variable leakage – The rendering function runs in a Node.js environment. Missing
GATSBY_prefixed env vars will cause runtime errors. Usegatsby-config.jsto expose only the variables needed. - Unsupported hosting – Deploying to a pure static bucket will cause 404s for deferred routes. Confirm the host supports
gatsby serveor a compatible adapter.
When to Reconsider DSG
- Traffic shifts: If a previously low‑traffic page becomes hot, move it back to a full static build to eliminate the cold‑start penalty.
- Real‑time data requirement: If the content must reflect user state or live metrics, replace DSG with SSR or client‑side fetching.
- Operational constraints: If your team cannot maintain a Node.js runtime or manage rebuild hooks, it may be safer to accept longer builds and keep all pages static.
Practical Checklist
- Identify candidate pages (traffic < 100 views/day). Score them for staleness tolerance.
- Mark them with
defer: trueingatsby-node.js. - Deploy to a DSG‑capable host.
- Set up monitoring for latency, error rate, and cache headers.
- Configure CMS webhooks to trigger rebuilds on content changes.
- Periodically run a script to fetch a sample of deferred pages and compare the output to the CMS snapshot.
Summary
Deferred Static Generation is a powerful tool to trim build times on large Gatsby sites, but it comes with clear boundaries: no per‑request data, reliance on build‑time GraphQL, and a need for a runtime that can render on demand. By deferring only low‑traffic, stale‑tolerant pages, ensuring proper hosting, and monitoring the key metrics, you can keep your builds fast without compromising user experience.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.