Skip to content

feat: add caching layer with ISR and unstable_cache for improved performance#1441

Merged
danieltott merged 9 commits intomainfrom
JoeKarow/caching
Dec 2, 2025
Merged

feat: add caching layer with ISR and unstable_cache for improved performance#1441
danieltott merged 9 commits intomainfrom
JoeKarow/caching

Conversation

@JoeKarow
Copy link
Member

Linked Issue

N/A

Description

This PR implements a comprehensive caching strategy for the Virtual Coffee website using Next.js's Incremental Static Regeneration (ISR) and unstable_cache API to improve performance and reduce API calls.

Changes Made:

1. ISR Configuration for Pages

  • Added revalidate exports to key pages:
    • Home page (/) - revalidates every 12 hours
    • Events page (/events) - revalidates every 12 hours
    • Members page (/members) - revalidates every 24 hours
    • Podcast pages (/podcast, /podcast/[slug]) - revalidate every 24 hours

2. Data Layer Caching with unstable_cache

  • src/data/events.ts: Wrapped getEvents with cache (12-hour TTL, tag: events)
  • src/data/members/index.ts: Wrapped getMembers with cache (24-hour TTL, tag: members)
  • src/data/podcast.ts: Wrapped getEpisodes, getEpisode, and getTranscript with cache (24-hour TTL, tag: podcast)
  • src/data/sponsors.ts: Wrapped getSponsors with cache (24-hour TTL, tag: sponsors)

3. Enhanced Cache Revalidation Route

  • Updated src/app/_cache/route.ts to support tag-based revalidation via ?tag= query parameter
  • Allows on-demand cache invalidation by tag (e.g., /_cache?tag=events to revalidate all events-related cache)
  • Path-based revalidation still supported via ?path= parameter

4. Bug Fix

  • Added optional chaining in sponsors.ts (sponsor.tier?.id) to prevent potential crashes when sponsor tier is null

Files Modified (10 files):

  • src/app/%5Fcache/route.ts
  • src/app/events/page.tsx
  • src/app/members/page.tsx
  • src/app/page.tsx
  • src/app/podcast/[slug]/page.tsx
  • src/app/podcast/page.tsx
  • src/data/events.ts
  • src/data/members/index.ts
  • src/data/podcast.ts
  • src/data/sponsors.ts

Methodology

Why these changes?

  1. Netlify Serverless Function Usage Spike: After upgrading from Next.js 15.0.0-rc to 15.5.4, Netlify Serverless Function usage dramatically increased. This is due to Next.js 15's change in default caching behavior—pages and data fetches are no longer cached by default, causing every request to trigger serverless function invocations.

  2. Performance: CMS and external API calls (events, podcast, sponsors, members) are expensive operations. Caching reduces load times and API rate limiting concerns.

  3. ISR + unstable_cache dual-layer approach:

    • ISR handles page-level caching for static generation
    • unstable_cache provides data-level caching that works across different pages sharing the same data
  4. Tag-based revalidation: Enables surgical cache invalidation. When content is updated in the CMS, a webhook can call /_cache?tag=podcast to invalidate only podcast-related caches without affecting other cached data.

  5. Cache duration rationale:

    • Events: 12 hours (moderate frequency updates)
    • Members/Podcast/Sponsors: 24 hours (less frequent updates)

Code of Conduct

By submitting this pull request, you agree to follow our Code of Conduct

Add revalidate exports to enable Incremental Static Regeneration:
- Homepage and events: 12 hours (43200s)
- Podcast and members pages: 24 hours (86400s)
Wrap getEvents with unstable_cache for 12-hour caching with 'events' tag.
Wrap getSponsors with unstable_cache for 24-hour caching with 'sponsors' tag.
Also fix null safety issue when sponsor.tier is null.
Wrap getEpisodes, getEpisode, and getTranscript with unstable_cache
for 24-hour caching with 'podcast' tag.
Wrap getMembers with unstable_cache for 24-hour caching with 'members' tag.
Support revalidating by cache tag in addition to path:
- /_cache?tag=events - invalidates events cache
- /_cache?tag=sponsors - invalidates sponsors cache
- /_cache?tag=podcast - invalidates podcast cache
- /_cache?tag=members - invalidates members cache
@JoeKarow JoeKarow requested a review from a team as a code owner November 25, 2025 20:11
@netlify
Copy link

netlify bot commented Nov 25, 2025

👷 Deploy Preview for virtual-coffee-io processing.

Name Link
🔨 Latest commit c94993b
🔍 Latest deploy log https://app.netlify.com/projects/virtual-coffee-io/deploys/692f36d338b12700084c954c

@JoeKarow JoeKarow self-assigned this Nov 25, 2025
Copy link
Member

@danieltott danieltott left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JoeKarow this is great - thank you so much for getting this rolling!

@danieltott danieltott merged commit ecd1cae into main Dec 2, 2025
4 of 5 checks passed
@danieltott danieltott deleted the JoeKarow/caching branch December 2, 2025 18:59
@danieltott danieltott mentioned this pull request Dec 8, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants