Description
Restore Incremental Static Regeneration (ISR) on the API reference page src/pages/docs/api-reference/[slug].tsx without exceeding the AWS Lambda function-bundle size limit currently enforced by Netlify's @netlify/plugin-nextjs v4. The page was running on ISR (revalidate: 86400) until PR #1226 was reverted; ISR is currently disabled in PR #1264 as a workaround.
Context
PR #1226 introduced server-rendered overview content and ISR on the API reference page. Two days after merge, every Netlify preview deploy of any branch built on top of post-#1226 main began failing AWS Lambda's CreateFunction step with HTTP 400: Invalid AWS Lambda parameters used in this request. The failure was deterministically traced to the size delta produced by revalidate: 86400 on this page (toggling the line on/off flipped deploys between pass and fail with no other code change). PR #1262 reverted the entire SEO PR to unblock production. PR #1264 re-lands the SEO work with revalidate removed.
Full timeline, handler sizes, and experimental confirmation are documented in plans/PR-1226-deploy-failure-postmortem.md (local file, not versioned).
Goal
Re-enable revalidate on src/pages/docs/api-reference/[slug].tsx so newly published OpenAPI specs are picked up between deploys, while keeping each Netlify-generated handler bundle (___netlify-handler, ___netlify-odb-handler) within AWS Lambda's parameter limits.
Investigation Notes
Bundle size data points (compressed handler size from Netlify deploy API)
| Build configuration |
___netlify-handler |
___netlify-odb-handler |
| Post-revert main, no PR #1226 content |
49.65 MB |
49.66 MB |
| PR #1264 with ISR removed (current) |
49.66 MB |
49.66 MB |
PR #1226 with revalidate: 86400 |
84.63 MB |
84.64 MB |
ISR adds ~35 MB per handler. The two builds with ISR enabled exceeded the threshold Netlify/AWS started enforcing on May 14 2026 and failed to upload. Builds at 49.6 MB succeed.
Likely contributors to the ISR payload
sidebarfallback is the full site navigation (public/navigation.json, ~812 KB on disk, ~21k lines). It is passed as a prop on every page and serialized into the per-path ISR cache.
- Source:
src/utils/getNavigation.ts fetches process.env.navigationJsonUrl.
- Consumed in
src/pages/docs/api-reference/[slug].tsx lines 522, 676, 760.
- Per-page props returned by
getStaticProps (endpoints map, pagination map, endpointNames map, descriptionHtml, overviewEndpoints[], overviewEndpointGroups[]) are recomputed per slug. With ~80-100 OpenAPI specs registered by src/utils/getReferencePaths.ts, the aggregated serialized payload is non-trivial.
- The only other ISR page in the codebase is
src/pages/updates/release-notes/[slug].tsx (revalidate: 600), which currently coexists with the rest of the bundle.
Suggested investigation paths
- Trim
sidebarfallback from per-page props. Replace the full-tree prop with a minimal slice scoped to the current page's branch in the nav tree. Move the rest to a client-side fetch of /navigation.json after hydration.
- Audit the unzipped handler size locally. Run
yarn build and inspect .netlify/functions-internal/___netlify-handler/*.zip (size, contents) to measure exactly which files dominate the bundle.
- Externalize heavy props from the function bundle. Move per-spec data to a static JSON asset under
/public/api-reference-overview/<slug>.json and fetch it on the client when needed; the ISR handler then only needs to know which slugs exist, not their full props.
- Consider splitting
getStaticPaths strategy. Currently fallback: 'blocking' is used. Evaluate whether fallback: false with a deploy-time path list is acceptable, which avoids the need for ISR-style serialized data in the handler.
- Establish a CI size budget. Add a build-time check that fails the build if
___netlify-handler exceeds a configurable compressed-size threshold (e.g. 60 MB) so the next size cliff is caught at build time rather than at Netlify deploy time.
Acceptance criteria
revalidate is re-enabled on src/pages/docs/api-reference/[slug].tsx (any reasonable interval).
- A Netlify preview deploy of the change succeeds end-to-end.
- Both function handlers measure under 75 MB compressed (at least 10 MB safety margin under the failing region of 84 MB).
- Newly added OpenAPI specs are reflected on the live site without a new deploy.
Related
Description
Restore Incremental Static Regeneration (ISR) on the API reference page
src/pages/docs/api-reference/[slug].tsxwithout exceeding the AWS Lambda function-bundle size limit currently enforced by Netlify's@netlify/plugin-nextjsv4. The page was running on ISR (revalidate: 86400) until PR #1226 was reverted; ISR is currently disabled in PR #1264 as a workaround.Context
PR #1226 introduced server-rendered overview content and ISR on the API reference page. Two days after merge, every Netlify preview deploy of any branch built on top of post-#1226
mainbegan failing AWS Lambda'sCreateFunctionstep withHTTP 400: Invalid AWS Lambda parameters used in this request. The failure was deterministically traced to the size delta produced byrevalidate: 86400on this page (toggling the line on/off flipped deploys between pass and fail with no other code change). PR #1262 reverted the entire SEO PR to unblock production. PR #1264 re-lands the SEO work withrevalidateremoved.Full timeline, handler sizes, and experimental confirmation are documented in
plans/PR-1226-deploy-failure-postmortem.md(local file, not versioned).Goal
Re-enable
revalidateonsrc/pages/docs/api-reference/[slug].tsxso newly published OpenAPI specs are picked up between deploys, while keeping each Netlify-generated handler bundle (___netlify-handler,___netlify-odb-handler) within AWS Lambda's parameter limits.Investigation Notes
Bundle size data points (compressed handler size from Netlify deploy API)
___netlify-handler___netlify-odb-handlerrevalidate: 86400ISR adds ~35 MB per handler. The two builds with ISR enabled exceeded the threshold Netlify/AWS started enforcing on May 14 2026 and failed to upload. Builds at 49.6 MB succeed.
Likely contributors to the ISR payload
sidebarfallbackis the full site navigation (public/navigation.json, ~812 KB on disk, ~21k lines). It is passed as a prop on every page and serialized into the per-path ISR cache.src/utils/getNavigation.tsfetchesprocess.env.navigationJsonUrl.src/pages/docs/api-reference/[slug].tsxlines 522, 676, 760.getStaticProps(endpointsmap,paginationmap,endpointNamesmap,descriptionHtml,overviewEndpoints[],overviewEndpointGroups[]) are recomputed per slug. With ~80-100 OpenAPI specs registered bysrc/utils/getReferencePaths.ts, the aggregated serialized payload is non-trivial.src/pages/updates/release-notes/[slug].tsx(revalidate: 600), which currently coexists with the rest of the bundle.Suggested investigation paths
sidebarfallbackfrom per-page props. Replace the full-tree prop with a minimal slice scoped to the current page's branch in the nav tree. Move the rest to a client-side fetch of/navigation.jsonafter hydration.yarn buildand inspect.netlify/functions-internal/___netlify-handler/*.zip(size, contents) to measure exactly which files dominate the bundle./public/api-reference-overview/<slug>.jsonand fetch it on the client when needed; the ISR handler then only needs to know which slugs exist, not their full props.getStaticPathsstrategy. Currentlyfallback: 'blocking'is used. Evaluate whetherfallback: falsewith a deploy-time path list is acceptable, which avoids the need for ISR-style serialized data in the handler.___netlify-handlerexceeds a configurable compressed-size threshold (e.g. 60 MB) so the next size cliff is caught at build time rather than at Netlify deploy time.Acceptance criteria
revalidateis re-enabled onsrc/pages/docs/api-reference/[slug].tsx(any reasonable interval).Related