All articles
SEO & GrowthJuly 4, 2026 6 min read

Rendering Strategy for Programmatic SEO: SSR, ISR, or Static at 200k Pages

SSR, ISR, or full static export? At 200k programmatic pages the answer stops being a preference and starts being a budget line. Here's how we pick.

Rendering Strategy for Programmatic SEO: SSR, ISR, or Static at 200k Pages

Every programmatic SEO project hits the same wall around 50k–100k pages: the rendering strategy that felt clever at launch becomes the reason your build times cross an hour, your TTFB spikes on the pages Google actually cares about, or your infra bill quietly triples. Picking between SSR, ISR, and static export isn't a stylistic choice at that scale — it's a load-bearing architectural decision. Here's how we think about it when we ship these systems.

The three options, honestly framed

Before anything else, let's strip the marketing off each mode.

Static Site Generation (SSG) means every page is HTML on disk at build time. The CDN serves it. TTFB is essentially network latency. The cost is your build pipeline.

Server-Side Rendering (SSR) means every request renders a page on demand. TTFB depends on your data layer, your runtime, and how well you cache. The cost is compute per request plus the operational surface area of a live backend.

Incremental Static Regeneration (ISR) — Next.js's term, but the pattern exists in Nuxt, Astro, SvelteKit, and Gatsby under other names — means pages are generated on first request, cached at the edge, and revalidated on a schedule or on demand. It's a hybrid: static for readers, lazy for builds.

At small scale, all three work. The interesting question is what breaks first when your sitemap grows past 200k URLs.

What actually fails at scale

In our experience running programmatic sites for clients in travel, jobs, and marketplaces, the failure modes are pretty predictable.

Build time (the SSG killer)

A pure static build of 200k pages, each hitting a database or an API during rendering, tends to fall over somewhere between 45 minutes and several hours depending on parallelism and data fetching patterns. That's fine until you need to ship a template fix on Friday afternoon and your deploy pipeline becomes a hostage situation.

Worse, most CI providers charge by build minute. A 90-minute build running twice a day, plus feature branches, plus previews, adds up fast.

Cold TTFB (the SSR killer)

Googlebot doesn't care about your P50. It cares about P95 and P99 on the long tail — the pages that get crawled once a month. On SSR, those pages are almost always cold. Cold means a database round trip, template render, and any third-party calls you were sloppy enough to leave synchronous.

If your P95 TTFB on rarely-crawled URLs is 1.8s, Googlebot notices. Crawl rate drops. Discovery of new programmatic pages slows. You now have an SEO problem masquerading as a performance problem.

Cache stampedes (the ISR killer)

ISR looks like a free lunch until the day you push a template change that invalidates the whole cache, and 40,000 URLs get hit in the same hour by a mix of Googlebot, Bingbot, and real users. Every one of those requests goes to your origin. Your database melts. Welcome to your first cache stampede.

A decision framework we actually use

We don't pick a rendering mode by page count alone. We look at four axes:

  1. Data volatility — does the page content change hourly, daily, or monthly?
  2. Traffic distribution — is it a fat head (10% of pages get 90% of traffic) or a true long tail?
  3. Template complexity — how expensive is a single render?
  4. Team constraints — do you have infra people on call, or is this a two-engineer product team?

Rough heuristics we apply:

  • Pure SSG works up to roughly 30k–50k pages, or higher if renders are cheap and data is stable. Great for glossaries, location pages with slow-moving data, spec sheets.
  • ISR with generous revalidation is our default for 50k–500k pages when data changes daily-ish. Fat-head pages get pre-rendered at build; the long tail generates on demand.
  • SSR with aggressive edge caching wins when data volatility is high (pricing, inventory, availability) and you can't tolerate stale HTML.
  • Hybrid per-route is what actually ships in production. Different page templates get different modes.

The hybrid pattern in practice

Here's a stripped-down Next.js App Router example showing per-route strategy on a marketplace-style site:

