BlogCache Components

Last update

Interactive demo of how to cache individual fields of a record with different strategies in Next.js 16, improving perceived latency and reducing infrastructure load during request time.

The Problem

Imagine you have a product with 3 fields:

  • Text (name + description): Rarely changes
  • Price: Changes occasionally
  • Stock: Must always be updated

How do you cache each field independently?

❌ What DOES NOT work

// Trying to selectively cache from a single object
async function ProductPage({ productId }) {
  // A single query brings everything
  const product = await db.query("SELECT * FROM products WHERE id = ?");

  // How do I cache only the price?
  // How do I NOT cache the stock?
  return (
    <div>
      {product.name} - ${product.price} - Stock: {product.stock}
    </div>
  );
}

It doesn't work because: Once you have the complete object, you cannot selectively apply use cache to individual fields.

✅ The Solution

Each field is a separate async component with its own query and cache strategy.

export default function ProductPage({ params }) {
  return (
    <Suspense fallback={<PageSkeleton />}>
      <ProductContent params={params} />
    </Suspense>
  );
}

async function ProductContent({ params }) {
  const { id } = await params;

  return (
    <div>
      {/* FIELD 1: Cached text */}
      <ProductText productId={id} />

      {/* FIELD 2: Cached price */}
      <ProductPrice productId={id} />

      {/* FIELD 3: Stock without cache */}
      <Suspense fallback={<StockSkeleton />}>
        <ProductStock productId={id} />
      </Suspense>
    </div>
  );
}

Important: The Suspense goes in the parent, not inside the async component.

Architecture

ProductPage (sync - static)

└─ <Suspense>
   └─ ProductContent (async - accesses params)
      ├─ ProductText (async + 'use cache')
      ├─ ProductPrice (async + 'use cache')
      └─ <Suspense>
         └─ ProductStock (async without cache)

Visual Comparison

At build time, Next.js prerenders the page: - ✅ ProductText executes query → included in static shell - ✅ ProductPrice executes query → included in static shell - ❌ ProductStock DOES NOT execute (requires request context) Result: HTML with text and price already rendered

Next steps

On this page