Eager Loading
We will use the following example schema in our walk-through, which contains a few different edges:
What is eager loading?
Eager loading is a feature in EntGo that allows you to eager-load edges on a query, which means that
the edges are fetched along with the parent entity. This is primarily useful when you have a a parent
entity, like a Pet
, and you are confident that you always want to fetch the associated owner of that
pet (the owner
type, which is a User
).
In entrest, we build upon this functionality -- to start, all edges by default will have a dedicated endpoint where you can query an entities associated edges -- these are called edge endpoints:
- Unique edge example:
GET /pets/{id}/owner
- Non-unique edge example:
GET /users/{id}/pets
Usage
If you enable eager-loading for an edge, say the owner
edge on the Pet
schema using the
WithEagerLoad
annotation,
calling GET /pets/{id}
would return something like this:
And the associated code required:
Additional configuration
- The default maximum number of results that can be eager-loaded for a given edge can be controlled
with the config option
EagerLoadLimit
, and associatedWithEagerLoadLimit
annotation. - If you eager load an edge, by default the associated edge endpoint will have its pagination turned off.
This can be turned off with the config option
DisableEagerLoadNonPagedOpt
. - If you only ever want to eager load a specific edge and not have a dedicated endpoint, you can use
the
WithEdgeEndpoint
annotation to disable the edge endpoint. This can also be configured globally with the config optionDisableEagerLoadedEndpoints
. - All edges can be eager loaded by default (though highly discouraged). See the config option
DefaultEagerLoad
.
When should you not eager load?
Eager loading is a very powerful feature, but it can also be very expensive. For example, if you have
a User
schema, and an edge which may have 1000+ associated entities, eager loading will never
be paginated, so it must always fetch all of the associated entities. Eager loading should only be used
when you are confident that the associated entities will not scale to a large number of entities in almost
all cases.
It's also worth noting that this could be used as an attack vector (i.e. denial-of-service and/or resource-exhaustion).
If a user is in control of an association, and intentionally adds additional entities to the association,
they could overwhelm consumers of your API (response times, memory usage, total response sizes, etc).
As such, entrest sets a default limit for the number of eager loaded results. This can be controlled
via the config option EagerLoadLimit
,
and associated WithEagerLoadLimit
annotation.
Examples of good and bad eager loading
- Eager loading the
owner
edge on thePet
schema: ✔️- As long as the
owner
edge does not grow to have an extremely large amount of fields, this is relatively safe.
- As long as the
- Eager loading the
friends
edge on thePet
schema: ❌- As this field is likely user-controlled, this could result in an unknown amount of entities being fetched, and it is likely a field that is hard to add a limit to.
- Eager loading a
notifications
edge on theUser
schema: ✔️- Even though
notifications
to some extent are likely user-controlled, it's something that you could add a limit to (e.g. a given user can only have 200 historical notifications).
- Even though