// app/category/[slug]/page.tsx — high-traffic, stable
export const revalidate = 86400; // 24h ISR
export async function generateStaticParams() {
  // Pre-build only the top 5k categories at deploy time
  const top = await db.categories.findTop(5000);
  return top.map((c) => ({ slug: c.slug }));
}

// app/listing/[id]/page.tsx — volatile pricing, long tail
export const revalidate = 300; // 5min ISR
export const dynamicParams = true;

// app/search/[query]/page.tsx — truly dynamic
export const dynamic = 'force-dynamic';
// SSR with a 60s edge cache header set in middleware

The important detail: generateStaticParams returns only the fat head. The rest are generated on first hit and cached. You get the SEO benefits of static for the pages that matter most, without the build-time explosion.

Cache design is the actual product

Once you commit to ISR or SSR-with-caching, the cache layer stops being infrastructure and starts being a first-class part of the SEO product. A few rules we live by:

Stale-while-revalidate is your friend

Always serve stale content while regenerating in the background. Googlebot gets HTML immediately; your data freshens for the next request. Every serious CDN — Cloudflare, Fastly, Vercel's edge — supports this natively.

Cache-Control: public, s-maxage=3600, stale-while-revalidate=86400

That header alone has saved more programmatic sites than any technical SEO audit.

Separate the cache key from the URL

If your page varies by country, currency, or A/B test, do not let those variants share a URL with different content. Either put them in the path, or set Vary correctly and accept the cache hit rate collapse. Googlebot cloaking rules aside, mixed-content caches are how you end up serving USD prices to EU users and vice versa.

Purge intelligently, not globally

When your data pipeline updates 12,000 listings overnight, do not invalidate the whole cache. Tag pages with content IDs at render time, and purge by tag. Cloudflare, Fastly, and Vercel all support this. It's the difference between a cache warm-up that takes minutes and one that takes days.

What we measure after launch

Rendering strategy isn't set-and-forget. We instrument three things from day one:

  • Origin hit rate per route template — if it climbs above 5% for ISR pages, something is bypassing cache. Usually a rogue query param.
  • P95 TTFB segmented by crawl source — Googlebot vs. real users vs. Bingbot. If Googlebot's P95 diverges from users', you have a cold-cache problem specifically affecting SEO.
  • Build duration trend — if it's growing linearly with page count, you didn't actually adopt ISR, you just added ISR on top of SSG. Fix generateStaticParams.

GA4 and GSC will tell you the downstream story — indexed pages, impressions, crawl stats — but the rendering-layer metrics are what let you act before the SEO impact shows up in Search Console two weeks later.

The war story

We inherited a jobs site running full SSG on ~180k pages. Builds took 2h 40min. The team was terrified of deploys. Any template change meant a full rebuild, and job listings were stale by up to a day because incremental data updates required a rebuild too.

We migrated to ISR with revalidate = 600 on listing pages, kept SSG for the ~8k category and city landing pages (the fat head that pulled most organic traffic), and moved search results to SSR with a 90-second edge cache. Build time dropped to 11 minutes. Freshness improved from 24 hours to 10 minutes. Indexed pages went up over the following two months, not down — the fear that ISR would hurt crawl was unfounded once cache hit rates settled above 92%.

The lesson wasn't "ISR beats SSG." It was that treating every page template the same was the actual bug.

Where we'd start

If you're staring at a growing programmatic site and wondering whether to migrate: don't rewrite everything. Instead, spend a day segmenting your URL templates by traffic and data volatility. Pick the one template that's most painful — usually the highest-volume, most-volatile one — and change only that route's rendering mode. Ship it behind a feature flag, watch your origin hit rate and P95 TTFB for a week, then move to the next template.

We do this kind of rendering-strategy audit as part of our performance and SEO engineering work, and the honest truth is that the biggest wins almost never come from picking the "right" mode. They come from admitting that different pages deserve different modes, and building the pipeline to support that.

#Programmatic SEO#Rendering#Performance#Next.js#Infrastructure

Want a team like ours?

72Technologies builds production software for the kind of teams who actually read this blog.

Start a project