# How Astro's Hybrid SSG/SSR Rendering Strategy Works: Build-Time vs Request-Time Rendering

> Discover how Astro's hybrid SSG SSR rendering blends build-time and request-time strategies. Learn to optimize your site's performance and flexibility with Astro's powerful rendering engine.

- Repository: [Astro/astro](https://github.com/withastro/astro)
- Tags: internals
- Published: 2026-03-06

---

**Astro blends Static Site Generation (SSG) and Server-Side Rendering (SSR) by allowing each route to opt into prerendering at build time or stay dynamic at request time, using a unified rendering engine that outputs either static HTML files or server responses.**

The `withastro/astro` repository implements a flexible **hybrid SSG/SSR rendering strategy** that eliminates the traditional binary choice between static and dynamic architectures. By inspecting route-level exports and leveraging a shared rendering pipeline, Astro enables developers to deploy high-performance static pages alongside real-time server-rendered endpoints within a single codebase.

## Route-Level Prerender Configuration

Astro determines whether to generate a page at build time or render it on-demand by scanning for an exported `prerender` constant in each route file. In [`packages/astro/src/core/routing/prerender.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/routing/prerender.ts), the system uses the `PRERENDER_REGEX` to extract this flag:

```ts
const PRERENDER_REGEX = /^\s*export\s+const\s+prerender\s*=\s*(true|false);?/m;

```

If the export is absent, Astro falls back to the global `prerender` setting from `astro.config.mjs` via `getPrerenderDefault`. When a route is explicitly marked as non-prerendered, the build output shifts to server mode:

```ts
if (!route.prerender) settings.buildOutput = 'server';

```

- **`export const prerender = true`** triggers **static generation** during the build process.
- **`export const prerender = false`** keeps the route **dynamic**, requiring server-side execution at request time.

## Build-Time Static Generation (SSG Pipeline)

During the `astro build` command, Astro instantiates the **default prerenderer** through `createDefaultPrerenderer` in [`packages/astro/src/core/build/default-prerenderer.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/build/default-prerenderer.ts). This Node-based prerenderer processes all routes where `prerender === true`.

The prerenderer imports the build entry bundle and creates a `BuildApp` instance. It gathers static routes—including those expanded by `getStaticPaths`—and invokes the rendering engine for each:

```ts
app.render(request, { routeData })

```

Despite using the same internal engine as runtime SSR, the prerenderer captures the output and writes the resulting HTML directly to the filesystem rather than returning an HTTP response.

## Runtime Server-Side Rendering (SSR Pipeline)

For routes with `prerender` set to `false`, Astro utilizes the runtime server renderer defined in [`packages/astro/src/runtime/server/render/astro/render.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/render/astro/render.ts). The primary entry points are `renderToString`, `renderToReadableStream`, and `renderToAsyncIterable`.

The rendering flow executes as follows:

1. `callComponentAsTemplateResultOrResponse` generates a **template result** from the component.
2. The template result's `.render(destination)` method streams chunks to a `RenderDestination`.
3. For page routes, the renderer automatically injects the DOCTYPE declaration and buffers `<head>` content.
4. The completed HTML string or streaming response is transmitted to the client.

## The Unified Rendering Engine

Both SSG and SSR execution paths leverage the identical core engine located in [`render.ts`](https://github.com/withastro/astro/blob/main/render.ts). Whether pre-generating files during the build or responding to live HTTP requests, Astro invokes the same `renderToString` or streaming functions.

This architectural consistency allows developers to author components once using `.astro` syntax or UI framework components, while Astro optimizes the delivery method based on the route-level `prerender` flag. Static pages maximize CDN cacheability and eliminate compute costs, whereas dynamic pages execute per-request logic such as authentication checks or database queries.

## Summary

- Astro determines rendering mode at the **route level** via the exported `prerender` constant, detected by `PRERENDER_REGEX` in [`packages/astro/src/core/routing/prerender.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/core/routing/prerender.ts).
- The **default prerenderer** (`createDefaultPrerenderer`) processes static routes during `astro build`, writing HTML directly to disk using the same engine as runtime SSR.
- **Runtime SSR** uses `renderToString` and streaming variants in [`packages/astro/src/runtime/server/render/astro/render.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/render/astro/render.ts) to generate responses on demand for non-prerendered routes.
- Both strategies share a **unified rendering pipeline**, allowing seamless mixing of static and dynamic content without requiring different component authoring patterns.

## Frequently Asked Questions

### What happens if I don't export a prerender constant?

If you omit the `export const prerender` declaration, Astro falls back to the global `prerender` default specified in `astro.config.mjs`. The system checks this via `getPrerenderDefault` in the routing logic, applying the same build-time or server-mode logic based on that configuration value.

### Can I use getStaticPaths with prerender = false?

No. The `getStaticPaths` function is designed specifically for static site generation and requires `export const prerender = true` to function. When `prerender` is `false`, Astro expects the route to handle dynamic parameters at request time rather than pre-generating paths during the build.

### How does Astro handle streaming for SSR routes?

According to [`packages/astro/src/runtime/server/render/astro/render.ts`](https://github.com/withastro/astro/blob/main/packages/astro/src/runtime/server/render/astro/render.ts), Astro supports multiple output modes including `renderToReadableStream` and `renderToAsyncIterable`. These methods create a template result that writes chunks incrementally to the `RenderDestination`, enabling streaming HTML responses for improved Time to First Byte (TTFB) on dynamic pages.

### Is the rendering queue architecture used for .astro files?

Currently, queue-based rendering via [`render-async-iterable.ts`](https://github.com/withastro/astro/blob/main/render-async-iterable.ts) is disabled for `.astro` files. The renderer in [`render.ts`](https://github.com/withastro/astro/blob/main/render.ts) handles `.astro` components with direct string buffering or streaming approaches, while the async iterable queue system remains available for other rendering contexts within the Astro ecosystem.