Skip to content

Reduce Next.js handler bundle size to re-enable ISR on API reference pages #1267

@PedroAntunesCosta

Description

@PedroAntunesCosta

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions