September 20, 2024
10k+ pages + improved Core Web VitalsScaling Travel Platform: High-Performance Static Generation at Scale
Improved page load performance and SEO footprint while scaling to 10k+ destination pages
- Performance and UX: Moved initial load from multi-second to ~sub-second/low-seconds territory on key pages (representative). Improved Core Web Vitals and reduced mobile bounce.
- SEO footprint: Made destination pages reliably indexable at scale. Improved metadata and structured data hygiene for richer search presence.
- Delivery efficiency: Reduced build and deployment overhead (hours → ~10–20 minutes for iterative builds, representative) via ISR and caching, enabling faster iteration.
Scope & constraints
- Role
- Lead Engineer
- Scope
- performance, SEO, large-scale static generation
- Constraints
- thousands of pages, freshness requirements, and mobile performance
Role & Scope
- Team: frontend + platform stakeholders (representative)
- Responsibility: rendering strategy, performance targets, and delivery pipeline
- Stakeholders: product, growth/SEO, and content owners
- Constraints: thousands of pages, freshness requirements, and mobile performance
Outcome metrics
- Performance: moved key pages from multi-second to ~sub-second/low-seconds (representative)
- SEO: increased indexable footprint with consistent metadata and structured data hygiene
- Delivery: iterative builds reduced from hours to ~10–20 minutes (representative)
Context
I led the frontend architecture for a travel booking platform that needed to serve detailed destination pages for thousands of locations worldwide. Each page included rich content (descriptions, photos, reviews, recommendations) and needed to rank well in search engines.
The existing implementation was a client-side rendered React application. While it provided a good user experience for returning visitors, it had significant drawbacks: slow initial page loads, poor SEO performance, and high infrastructure costs from server-side rendering every request.
Problem
The core challenges:
SEO performance: Client-side rendering meant search engines struggled to index our content. We were losing organic traffic to competitors with better-optimized sites.
Page load performance: First Contentful Paint (FCP) was often 3-4 seconds, especially on mobile devices. Users were bouncing before content loaded.
Scale and build times: We needed to generate thousands of pages, but traditional static site generation would take hours to build, making deployments impractical.
Content freshness: Destination information (prices, availability, reviews) changed frequently. We needed a strategy to keep content fresh without rebuilding the entire site.
Approach
We migrated to Next.js with a hybrid rendering strategy that balanced performance, SEO, and operational complexity:
Static generation strategy:
- Used
getStaticPathswithfallback: 'blocking'to generate popular destinations at build time - Implemented Incremental Static Regeneration (ISR) with stale-while-revalidate for less-trafficked pages
- Prioritized page generation based on traffic analytics—top destinations built at deploy time
Performance optimizations:
- Implemented aggressive image optimization with next/image (WebP, lazy loading, responsive sizes)
- Code splitting by route and component to minimize initial bundle size
- Prefetching critical data and assets for likely navigation paths
- CDN caching strategy with appropriate cache headers (immutable assets, short TTLs for HTML)
Build pipeline improvements:
- Parallelized page generation across multiple workers
- Implemented build caching to avoid regenerating unchanged pages
- Created preview environments with subset of pages for faster feedback during development
SEO enhancements:
- Structured data (JSON-LD) for destination pages with rich snippets
- Optimized meta tags (title, description, Open Graph, Twitter Cards) per page
- XML sitemap generation with priority based on page importance
- Proper heading hierarchy and semantic HTML
Outcomes
- Performance and UX: Moved initial load from multi-second to ~sub‑second/low‑seconds territory on key pages (representative), improving Core Web Vitals and reducing bounce on mobile.
- SEO footprint: Made destination pages reliably indexable at scale and improved metadata/structured data hygiene for richer search presence.
- Delivery efficiency: Reduced build and deployment overhead (hours → ~10–20 minutes for iterative builds, representative) via ISR and caching, enabling faster iteration.
Stack / Constraints
Stack: Next.js with TypeScript, Static Site Generation (SSG) with Incremental Static Regeneration (ISR), CDN caching strategy, next/image optimization.
Constraints: Thousands of destination pages, content freshness requirements, mobile performance targets, and build time limitations.
Decisions & Tradeoffs
- SSG/ISR vs. SSR: Optimized for SEO and performance while keeping freshness acceptable with ISR and cache strategy.
- Build time vs. completeness: Prioritized high-traffic pages at deploy time and generated the long tail on-demand to keep releases practical.
- Caching vs. correctness: Tuned TTLs and revalidation to balance cost, freshness, and operational simplicity.
What I'd Do Differently
Earlier adoption of edge functions: We relied heavily on CDN caching, but some personalization features still required client-side logic. Edge functions (like Vercel Edge Functions or Cloudflare Workers) would have allowed us to move more logic closer to users while maintaining performance.
More sophisticated ISR strategy: Our initial ISR implementation used fixed revalidation times. A more event-driven approach (revalidating on content updates) would have provided better freshness guarantees.
Better analytics integration: We should have instrumented performance metrics (Core Web Vitals) in production from day one to understand real-world performance, not just lab tests.
Incremental migration path: We did a big-bang migration which was risky. A gradual rollout (starting with a subset of pages) would have reduced risk and allowed us to learn and adjust the approach.
The project successfully demonstrated that static generation can scale to thousands of pages while maintaining excellent performance and SEO. The patterns we established became the foundation for other content-heavy sections of the platform.