Skip to content

feat(serializer): lazy-load relationship data by default - #203

Merged
tvdeyen merged 1 commit into
mainfrom
fix-jsonapi-lazy-load-nested
Sep 1, 2026
Merged

feat(serializer): lazy-load relationship data by default#203
tvdeyen merged 1 commit into
mainfrom
fix-jsonapi-lazy-load-nested

Conversation

@tvdeyen

@tvdeyen tvdeyen commented Aug 24, 2026

Copy link
Copy Markdown
Member

Emitting relationship linkage that the request's include never asked for is surprising to API clients and triggers N+1 queries on the server. This makes every relationship lazy-load its data by default, so a resource carries only the linkage a query actually requested.

The element tree is the deliberate exception and stays eager — all_elements, elements, fixed_elements, and nested_elements. A nested-element tree of arbitrary depth cannot be expressed as an include path, and clients rely on the top-level elements/fixed_elements linkage as the entry points from which to walk nested_elements and reconstruct a page's content; making those lazy would leave the frontend unable to render.

Enabling this meant fixing how jsonapi-serializer's lazy_load_data handles nested includes. Upstream decides whether to emit linkage with includes_list.include?(key), but top-level includes are dotted paths (primary_taxon.ancestors) and every sideloaded record is handed the parent's includes_list rather than its own scoped remainder — so enabling lazy_load_data suppressed linkage for every relationship of a nested resource, even requested ones. A SerializationCore patch, prepended at boot, matches the base key of each requested path and threads the scoped remainder into each sideloaded record, covered by an isolated spec that also pins the vendored behavior (deduplication, deep nesting, has_many) the patch now owns.

@tvdeyen
tvdeyen force-pushed the fix-jsonapi-lazy-load-nested branch from 62a1897 to befdc82 Compare August 24, 2026 13:30
@mamhoff

mamhoff commented Aug 24, 2026

Copy link
Copy Markdown
Contributor

Amazing.

@tvdeyen
tvdeyen force-pushed the fix-jsonapi-lazy-load-nested branch 4 times, most recently from 9bae754 to 79ddb46 Compare August 26, 2026 18:01
@tvdeyen
tvdeyen marked this pull request as draft August 27, 2026 21:31
@tvdeyen tvdeyen added this to the 8.4 milestone Sep 1, 2026
Emitting relationship linkage that the request's `include` never asked for
is surprising to clients and triggers N+1 queries on the server, so every
relationship now sets `lazy_load_data: true` and emits its `data` only when
requested. The element tree is the exception and stays eager (`all_elements`,
`elements`, `fixed_elements`, `nested_elements`): a tree of arbitrary depth
cannot be expressed as an `include` path, and clients rely on the top-level
linkage as the entry points to reconstruct the page's content.

This requires making jsonapi-serializer's `lazy_load_data` honour nested
includes: upstream matches `includes_list.include?(key)`, but top-level
includes are dotted paths and each sideloaded record receives the parent's
includes_list, so it suppressed linkage for every relationship of a nested
resource. A SerializationCore patch, prepended at boot, matches the base key
of each requested path and threads the scoped remainder into each sideloaded
record.
@tvdeyen
tvdeyen force-pushed the fix-jsonapi-lazy-load-nested branch from 79ddb46 to d7986e0 Compare September 1, 2026 06:00
@tvdeyen tvdeyen changed the title fix(serializer): honour nested includes in lazy_load_data feat(serializer): lazy-load relationship data by default Sep 1, 2026
@tvdeyen
tvdeyen marked this pull request as ready for review September 1, 2026 06:03
@tvdeyen tvdeyen added the enhancement New feature or request label Sep 1, 2026
@tvdeyen
tvdeyen merged commit 8646d08 into main Sep 1, 2026
13 checks passed
@tvdeyen
tvdeyen deleted the fix-jsonapi-lazy-load-nested branch September 1, 2026 06:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants