All ArticlesPortfolio•October 27, 2026•12 min read

Edge Rendering vs Static Generation: 2026 Portfolio Benchmarks

A hard look at TTFB, egress cost, and Core Web Vitals for developer portfolios across Vercel, Cloudflare, and AWS. Learn when static-first wins, when edge rendering pays off, and how to benchmark it without vendor hype.

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

The 2026 Portfolio Reality: Static Content, Global Audience

Developer portfolios are mostly static artifacts: case studies, project summaries, résumé PDFs, Open Graph images, and a contact form. The content changes when you ship, not when a user requests it. That makes static generation the default architecture, not a compromise. Edge rendering is still useful, but it should be an exception with a measurable reason: personalization, auth-gated previews, geo routing, A/B variants, or request-time API composition.

The performance question is not whether edge compute is fast. It is whether you need compute in the request path at all. A CDN-served static HTML document can hit cache at the edge with no function invocation, no cold start, and no origin fetch. That is the baseline every edge-rendered portfolio must beat.

Benchmark Methodology: What to Measure and What the Numbers Mean

The ranges below are a reproducible 2026 benchmark framework, not vendor SLAs. Model a portfolio with 40 project pages, 1.2 MB median page weight, global traffic from 10 regions, and p75 field data. Test three paths:

  1. Static HTML at CDN edge with immutable assets.
  2. Edge SSR with cached HTML and stale-while-revalidate.
  3. Origin SSR through a CDN or Lambda@Edge.

Measure TTFB at p75 from real-user monitoring, not a single laptop. TTFB is diagnostic, not a Core Web Vital. The CWV targets remain LCP <= 2.5s, INP <= 200ms, and CLS <= 0.1 at p75.

ArchitectureTTFB p75LCP p75INP p75Egress risk
Static HTML on CDN30-90 ms0.8-1.6 s50-120 msLow to medium
Edge SSR with warm cache80-220 ms1.1-2.0 s70-160 msMedium
Edge SSR on cache miss180-450 ms1.8-3.2 s100-220 msMedium to high
Lambda@Edge cold path250-700 ms2.2-4.0 s120-260 msHigh
Origin SSR400-900 ms3.0-5.0 s150-350 msHigh

The table is intentionally directional. Your CMS, bundle size, image strategy, and cache hit ratio will move these bands more than the logo on the dashboard. For portfolios, the only reliable conclusion is stable: static HTML wins TTFB and LCP unless edge rendering removes a much slower origin dependency or enables a business-critical dynamic feature.

Why edge rendering often loses on TTFB

Edge rendering puts compute in the request path. Even with a warm isolate or function, the platform must parse the request, run your code, possibly fetch data, serialize HTML, and apply cache headers. Static generation does that work once at build time. The CDN then serves bytes.

Edge compute wins when it removes a transoceanic origin round trip that static generation cannot avoid. But if your HTML is already cached at 300+ edge locations, there is no origin round trip to remove.

The cache-miss tax

The dangerous benchmark is not the warm request. It is the p95 cache miss during a deploy, a purge, or a viral post. Edge SSR cache misses can amplify origin load and egress. If every request invokes a function, your bill and latency tail grow with traffic. Static generation turns traffic spikes into CDN hits.

Egress Cost Math for a Developer Portfolio

Egress is where portfolios quietly become expensive. The formula is simple:

monthly_egress_gb = (monthly_visits * pages_per_visit * avg_page_weight_mb) / 1024

For 100,000 visits, 3 pages per visit, and 1.2 MB per page, that is about 352 GB per month. At a hypothetical $0.15/GB, user-facing bandwidth alone is about $53. Add image transformations, function invocations, and origin egress, and the real number can double. Static-first architecture reduces function invocations to near zero and makes caching predictable.

Cloudflare R2 is notable because it has zero egress fees to the public internet when paired with Cloudflare CDN, which is attractive for portfolio media. AWS CloudFront and Vercel bandwidth are metered by contract and tier. The architectural lesson is not 'pick the cheapest logo.' It is 'keep large media off the dynamic path, cache HTML aggressively, and measure the cost per 1,000 visits.'

Reference Architecture: Static-First, Edge-Aware

The production pattern is static-first with edge-aware routing:

  • Build all content pages at deploy time from Markdown or a CMS.
  • Hash and cache static assets for one year with immutable.
  • Serve HTML with short shared-cache TTLs and stale-while-revalidate.
  • Use edge middleware for redirects, locale negotiation, and auth gates, not for rendering every page.
  • Put contact forms and search behind small serverless endpoints with rate limits.
  • Serve case-study media from an object store with image resizing at build time or at the image CDN.

Next.js static generation with typed CMS data

ts
type Project = {
  slug: string;
  title: string;
  summary: string;
  updatedAt: string;
};

async function getProjects(): Promise<Project[]> {
  const cmsUrl = process.env.CMS_URL;
  const token = process.env.CMS_TOKEN;

  if (!cmsUrl || !token) {
    throw new Error('CMS_URL and CMS_TOKEN must be configured');
  }

  const response = await fetch(`${cmsUrl}/api/projects`, {
    headers: { authorization: `Bearer ${token}` },
    next: { revalidate: 3600 },
  });

  if (!response.ok) {
    throw new Error(`CMS request failed with status ${response.status}`);
  }

  return (await response.json()) as Project[];
}

export async function generateStaticParams(): Promise<Array<{ slug: string }>> {
  try {
    const projects = await getProjects();
    return projects.map((project) => ({ slug: project.slug }));
  } catch (error) {
    const detail = error instanceof Error ? error.message : 'unknown error';
    throw new Error(`Unable to generate portfolio routes: ${detail}`);
  }
}

This keeps the portfolio build deterministic. If the CMS is down, the build fails loudly instead of shipping a half-rendered site.

Cloudflare Worker for cache-safe static assets

ts
export interface Env {
  ASSETS: Fetcher;
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method !== 'GET' && request.method !== 'HEAD') {
      return new Response('Method Not Allowed', {
        status: 405,
        headers: { allow: 'GET, HEAD' },
      });
    }

    try {
      const assetResponse = await env.ASSETS.fetch(request);
      const headers = new Headers(assetResponse.headers);

      headers.set(
        'Cache-Control',
        'public, max-age=0, s-maxage=300, stale-while-revalidate=86400',
      );
      headers.set('X-Edge-Mode', 'static-assets');

      return new Response(assetResponse.body, {
        status: assetResponse.status,
        headers,
      });
    } catch (error) {
      const detail = error instanceof Error ? error.message : 'unknown error';
      return new Response(`Edge asset failure: ${detail}`, {
        status: 502,
        headers: { 'Cache-Control': 'no-store' },
      });
    }
  },
};

The worker is deliberately boring. It serves prebuilt assets and lets the CDN cache them. That is the right use of edge compute for a portfolio: routing, headers, and safety rails, not rendering every case study.

Platform Comparison: Vercel vs Cloudflare vs AWS

Vercel

Vercel is the lowest-friction path for Next.js portfolios. Static pages, ISR, image optimization, and edge functions are integrated. The trade-off is metered bandwidth and platform lock-in around framework features. Use it when developer experience and Next.js integration matter more than granular cost control.

Cloudflare

Cloudflare Workers, Pages, and R2 are strong for cost-sensitive portfolios with global static assets. Workers have excellent cold-start behavior and R2 changes the egress math. The trade-off is a more explicit runtime model, fewer Node.js APIs, and more responsibility for build and cache semantics.

AWS

CloudFront plus S3 is a durable static baseline. Lambda@Edge adds request-time logic, but cold starts and operational complexity are real. AWS wins when you already have IAM, CloudFront, WAF, and observability standards. It is rarely the simplest choice for a solo developer portfolio.

Core Web Vitals Playbook for Portfolios

LCP is usually the hero image or largest text block. Preload the hero image, serve AVIF or WebP, set explicit width and height, and avoid lazy-loading above-the-fold media. INP is usually JavaScript. A portfolio should ship minimal client JavaScript: no heavy animation library for a résumé, no client-side router hydration for static case studies. CLS is usually fonts and media. Use font-display: swap, size-adjust fallbacks, and reserved media boxes.

TTFB matters because it starts the LCP clock. Static HTML with CDN caching gives the best repeatable TTFB. Edge SSR can be acceptable, but only with cache hit ratios above 90% and a warm path. Monitor p75 and p95 separately; p95 is where cold starts and cache misses appear.

Production Checklist and Pitfalls to Avoid

  • Pre-render all portfolio pages and invalidate by deployment, not by broad purge.
  • Cache hashed assets for one year with immutable; keep HTML TTLs short.
  • Use stale-while-revalidate for HTML, but never for personalized or auth-gated responses.
  • Keep query strings canonical; unbounded parameters destroy cache hit ratios.
  • Serve media from R2, S3, or an image CDN; do not route large files through edge functions.
  • Measure with RUM and CrUX, not one synthetic run from one region.
  • Set budget alerts for egress, function invocations, and image transformations.
  • Test the cold path: deploy, purge, and measure p95 before trusting a benchmark.

Avoid these traps: caching personalized HTML at the edge, using edge SSR for content that changes monthly, assuming edge compute always beats a CDN, and comparing vendors with different cache hit ratios. A benchmark without cache state is marketing.

Final Recommendation

For a developer portfolio in 2026, static generation is the correct default. Use edge rendering only for the narrow cases that need request-time decisions: auth previews, geo routing, A/B variants, or API composition that cannot be prebuilt. If you do run edge rendering, cache it, cap it, and measure the p95 cache-miss cost. The winning portfolio architecture is not the one with the most edge functions. It is the one that delivers a fast LCP, a stable INP, and a predictable bill.

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