playbook/antigravity-awesome-skills/skills/vercel-optimize/lib/gates/isr-overrevalidation.mjs

63 lines
2.4 KiB
JavaScript

// ISR writes re-execute the page render. A w/r ratio above 0.5 means writes are
// happening at least once for every two reads — high enough for the default
// audit to spend investigation budget. writes>100 avoids flapping on quiet routes.
export const metadata = {
id: 'isr_overrevalidation',
threshold: 'writes/reads > 0.5 AND writes > 100',
billingDimension: 'isr',
scope: 'route',
sourceCitation: 'https://vercel.com/docs/incremental-static-regeneration',
description:
'ISR routes with > 1 write per 2 reads. The revalidate interval is too aggressive relative to read traffic — many reads pay to regenerate. Investigate whether the page can tolerate a longer revalidate window or on-demand revalidation via revalidateTag.',
};
export function gate(signals) {
const rows = extractRows(signals);
return rows
.filter((r) => r.writes > 100 && r.reads > 0 && r.writes / r.reads > 0.5)
.map((r) => {
const ratio = r.writes / r.reads;
return {
kind: metadata.id,
scope: 'route',
route: r.route,
files: [],
priority: Math.round(r.writes),
confidence: 0.88,
o11ySignal: `writes=${r.writes},reads=${r.reads},w/r=${ratio.toFixed(2)}`,
reason: 'ISR revalidating faster than read traffic justifies',
question: `On ${r.route}, ${r.writes} ISR writes against ${r.reads} reads (${(ratio * 100).toFixed(0)} writes per 100 reads) — what is the current revalidate interval and can it be lengthened or switched to on-demand?`,
evidence: {
metric: 'isrWritesByRoute',
route: r.route,
writes: r.writes,
reads: r.reads,
ratio,
},
};
});
}
function extractRows(signals) {
const writes = signals.metrics?.isrWritesByRoute?.rows ?? [];
const reads = signals.metrics?.isrReadsByRoute?.rows ?? [];
const writeByRoute = new Map();
for (const r of writes) {
if (!r.route) continue;
writeByRoute.set(r.route, (writeByRoute.get(r.route) ?? 0) + (r.value ?? 0));
}
const readByRoute = new Map();
for (const r of reads) {
if (!r.route) continue;
readByRoute.set(r.route, (readByRoute.get(r.route) ?? 0) + (r.value ?? 0));
}
const routes = new Set([...writeByRoute.keys(), ...readByRoute.keys()]);
return [...routes].map((route) => ({
route,
writes: writeByRoute.get(route) ?? 0,
reads: readByRoute.get(route) ?? 0,
}));
}