feat(serializer): lazy-load relationship data by default - #203
Merged
Conversation
tvdeyen
force-pushed
the
fix-jsonapi-lazy-load-nested
branch
from
August 24, 2026 13:30
62a1897 to
befdc82
Compare
Contributor
|
Amazing. |
tvdeyen
force-pushed
the
fix-jsonapi-lazy-load-nested
branch
4 times, most recently
from
August 26, 2026 18:01
9bae754 to
79ddb46
Compare
tvdeyen
marked this pull request as draft
August 27, 2026 21:31
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
force-pushed
the
fix-jsonapi-lazy-load-nested
branch
from
September 1, 2026 06:00
79ddb46 to
d7986e0
Compare
tvdeyen
marked this pull request as ready for review
September 1, 2026 06:03
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Emitting relationship linkage that the request's
includenever asked for is surprising to API clients and triggers N+1 queries on the server. This makes every relationship lazy-load itsdataby 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, andnested_elements. A nested-element tree of arbitrary depth cannot be expressed as anincludepath, and clients rely on the top-levelelements/fixed_elementslinkage as the entry points from which to walknested_elementsand 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_datahandles nested includes. Upstream decides whether to emit linkage withincludes_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 enablinglazy_load_datasuppressed linkage for every relationship of a nested resource, even requested ones. ASerializationCorepatch, 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.