DEVPROTON
← Insights·ENGINEERING

What We Learned Building Production Apps with Next.js 15

April 20, 2026·2 min read
What We Learned Building Production Apps with Next.js 15

Next.js 15 landed with some opinionated changes — async request APIs, stricter caching defaults, Turbopack graduating to stable. We've been running it in production for six months across three client projects. Here's the unfiltered version.

The caching model finally makes sense

The biggest mental shift in App Router is moving from getStaticProps / getServerSideProps thinking to per-fetch caching decisions. In Next.js 15, fetches are not cached by default. You opt in.

// Cached, revalidates every 60 seconds
const data = await fetch('/api/data', { next: { revalidate: 60 } })

// Always fresh (like getServerSideProps)
const data = await fetch('/api/data', { cache: 'no-store' })

// Cached indefinitely (like getStaticProps)
const data = await fetch('/api/data', { cache: 'force-cache' })

This is more explicit and less magical than the previous model. We've stopped reaching for unstable_cache in most cases.

Turbopack is real now

Local dev with Turbopack is noticeably faster on large projects. Our biggest client app — 200+ routes, 400+ components — went from 8 seconds cold start to under 2. Hot reload is instant.

We haven't hit a Turbopack compatibility issue in three months. Ship it.

What we'd do differently

One regret: we colocated too much logic in Server Components early on. Some of that is now hard to test. The rule we use now: Server Components fetch data and pass it down. Client Components handle interaction. Logic lives in plain functions that neither knows about.

Written by

DevProton Engineering

Published

April 20, 2026

Free · 5-day delivery · No commitment

Get a Free AI-Readiness Audit.

Five-day structured review of your data, workflows, and team. We hand back a scored opportunity matrix and a 90-day roadmap — not a sales call.