All ArticlesLanding Page Examples•November 2, 2026•12 min read

Landing Pages at 100M Views: Next.js vs Astro vs Hugo vs Eleventy — Build Latency, TTFB, and True Cost per Million Visitors Benchmarked

At 100M monthly views, landing-page performance is less about framework demos and more about cache hit ratio, build invalidation, and egress economics. This benchmark-driven guide compares Next.js, Astro, Hugo, and Eleventy on build latency, TTFB, Core Web Vitals, and true cost per million visitors.

Close-up of server racks in a data center highlighting modern technology infrastructure.Photo by panumas nikhomkhai on Pexels

At 100M monthly views, a landing page is a distributed cache with a content workflow attached. The framework matters, but not in the way most comparisons imply: build speed affects release velocity, TTFB affects conversion and crawl budget, and cost per million is dominated by bytes, cache misses, and compute that should never have run.

Define the Workload Before You Benchmark

A meaningful static site generator benchmark must fix the workload. The reference workload in this article is 100M monthly HTML page views, 500 CMS-backed landing pages, 10 deploys per day, 2 MB compressed transfer per view, and a 99.5% edge cache hit ratio for anonymous HTML. Images are served from an image CDN, analytics is asynchronous, and personalization is client-side or edge-cached as explicit variants. No logged-in HTML is cached publicly.

That traffic level is about 38.6 average requests per second when spread across 30 days, but landing-page traffic is bursty. Plan for a 6x peak factor, roughly 230-300 RPS, and test cache-cold behavior separately from cache-warm behavior. At 99.5% hit ratio, 100M views produce 500,000 origin renders per month. At 95%, the same traffic produces 5M origin renders, a 10x increase in TTFB-sensitive work and compute spend.

Build Latency: Release Velocity, Not Hot-Path TTFB

Build latency is often misused in framework debates. At 100M views, a healthy edge cache means the build system is not in the request path. Build latency matters because it controls editorial cadence, cache invalidation windows, rollback speed, and how safely you can rebuild after a headless CMS change.

The following ranges are directional, not universal. They assume 5,000 static marketing pages on a 4 vCPU CI runner with external image URLs and no heavy data transforms. Always benchmark your own templates, data sources, and plugins.

FrameworkCold build at 5k pagesIncremental pathRuntime model
Hugo5-30sFull rebuild, very fastGo binary, static output
Eleventy30-120sFull rebuild plus incremental pluginsNode.js, static output
Astro90-300sStatic pages plus islandsStatic HTML plus selective hydration
Next.js3-15 minISR, on-demand revalidation, static exportReact server rendering plus static/ISR

Hugo wins raw cold-build throughput for content-heavy sites. Eleventy offers flexible JavaScript data pipelines with predictable static output. Astro keeps pages static while allowing interactive islands. Next.js provides the richest React application model and incremental rendering, but its build and cache semantics require more operational discipline.

TTFB: Edge Hit Latency Beats Origin Render Latency

TTFB is a compound metric: DNS, TLS, edge lookup, cache status, origin fetch, rendering, and streaming. For anonymous landing pages, the biggest lever is not the framework. It is the cache hit ratio and cache header correctness. A static HTML object served from an edge POP can be 20-100 ms P50 in many regions. A server-rendered origin page is commonly 200-800 ms before cold starts, and p99 can be much worse.

Model TTFB as:

p50_ttfb ≈ edge_lookup + miss_ratio × origin_render_time

Lowering miss ratio from 5% to 0.5% reduces origin renders by 90% and removes tail latency from most users. Use s-maxage, stale-while-revalidate, and tag-based purge to absorb traffic spikes. Core Web Vitals still matter: TTFB influences LCP, while JavaScript and third-party tags usually decide INP. A landing page with excellent TTFB and a bloated tag manager can still lose conversion rate optimization gains.

Next.js: Fast When Static, Expensive When Accidentally Dynamic

Next.js can be an excellent 100M-view landing-page platform, but only if you keep routes static or ISR-cached and avoid per-request dynamic APIs. App Router caching is powerful and easy to invalidate correctly. It is also easy to invalidate accidentally with cookies(), headers(), searchParams, or uncached fetch calls.

ts
import { revalidatePath } from 'next/cache';

export const revalidate = 3600;

type LandingPage = { slug: string; headline: string; heroUrl: string };

async function getLandingPage(slug: string): Promise<LandingPage> {
  const res = await fetch(`https://cms.example.com/api/landing-pages/${slug}`, {
    next: { revalidate: 3600, tags: [`landing:${slug}`] },
  });
  if (!res.ok) throw new Error(`CMS fetch failed: ${res.status}`);
  return (await res.json()) as LandingPage;
}

