Astro Static, Hybrid, and Server Output Modes: A Complete Configuration Guide
Astro offers two distinct output modes—static (which absorbed the former hybrid behavior) that prerenders pages by default with optional server-side rendering via export const prerender = false, and server which forces SSR for every request—determining build artifacts, adapter requirements, and hosting architecture.
The withastro/astro framework provides flexible rendering strategies through its output configuration, allowing developers to optimize for static site generation or full server-side rendering. Understanding the differences between Astro's static and server-only output modes is essential for architecting performant applications, as this choice affects everything from build artifacts in packages/astro/src/core/ to adapter integration and runtime behavior.
Understanding Astro's Output Configuration
Astro defines its output behavior through the output field in astro.config.mjs. According to the type definitions in packages/astro/src/types/public/config.ts (lines 15-20), only two valid values exist: 'static' and 'server'. The former output: 'hybrid' option was removed in Astro 5, with its functionality merged into the static mode.
Static Output Mode (Formerly Hybrid)
In output: 'static' mode, Astro prerenders every page at build time by default, generating plain HTML files that can be served from a CDN. This behavior, previously called "hybrid" mode, allows specific pages to opt out of prerendering using the export const prerender = false directive.
As documented in packages/astro/src/core/README.md (line 46), the build pipeline treats static output as a hybrid generation process, creating HTML files for prerendered routes while reserving server runtime capabilities for opted-out routes.
Configuration Example
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
// All pages prerendered by default (Astro 5+)
output: 'static',
});
Opting Out of Prerendering
To force server-side rendering for specific routes in static mode, export the prerender constant:
---
// src/pages/dashboard.astro
export const prerender = false;
---
<h1>Dashboard (SSR)</h1>
<p>Personalized data for {Astro.request.user?.name}</p>
Server Output Mode
Setting output: 'server' forces every page to render on the server at request time. No HTML files are emitted during the build process; instead, Astro relies entirely on server-side rendering (SSR) for all routes. This mode requires an adapter capable of handling a full server runtime.
Configuration Example
// astro.config.mjs
import { defineConfig } from 'astro/config';
import node from '@astrojs/node';
export default defineConfig({
output: 'server',
adapter: node({
mode: 'standalone'
}),
});
---
// src/pages/index.astro
import { fetchProducts } from '../lib/api';
const products = await fetchProducts(); // Executes on every request
---
<h1>Product Catalogue (SSR)</h1>
<ul>
{products.map(p => <li>{p.name}</li>)}
</ul>
Key Differences: Static vs Server Output
Understanding the architectural implications of each mode helps determine the optimal configuration for your project.
Rendering Timing
- Static mode: Pages build as HTML files at build time, with optional SSR for specific routes using
prerender = false. - Server mode: Every request triggers server-side rendering; no static HTML files exist.
Adapter Requirements
- Static mode: Adapters treat the build as a static site, copying generated HTML files to the deployment output. They require only minimal runtime capabilities for non-prerendered pages.
- Server mode: Adapters expect a full server runtime because every request may hit a server-rendered route, requiring continuous backend availability.
Performance and Cost
- Static mode: Most traffic serves from a CDN (static files), minimizing latency and cost. Server-rendered routes incur compute costs only for pages that explicitly require dynamic data.
- Server mode: Every request hits a server, increasing latency and requiring payment for continuously running backend infrastructure.
Ideal Use Cases
- Static mode: Content-heavy sites requiring the speed of static files but needing a handful of dynamic endpoints (authentication, API routes, personalized pages).
- Server mode: Fully dynamic applications such as dashboards, e-commerce carts, or real-time data displays where every page depends on request-time data.
Migrating from Hybrid to Static (Astro 5+)
The output: 'hybrid' option was removed in Astro 5, with its behavior merged into output: 'static'. As noted in packages/astro/CHANGELOG.md (around line 5295), the new static mode provides the exact same functionality—prerendering by default with opt-out support—without requiring experimental flags.
Before (Astro <5):
// astro.config.mjs
export default defineConfig({
output: 'hybrid',
experimental: { hybridOutput: true },
});
After (Astro 5+):
// astro.config.mjs
export default defineConfig({
output: 'static', // Same behaviour as old 'hybrid'
});
Summary
- Astro provides two output modes defined in
packages/astro/src/types/public/config.ts:'static'and'server'. - Static mode (formerly hybrid) prerenders all pages at build time by default, allowing specific routes to opt into SSR via
export const prerender = false. - Server mode forces SSR for every request, emitting no static HTML files and requiring a full server runtime adapter.
- The
output: 'hybrid'option was removed in Astro 5; useoutput: 'static'to achieve the same behavior. - Choose static mode for content-heavy sites with occasional dynamic needs, and server mode for fully dynamic applications.
Frequently Asked Questions
What happened to Astro's hybrid output mode?
Astro removed the output: 'hybrid' configuration option in version 5, merging its functionality into output: 'static'. As documented in packages/astro/CHANGELOG.md, the new static mode behaves exactly like the old hybrid mode—prerendering pages by default while supporting server-side rendering for routes that export prerender = false.
Can I mix static and server-rendered pages in the same Astro project?
Yes, but only when using output: 'static'. In static mode, all pages are prerendered at build time by default, but you can opt individual pages out of prerendering by adding export const prerender = false to the frontmatter. This creates a hybrid architecture where most content serves from a CDN while specific routes (like authentication pages or dashboards) render on the server.
Which output mode should I choose for a content-heavy blog with a few dynamic features?
Use output: 'static' (the default). This mode generates static HTML files for all your blog posts at build time, allowing them to be cached on a CDN for maximum performance. For the few dynamic features—such as a personalized user dashboard or authentication callbacks—simply add export const prerender = false to those specific page files to enable server-side rendering only where needed.
What are the performance implications of using server-only output mode?
Server mode (output: 'server') increases latency and hosting costs because every page request triggers server-side rendering with no static HTML files to serve from the edge. As implemented in packages/astro/src/core/, this mode requires a continuously running backend and an adapter capable of handling full SSR workloads, making it ideal for highly dynamic applications but less efficient for content that rarely changes.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →