If you’re running a self-hosted site on a Raspberry Pi, a Proxmox VM, or pushing deploys to Cloudflare Pages on a free tier, your SSG choice has real consequences — not philosophical ones. Build time means CI minutes or local CPU cycles. Bundle size means bandwidth and storage. This article cuts through the hype and gives you numbers to make an actual decision.
The Benchmark Setup
The reference benchmarks tested Astro 5, Hugo 0.120, and Jekyll 4 across three content set sizes: 10, 100, and 500 Markdown pages. Cold builds (no cache) and warm builds (incremental/cached) were measured separately. Here’s a condensed view of what matters:
| Generator | 100 pages (cold) | 500 pages (cold) | Output size (100 pages) |
|---|---|---|---|
| Hugo | ~0.3s | ~1.1s | ~2.1 MB |
| Jekyll | ~6s | ~38s | ~3.4 MB |
| Astro | ~8s | ~52s | ~4.8 MB |
Hugo is in a different category. It’s not slightly faster — it’s an order of magnitude faster. Jekyll and Astro are closer to each other, with Astro edging out Jekyll only on warm rebuilds when its Vite-based dev server kicks in.
When Build Speed Actually Matters
For most homelab sites and small blogs, it doesn’t. A 52-second cold build on a 500-page site runs once per deploy. If you deploy twice a day, that’s under two minutes of compute. On a Raspberry Pi 4 you might double those numbers, but you’re still not paying by the minute for local hardware.
Build time starts mattering in these specific situations:
Cloudflare Pages free tier caps build minutes. If you’re running multiple projects and pushing frequently, a Hugo site gives you far more headroom before you hit limits or need to upgrade.
CI/CD pipelines with paid runners — GitHub Actions, GitLab CI. Every second of build time has a cost. Hugo’s sub-second builds can keep you well within free tier limits; Astro at 52 seconds for 500 pages adds up across branches and PRs.
Content-heavy sites scaling past 1,000 pages. Astro’s build time grows roughly linearly with content. At 1,000 pages you’re looking at 100+ seconds cold. Hugo stays under 3 seconds. That’s a different class of tool.
Local development iteration loops. Astro’s dev server with HMR is excellent for component-heavy work. Hugo’s watch mode is faster for pure content editing. Jekyll’s watch mode is sluggish and the gap widens with site size.
What the Bundle Size Difference Costs You
Astro outputting ~4.8 MB for 100 pages vs Hugo’s ~2.1 MB sounds significant. In practice, for static hosting it rarely translates to real costs.
On Cloudflare Pages, you get 500 MB per site with unlimited bandwidth on the free tier. You’d need a very large site before asset size becomes a constraint.
On a homelab with nginx serving over a local network or through a Cloudflare Tunnel, the difference is negligible. A 2.7 MB delta across the entire site output is not a per-request cost — it’s a one-time storage cost.
Where it does matter: object storage backends. If you’re syncing your build output to S3-compatible storage (Wasabi, Backblaze B2, MinIO on your NAS), you pay for storage and egress. Hugo’s leaner output adds up over time if you’re versioning deployments.
For a homelab MinIO sync workflow the math looks like this over a year of daily deploys with 10 versions retained:
- Hugo: 2.1 MB × 10 = 21 MB retained
- Astro: 4.8 MB × 10 = 48 MB retained
At Backblaze B2 rates (~$0.006/GB/month) neither breaks the bank. But if your site grows to thousands of pages, the multiplier matters.
Running Jekyll Without the Ruby Headaches
Jekyll’s biggest practical problem isn’t build speed — it’s dependency management. Here’s a Docker Compose setup that eliminates the rbenv/rvm problem entirely:
# docker-compose.yml
services:
jekyll:
image: jekyll/jekyll:4.3.3
command: jekyll serve --watch --force_polling --drafts
ports:
- "4000:4000"
- "35729:35729"
volumes:
- .:/srv/jekyll
- jekyll_gems:/usr/local/bundle
environment:
- JEKYLL_ENV=development
volumes:
jekyll_gems:
Start it with:
docker compose up
# Build only (no server):
docker compose run --rm jekyll jekyll build
The jekyll_gems volume caches your gem bundle so subsequent starts don’t reinstall everything. This is the sanest way to run Jekyll in 2026 on any homelab box regardless of the host Ruby version.
Hugo for the Speed-Critical Case
If you’ve decided Hugo’s build speed is the right tradeoff, here’s a minimal build-and-deploy script for pushing to an S3-compatible bucket or rsync target:
#!/usr/bin/env bash
set -euo pipefail
BUILD_DIR="public"
REMOTE="user@homelab-nginx:/var/www/mysite"
echo "Building with Hugo..."
hugo --minify --gc
echo "Deploying to ${REMOTE}..."
rsync -avz --delete "${BUILD_DIR}/" "${REMOTE}/"
echo "Done. Build output: $(du -sh ${BUILD_DIR} | cut -f1)"
Run hugo --minify --gc — the --gc flag cleans up unused cache files and keeps your build directory lean.
Astro’s Real Advantage: Component-Driven Sites
If your site is mostly Markdown content, Hugo wins on every practical metric. But if you’re building something with interactive components — a dashboard, a docs site with search, a homelab status page that islands in some live data — Astro’s architecture earns its overhead.
Astro’s island architecture means you ship zero JavaScript by default and opt in component by component. Hugo requires external JavaScript tooling to get there. Jekyll doesn’t have a story for it at all.
For a homelab monitoring page that embeds a live Prometheus query result or a status widget, Astro lets you write:
---
// No import statements needed for static content
const buildTime = new Date().toISOString();
---
<section>
<p>Site built: {buildTime}</p>
<!-- Your static content here -->
</section>
And add one interactive island without hydrating the entire page. That’s genuinely useful for hybrid homelab dashboards.
The Decision Matrix
Choose Hugo if:
- Your site is primarily Markdown content
- You’re on Cloudflare Pages free tier with limited build minutes
- You’re deploying from a low-power device (Pi, old NAS)
- Site scale is 500+ pages or growing fast
Choose Astro if:
- You need component-driven pages or interactive islands
- Your team knows JavaScript and wants one language across the stack
- You’re building docs, a portfolio, or a hybrid content/app site
- Build time is not a constraint for your deployment pipeline
Choose Jekyll if:
- You’re maintaining an existing Jekyll site (migration cost isn’t worth it)
- You need GitHub Pages native support without custom Actions
- The ecosystem of plugins (jekyll-feed, jekyll-seo-tag) solves your needs already
For greenfield homelab sites in 2026: Hugo for pure content, Astro for anything interactive. Jekyll is legacy unless you have a specific reason.
[discussion]
Comments are powered by Giscus — backed by GitHub Discussions. Sign in with GitHub to join the conversation.