Is the "Inline Fetch Plan" new feature safe ?!

The new version of Jmix 2.5 has introduced an interesting feature, “Inline Fetch Plans” which gives our REST API clients more flexibility regarding which fields to retrieve. As the saying goes, with great power comes great responsibility.

I have reread the documentation associated with this new feature to check whether any mechanisms were planned to protect against data leaks from our entities. I found nothing.

With the previous approach, where we passed the name of the fetch plans as a query parameter, we had more assurance regarding which fields were accessible to our API clients. It was the developer who precisely defined the fetch plan for the exposed fields. However, with the new approach, the caller (API client) chooses the fields to extract (keeping in mind that they need knowledge of the internal structure and relationships between entities).

Maybe I understand the idea behind this innovation, perhaps a “GraphQL-like” approach. However, I would prefer a GraphQL add-on (to expose APIs and consume others via a “GraphQL DataStore”).

The questions that come to mind, knowing that the only existing configuration currently allows enabling or disabling this feature globally (not per entity), are the following:

  • How can we protect against data leaks? Can we limit the exposed fields per API not globally per entity ?
  • How can we prevent an eventual DDoS caused by extracting a large entity graph? The caller, via the Fetch Plan, can choose fields in depth, leading to complex joins.
  • Is it possible to enable this feature for specific entities only and not for others?
  • How do we manage API evolution? With these dynamic fetch plans, it becomes difficult to track which fields and dependencies are used by our clients. This drastically increases the risk of breaking their code, especially since we are directly exposing the internal structure of our entities externally.

I have a feeling that this feature introduces more risks and complexity than value. It might be better to stick to standard solutions like GraphQL between the caller and the API (perhaps, for consistency, converting the request into a Fetch Plan once it reaches Jmix).

Or at least, define a big exposed fetch plans (the old way). Then, provide the ability to define a sub-fetch plan using JSON. This way, the caller can only specify a subset of fields defined by the big/large Fetch Plan (for reasons such as loading less data when needed).

PS: The same issue applies to dynamic filters via REST APIs.

I addressed this question during the recent online Office Hours event, so let me just summarize my response for the record.

Jmix’s Generic REST API is inherently dynamic—clients can request any entity along with its immediate attributes by using different URLs. This functionality has always been available, whether or not inline fetch plans are used. However, proper role and policy configuration is essential to prevent unintended data exposure.

Security Measures in Jmix

Jmix includes several safeguards to minimize accidental data leaks:

  • REST is disabled by default—a user must have an explicit policy to access any endpoint.
  • Entities and attributes are restricted by default—permissions must be granted explicitly.
  • Role scopes (UI vs. API)—allow clear separation between UI and REST permissions, enabling stricter control over API access.

Performance Considerations with Inline Fetch Plans

While inline fetch plans improve flexibility, they can introduce performance risks if clients request overly deep fetch plans, increasing server load. If you expose Generic REST to untrusted or uncontrolled clients, consider:

  • Disabling inline fetch plans.
  • Using custom endpoints instead of Generic REST for better control.

Recommended Use Cases

Generic REST is best suited for trusted integration scenarios (e.g., backend services under your control). For public APIs or frontend clients, a more restricted approach (e.g., custom endpoints) is preferable due to the dynamic nature of Generic REST.

The primary motivation for inline fetch plans was to simplify the REST DataStore integration, making it as seamless as possible.

Regards,
Konstantin

1 Like