Hey folks,
I have a relatively large ISR site (>600k pages). ISR works well, but I’m losing my cache every time I do a deploy, which is less than ideal. I want these pages primed as we’re optimizing for SEO, and I don’t mind if an invalidation is needed to refresh the pages content. The Vercel docs state ISR cache is automatically put in durable storage but every time I deploy, I lose the cache and it needs to be warmed again.
You’re right to be concerned about losing your ISR cache during deployments. That shouldn’t be happening, as Vercel does store ISR pages in durable storage.
Here are a few quick things to check:
Verify your ISR implementation, especially the revalidate options.
Review your Vercel project settings for any cache-clearing configurations.
Consider using on-demand revalidation for specific pages.
If these don’t help, we can take closer look at your specific setup and help identify why the cache isn’t persisting as it should.
Let me know if you need any clarification or have more questions!
Hi!
Could you help us understand why our pages are being invalidated and re-generated on subsequent requests after a deployment causing longer load times? Even when changes are unrelated to the components/routes we’re rendering. Whenever we commit to the branch, and Vercel re-builds and re-deploys the app, it causes the first visit to the page to be super slow.
I tested using timestamps on the props on preview environments, and it showed they were being regenerated on the first request. After that, the timestamp was stable and the generation worked as expected. But whenever we made a deployment, it cleared all the generated pages.
We’re currently using the pages router (but we also tried using the app router). We are using fallback: true mechanism (which is supposed to generate new pages on demand in the background, and serve the stale version upfront).
Here’s the ISR page we currently have. Is there anything we’re doing wrong or misunderstanding here? How can we get our ISR pages to stay alive across multiple deployments so we don’t need to warm them up for the first page view?
Thanks!
/* eslint-disable import/order */
import { GetStaticPaths, GetStaticProps } from "next";
import { charityDirectoryNonprofitPageRequest } from "@/services/charity-directory";
import { Nonprofit } from "@/services/charity-directory/types";
import { CharityProfile } from "@/components/charity-components";
import { MayNotOperate } from "@/components/charity-components/may-not-operate";
import "../../globals.css";
import Head from "next/head";
import { ctaDownloadAppRequestStatic } from "@/services/datocms/download-button/request-static";
import { Layout } from "@/components/static-layout/layout";
interface NonprofitProfileProps {
nonprofit: Nonprofit;
downloadLinks: {
appleStoreUrl: string;
chromeStoreUrl: string;
macOsStoreUrl: string;
legacyStoreUrl: string;
};
}
interface Props {
nonprofit: Nonprofit;
}
export const getStaticPaths: GetStaticPaths = async () => ({
paths: [
{
params: { ein: "010130427" }, // This is our testing EIN we have it generated on build time.
},
],
fallback: true,
});
// ISR (Incremental Static Regeneration)
export const getStaticProps: GetStaticProps<Props> = async ({ params }) => {
const nonprofitEin = (params?.ein as string).replace("ein-", "");
const nonprofit = await charityDirectoryNonprofitPageRequest(nonprofitEin);
const downloadLinks = await ctaDownloadAppRequestStatic();
if (!nonprofit) {
return {
notFound: true,
};
}
return {
props: {
nonprofit,
downloadLinks: {
appleStoreUrl:
downloadLinks.ctaDownloadApp?.ctaDownloadAppStoreUrl?.href,
chromeStoreUrl:
downloadLinks.ctaDownloadApp?.ctaDownloadAppChromeStoreUrl?.href,
macOsStoreUrl:
downloadLinks.ctaDownloadApp?.ctaDownloadMacosSafariExtensionUrl
?.href,
legacyStoreUrl:
downloadLinks.ctaDownloadApp?.ctaDownloadAppChromeStoreUrl?.href,
},
},
revalidate: 60 * 60 * 24, // 24 hours
};
};
function NonprofitProfile({ nonprofit, downloadLinks }: NonprofitProfileProps) {
if (!nonprofit) return;
// Set custom title and description based on nonprofit data
const customTitle = `${nonprofit.name} | Legit, CEO Salary, Mission, 990 and more`;
const customDescription = `Learn about ${nonprofit.name}: Is it legit? Do I like the mission? What is the CEO's salary?`;
const titleWithReview = `Reviews of ${nonprofit.name}, CEO Salary, Legit, Mission, 990 and more`;
const descriptionWithReview = `Read reviews of ${nonprofit.name}. Is it legit? Do I like the mission? What is the CEO's salary?`;
// Choose title and description based on review presence
const pageTitle =
nonprofit.faqs.review || nonprofit.faqs.reviewFacebook
? titleWithReview
: customTitle;
const pageDescription =
nonprofit.faqs.review || nonprofit.faqs.reviewFacebook
? descriptionWithReview
: customDescription;
return (
nonprofit && (
<Layout downloadLinks={downloadLinks}>
<Head>
<title>{pageTitle}</title>
<meta name="description" content={pageDescription} />
<meta property="og:title" content={pageTitle} />
<meta property="og:description" content={pageDescription} />
<meta property="twitter:title" content={pageTitle} />
<meta property="twitter:description" content={pageDescription} />
</Head>
{typeof nonprofit.valid === "undefined" || nonprofit.valid ? (
<CharityProfile nonprofit={nonprofit} nonprofitEin={nonprofit.ein} />
) : (
<MayNotOperate nonprofit={nonprofit} nonprofitEin={nonprofit.ein} />
)}
</Layout>
)
);
}
export default NonprofitProfile;