Astro + Vercel: Choosing static vs hybrid output for low‑traffic cost reduction
0 reputation · 13 Jun 2025, 01:08 UTC
0 reputation · 13 Jun 2025, 01:08 UTC
An Astro project is deployed to Vercel. The site contains a handful of dynamic pages that require server‑side rendering, but the majority of content is static. The objective is to keep monthly compute usage (and thus cost) as low as possible while still supporting the dynamic routes.
Astro offers two output modes:
output: "static" – fully static build, no runtime required.output: "hybrid" – mix of static pages and SSR routes.Key constraints:
prerender flag be used to selectively pre‑render pages that would otherwise be SSR, and what impact does that have on build time versus runtime cost?35775 reputation · 13 Jun 2025, 07:45 UTC
To minimize compute costs on Vercel for a low-traffic site with a small percentage of dynamic content, use output: 'hybrid' in your Astro configuration. In this mode, all pages are pre-rendered as static HTML by default, incurring zero runtime compute cost. You then explicitly opt-in only the necessary dynamic routes to Server-Side Rendering (SSR).
astro.config.mjs:
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
});
.astro files for your dynamic routes, add the following export to disable pre-rendering:
export const prerender = false;
Runtime Cost vs. Route Count
On Vercel, compute costs are driven by invocations (requests to a function) and execution time, not by the number of SSR routes defined in your code. Having 100 routes marked prerender = false costs nothing if no one visits them; however, a single high-traffic SSR route can quickly exhaust a free tier.
prerender = true (or leaving it as the default in hybrid mode) shifts the compute burden from the request phase to the build phase.
Static pre-rendering becomes "more expensive" only when the number of pages is so high (high-cardinality) that build times exceed CI limits or memory thresholds, forcing a move to SSR for those specific paths.
To verify your configuration is working as intended:
Diagnostic Detail Needed: Are your dynamic routes based on a small, predictable set of IDs, or are they generated from an external API with thousands of unique entries? If the latter, the build-time memory limit may dictate whether you use prerender = true or false.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.