export default async function Page({ params }: { params: Promise<{ slug: string }> }) {
  const { slug } = await params;
  const page = await getLandingPage(slug);
  return <main><h1>{page.headline}</h1></main>;
}

export async function POST(req: Request) {
  const secret = req.headers.get('x-revalidate-secret');
  if (!secret || secret !== process.env.REVALIDATE_SECRET) {
    return Response.json({ error: 'unauthorized' }, { status: 401 });
  }
  const body = (await req.json()) as { slug?: string };
  if (!body.slug) return Response.json({ error: 'slug required' }, { status: 400 });
  revalidatePath(`/lp/${body.slug}`);
  return Response.json({ revalidated: true });
}

Use generateStaticParams for known landing-page slugs, and prefer tag-based revalidation over rebuilding the entire site for one CMS edit. Watch middleware: it runs on matching requests and can introduce latency and cost at 100M views. The common failure mode is a route that looks static in development but becomes dynamic in production because a cookie or header is read during render.

Astro: Static HTML With Islands Where Interaction Pays Rent

Astro is a strong fit for marketing sites because the default is static HTML. React, Vue, Svelte, or Solid components hydrate only where explicitly marked with a client directive. That keeps JavaScript budgets low and makes edge caching simple. The trade-off is that app-like personalization and authenticated flows are less natural than in Next.js.

astro
---
export const prerender = true;

type LandingPage = { slug: string; headline: string; heroUrl: string };

export async function getStaticPaths() {
  const res = await fetch('https://cms.example.com/api/landing-pages');
  if (!res.ok) throw new Error(`CMS fetch failed: ${res.status}`);
  const slugs = (await res.json()) as string[];
  return slugs.map((slug) => ({ params: { slug } }));
}

const { slug } = Astro.params;
if (!slug) return Astro.redirect('/404');

const res = await fetch(`https://cms.example.com/api/landing-pages/${slug}`);
if (!res.ok) throw new Error(`CMS fetch failed: ${res.status}`);
const page = (await res.json()) as LandingPage;
---

<main>
  <h1>{page.headline}</h1>
  <img src={page.heroUrl} alt='' width='1200' height='630' loading='eager' fetchpriority='high' />
  <NewsletterForm client:visible />
</main>

Treat getStaticPaths and CMS fetches as build inputs. Cache CMS responses at the CI layer, rate-limit webhooks, and avoid injecting request-time secrets into static pages. Astro's island model is excellent for landing page performance, but a single eagerly hydrated analytics or experimentation widget can erase much of the advantage.

Hugo and Eleventy: Operational Simplicity at Scale

Hugo is the throughput leader for large content sets. It compiles to a static site with no client runtime by default, so origin infrastructure can be a bucket plus CDN. Eleventy is similarly static but embraces JavaScript data files and plugins, which is valuable for teams that need custom integrations without adopting a full framework runtime.

Both stacks benefit from aggressive edge caching. A production static-host header policy might look like this:

