Dilip Singh logo
All posts
Web DevelopmentIntermediate2025-06-10·9 min read

Next.js 15 Performance: Server Components, Caching & Core Web Vitals

A practical guide to squeezing maximum performance from Next.js 15 — React Server Components, granular caching strategies, streaming Suspense boundaries, image optimization, and hitting 100 on Lighthouse.

The Mental Model Shift

Next.js 15 with React 19 changes how you think about performance. The default is now "render on the server, hydrate nothing unless necessary." Every component is a Server Component by default. You add 'use client' when the component actually needs interactivity.

This means most of your code runs zero JavaScript on the client.

Server Components vs Client Components

tsx
// app/blog/page.tsx — Server Component (default)
// Fetches data at request time, sends HTML to client
// Zero JavaScript bundle impact

import { getBlogPosts } from '@/lib/blog'

export default async function BlogPage() { const posts = await getBlogPosts() // Direct DB/API call — no useEffect

return (

{posts.map(post => ( ))}
) } ```

tsx
// components/SearchBox.tsx — Client Component
// Needs useState, useEffect, event handlers

'use client' import { useState } from 'react'

export function SearchBox({ onSearch }: { onSearch: (q: string) => void }) { const [query, setQuery] = useState('') return ( { setQuery(e.target.value); onSearch(e.target.value) }} /> ) } ```

Granular Caching

tsx
// Cache for 1 hour, revalidate on demand
const posts = await fetch('/api/posts', {
  next: { revalidate: 3600, tags: ['blog-posts'] }
})

// Force-dynamic (never cache) const userData = await fetch('/api/me', { cache: 'no-store' })

// Revalidate specific tags from a Server Action import { revalidateTag } from 'next/cache' export async function publishPost(slug: string) { await db.update({ slug, published: true }) revalidateTag('blog-posts') // Clears all caches tagged 'blog-posts' } ```

Streaming Suspense Boundaries

tsx
import { Suspense } from 'react'

export default function DashboardPage() { return (

Dashboard

{/ Fast: renders immediately /}

{/ Slow: streams in when ready, shows skeleton first /} }>

}>

) } ```

Image Optimization

tsx
import Image from 'next/image'

// Always use next/image — automatic WebP/AVIF conversion + lazy loading Hero ```

Core Web Vitals Checklist

MetricTargetCommon Fix
LCP< 2.5sPreload hero image, use priority prop
FID / INP< 200msMove heavy work to Server Components
CLS< 0.1Always set width/height on images
TTFB< 800msUse edge runtime for dynamic routes
DS
Dilip Singh
Lead Software Architect · Hureka Technologies

14+ years building enterprise software and AI systems. Architecting multi-agent AI platforms, RAG pipelines, voice AI, and high-performance SaaS for global clients.