Weâre building a website which contains a lot of (more or less) similar models. They all have a lot of fields in common but some of them are specific to the models itself. We would like to use blocks to group the common fields and include them as a frameless âModular Content (Single Block)â in the different models. This approach would also help us in the type generation as we could use fragments to fetch those blocks which could be used to type common fields. Our question is now if the usage of such frameless blocks could lead to performance implications when querying data via GraphQL? (compared to define the fields directly on the models itself)
On performance, there is a small theoretical difference you should be aware of. In our GraphQL complexity model, a Modular Content field has a base cost multiplier compared to plain top level fields. Concretely, âModular content field: 5 Ă inner fieldsâ cost.â With Single Block you also avoid the array wrapper so youâll receive a single object or null, which reduces a bit of payload and code noise. Details are in the complexity guide: https://www.datocms.com/docs/content-delivery-api/complexity, and the Single Block return shape is shown here: https://www.datocms.com/docs/content-delivery-api/modular-content-fields.
In practice this overhead is negligible for normal queries. The biggest drivers of performance are page size, how many nested relations you fetch, and whether you turn on deep filtering. Deep filtering. Also remember that responses are served from our CDN and are cacheable, and your query will be cached unless your compressed GraphQL request body exceeds 8 KB. The technical limits and caching notes are here: https://www.datocms.com/docs/content-delivery-api/technical-limits.
Given your goals, I would proceed with frameless Single Block for the shared fields. Keep the allowed block type to one and mark the field as required to keep the union narrow, keep using GraphQL fragments for those common fields, and fetch only what you need in each view. If you want, share an example of your intended query and I can sanity check the complexity headers and suggest small tweaks.
So yeah, it is a tiny increase in complexity, but unless you are nesting several layers of modular content, this should be completely negligible to performance, and will be 100% negligible if you make sure your query is being cached.
I just wanted to add one more thing to @m.finamorâs excellent and detailed reply (thank you!).
For the typical website (say, a marketing page or blog or such), you should be able to shield your websiteâs visitors from any sort of backend complexity, whether thatâs from a GraphQL query or anything else. Typically this is done through some sort of frontend caching, so that youâre sending them pre-generated and cached HTML (or Next.js JSON snippets or React Server Components or whatever). This sort of caching can be done by your frontend framework and/or a CDN.
Unless there is a need for real-time data from your project (and most of the time, there is not), it will be far faster, cheaper, and safer (so youâre not exposing your CDA API keys) to do it that way than having each visitor directly query the CDA from their own browser.
With proper caching, you completely detach the query complexity and response time from your visitor experience. Even an exceptionally complicated query that takes 20 seconds (which would be an extreme worst-case scenario, mind you) could thus be turned into a 0.05-sec cache fetch instead, and your visitors would be none the wiser.
Let us know if youâd like to discuss the frontend part of that more!