text
/lp/*
  Cache-Control: public, max-age=0, s-maxage=86400, stale-while-revalidate=604800

/assets/*
  Cache-Control: public, max-age=31536000, immutable

Keep HTML revalidation short enough for campaign changes, and fingerprint assets for immutable caching. If you use a headless CMS webhook, debounce it. A CMS import that triggers 500 deploys can cost more in CI and cache churn than the runtime savings from static generation.

True Cost per Million Visitors: Use a Workload Model

Vendor pricing pages rarely answer the right question. Model cost per million views with the variables that dominate at scale: egress bytes, edge requests, origin renders, image transforms, CI builds, and observability. This TypeScript model is intentionally auditable and rejects invalid inputs.

ts
type Workload = {
  monthlyViews: number;
  avgBytesPerView: number;
  cacheHitRatio: number;
  cdnEgressUsdPerGb: number;
  edgeRequestUsdPerMillion: number;
  originRenderUsdPerMillion: number;
  imageTransformUsdPerThousand: number;
  imageTransformsPerMillionViews: number;
  monthlyCiBuildUsd: number;
  observabilityUsd: number;
};

function costPerMillionViews(w: Workload): { totalMonthlyUsd: number; cpmUsd: number; egressUsd: number; originRenders: number } {
  if (w.monthlyViews <= 0) throw new Error('monthlyViews must be > 0');
  if (w.cacheHitRatio < 0 || w.cacheHitRatio > 1) throw new Error('cacheHitRatio must be in [0,1]');
  if (w.avgBytesPerView <= 0) throw new Error('avgBytesPerView must be > 0');

  const egressGb = (w.monthlyViews * w.avgBytesPerView) / 1_000_000_000;
  const egressUsd = egressGb * w.cdnEgressUsdPerGb;
  const edgeUsd = (w.monthlyViews / 1_000_000) * w.edgeRequestUsdPerMillion;
  const originRenders = w.monthlyViews * (1 - w.cacheHitRatio);
  const originUsd = (originRenders / 1_000_000) * w.originRenderUsdPerMillion;
  const transformsUsd = ((w.monthlyViews / 1_000_000) * w.imageTransformsPerMillionViews / 1000) * w.imageTransformUsdPerThousand;
  const totalMonthlyUsd = egressUsd + edgeUsd + originUsd + transformsUsd + w.monthlyCiBuildUsd + w.observabilityUsd;

  return { totalMonthlyUsd, cpmUsd: totalMonthlyUsd / (w.monthlyViews / 1_000_000), egressUsd, originRenders };
}

const result = costPerMillionViews({
  monthlyViews: 100_000_000,
  avgBytesPerView: 2_000_000,
  cacheHitRatio: 0.995,
  cdnEgressUsdPerGb: 0.03,
  edgeRequestUsdPerMillion: 0.5,
  originRenderUsdPerMillion: 15,
  imageTransformUsdPerThousand: 0.5,
  imageTransformsPerMillionViews: 5_000,
  monthlyCiBuildUsd: 250,
  observabilityUsd: 500,
});

console.log(result);

With those illustrative inputs, egress is roughly 200 TB per month and often dominates the bill. At $0.03 per GB, egress alone is about $6,000 per month, or $60 per million views. Framework compute only becomes the headline when cache hit ratio falls or image transforms are uncapped. This is why static site generator benchmark results must be paired with CDN and image-pipeline economics.

Core Web Vitals: JavaScript Budgets Decide INP

All four stacks can produce excellent Core Web Vitals. The risk profile differs. Hugo and Eleventy generally ship minimal client JavaScript. Astro ships only island code. Next.js can be fast but carries React hydration and routing costs unless the page is carefully composed.

StackTypical client JS riskMain CWV concern
HugoVery lowLarge unoptimized images
EleventyLow to moderatePlugin and analytics creep
AstroLow to moderateToo many hydrated islands
Next.jsModerate to highHydration, middleware, dynamic rendering

Optimize the LCP image with dimensions, fetchpriority, and AVIF/WebP. Defer non-critical scripts, self-host fonts, and audit third-party tags quarterly. For conversion rate optimization, test with real-user monitoring, not only lab Lighthouse runs.

Edge Caching and Invalidation: The Real Enterprise Architecture Test

At 100M views, cache key design is architecture. Avoid Vary: Cookie on anonymous landing pages; it fragments the cache and destroys hit ratio. Put personalization behind client-side fetches or explicit edge variants. Purge by surrogate key or tag. Use stale-while-revalidate so a cache miss does not become a thundering herd. Rate-limit CMS webhooks and serialize revalidation to prevent invalidation storms.

For Next.js, verify the route is statically rendered or ISR-backed. For Astro, Hugo, and Eleventy, verify that HTML is not accidentally served with no-store. For every stack, test from multiple geographies and inspect cache status headers at the edge, not just at the origin.

Production Checklist for 100M-View Landing Pages

  • Measure P50, P75, and P95 TTFB by cache status and region.
  • Target 99%+ HTML edge hit ratio for anonymous pages; 99.5%+ for aggressive scale.
  • Set s-maxage and stale-while-revalidate on HTML; fingerprint and immutably cache assets.
  • Purge by tag or surrogate key, never wildcard purge the whole site during a campaign.
  • Benchmark builds with real CMS data, not placeholder Markdown.
  • Keep client JavaScript and third-party tags on a budget.
  • Compress and resize hero images at the image CDN; cap transform variants.
  • Load test at 6x average RPS and include cache-cold cases.
  • Model cost per million with egress, transforms, ISR writes, CI, and observability.
  • Add RUM and synthetic checks for LCP, INP, CLS, and cache hit ratio.

Decision Matrix: Choose the Constraint You Want to Own

Choose Next.js when the landing page is part of a React product surface, needs incremental static regeneration, or requires app-like personalization and A/B infrastructure. Choose Astro when content velocity, static HTML, and selective interactivity are the priorities. Choose Hugo when build speed and minimal operations dominate a large content corpus. Choose Eleventy when you want JavaScript data pipelines with a static, framework-light output.

All four can serve 100M views. The differentiator is not the generator logo. It is cache discipline, image economics, invalidation design, and JavaScript restraint.

Sources & Technical References

0 views•0 comments

Discussion (0)

Join the conversation

Loading comments...

Continue Reading

More production-grade engineering deep dives and architectural guides

Explore all articles