I recently ran into an interesting issue while working on the /writing page of my site. Whenever I added or updated articles, the changes did not show immediately. Oddly enough, the individual article pages updated as expected, but the listing page stayed stale.
After some digging, I realized this was not a bug. It was Next.js doing exactly what it is supposed to.
How Next.js caching works
Next.js (App Router) handles HTML caching at the edge in production. For statically prerendered pages, it sets Cache-Control: s-maxage=31536000, which is one year. This header tells CDNs and edge caches that they can serve the page without re-fetching for a long time. Browser cache headers such as no-cache do not override this because s-maxage takes priority for shared caches.
This explains why the listing page showed stale content while individual article pages, which are either dynamic or use revalidation, updated immediately.
How to control caching
Next.js provides a clean way to manage page freshness.
First, set revalidation for a page. In the page file, for example app/writing/page.tsx, add: