Discussion regarding the complex response structure for REST & GraphQL (Developer Experience)

encouraging - thanks for updating that it is being looked at. I think even an interim step of a middleware that reverts to the ‘old’ format would help with those of us porting. longer term solutions will no doubt require more thought.

I was in the middle of a v3 → v4 migration when I saw those data and attributes pollute my graphQL queries.

I’ve created an account just to mention that I share the opinion of the folks above, and I’m really hoping to be able to use the old, intuitive and logical structure of the GraphQL responses.


So I was really bothered by this and wrote a normalizer on the front end that gets rid of both data and attributes, and also handles Typescript.

I’ve included an example of the normalization in the comments

It’s a very very rough draft. I need to clean it up, there are a few edge cases it doesn’t handle, and it is a bit too aggressive about stripping, but I’m wondering if it would be of use to anyone?

Was also quite excited about the v4 release until I ran across this little detail. Seems like Apollo Federation is also broken with this release, not sure if it is related to the same schema changes. Just a small datapoint in the bucket, but will be reverting back to v3 until there is some resolution here.

Hi @DMehaffy ,

Thanks a lot for your last update. Unless you (as strapi dev team) decide to stay locked in the room until providing a fix, I guess the meeting is over. Any news?

The more the comeback arrives here, the clearer the community needs became: a “breaking” change which get rides of useless data wrapper for single asset query response and no id and attributes split anymore. Really hope a pragmatic decision was taken today :pray: :candle:

I love strapi and I don’t want to be forced to switch on another solution… :cry:

Yup I was just re-reading through our notes from the meeting we did this morning and intended to share what we discussed and what we are thinking.

Actions we are taking right now:

  • Doing a bit more research into other existing implementations such as Facebooks Relay: https://relay.dev/ and how they are doing things as functionally our setup is very similar to theirs
  • Researching a bit into getting caching working (it is possible but not just as simple as apollo’s native config for it) as it’s a huge area of concern from everyone

Actions we plan to take in the next month or so:

  • Have a community call (or steal part of an existing one) to cover some of the background with this
  • Record a video or write a lengthy blog-post explaining some of the future needs we have from the response structure to support the following three features:
    • Content Versioning
    • Publication Workflows
    • Better meta information about an entity’s i18n locale
  • Breaking down our focus towards keeping things stable and some bits of the longer term plan

What we discussed was the following (keep in mind we aren’t taking a full decision right now because some people are on vacation next week and we want to do more research before we just rush into things).
I hope everyone can understand we don’t want to just take a decision on this lightly, especially now that we have extended the v3 EOL til Sept 2022.

  • Removing data {} is not possible now or in the future because it would conflict with high level meta {}
  • attributes {} could be removed in theory now but it would conflict with our long term plans in the future with meta {} (merged, we will probably touch on this in the video/blog post)
  • We are willing to make a breaking change for GraphQL plugin but would require a long and complex RFC before we would do that, not a short term solution but yes a plugin could technically be ejected from the versioning system the core uses. There would need to be a lot of validation from the community around the RFC that we didn’t have when we first issued the RFC (largely the problem on our side because it wasn’t clear what feedback we wanted, and it wasn’t shared enough)
  • Researching Relay => why does it work so well => why is it so accepted by their community => what learnings can we take from that => their caching layer?
  • Can SDKs help the end user? Is this stuff we can build to help?

We also discussed a bit on the RFC side and what went wrong and how to prevent it in the future:

  • RFC needs more readers AND interactions (comments, discussions, debates, not preferences but breaks downs on why an alternative is better with trade offs, ect)
  • More data in the RFC, too much internal information and context wasn’t shared
  • RFC format wasn’t clear enough, not enough descriptions
  • RFC process was too fast // Strapi v4 Beta process was too short (won’t happen again, we were under a time crunch due to poor timeline planning in v4)
  • Ideally we really should publish RFCs long before we start development and engineering team needs to be more active reading responses and responding to RFCs. Small team problems that we are fixing slowly but simply we need more devs.

Funnily enough one of the original respondents to the RFC when we published it was a community member who now works for us so we were able to rapidly gather some cool insights and in the future we would like to have some of these discussions in person such as in community calls going forward as it was really helpful to get that point of view.

TLDR: Nothing major happening right now, it’s clear we need to do some research but we need to make decisions carefully, we can’t “just revert” back to v3 style. Keep in mind that we did what we did as we were building pre-reqs for what we want to build in the future (ideally this year). That was never described to any of you and it’s what we need to do now.

Give us a bit of time we are listening and we do plan to engage with the community to find a working resolution to this. Your opinions are very valuable to us, time crunches just didn’t make things easy and too much got rushed.


on Relay - their response is as follows form their docs or am I missing re. the comparison

  "data": {
    "user": {
      "id": "4",
      "name": "Mark Zuckerberg",
      "username": "zuck"
    "viewer": {
      "actor": {
        "name": "Your Name"

I second this. There is no redundancy in their data structure, so it’s no surprise to me that’s “accepted by their community” as @DMehaffy asked.
IMO, it has nothing to do with adding the same two properties to each nested object.

To me, using GraphQL with Strapi was all about simplicity and flexibility. Now I’ll have to implement middlewares to recursively flatten all my objects, which is bad for both readability and performance.

I feel it’s going against simple dev principles like DRY, YAGNI, BDUF, but I’m sure I don’t have the full scope and vision, that’s just how I feel for my simple use cases.


Very interesting to see all this in the roadmap and the team being so proactive and receptive of feedback. T H A N K S ! !

As a tech lead who led adoption of GraphQL in a mid-sized company I would recommend to not overlook what Apollo is doing. In particular, I’d like to recommend this article from Sashko Stubailo (one of the core engineers of Apollo V1) who is a very respected voice in the GraphQL ecosystem: Understanding pagination: REST, GraphQL, and Relay - Apollo GraphQL Blog It makes a great case illustrating pagination issues and the trade-offs around conventions. That was a great kick-off for internal discussion in our experience when we needed to decide for Apollo or Relay. We are pretty happy with the flexibility Apollo provides.

An extra mention worth doing is Apollo has always been a DX-first company (they did Meteor before) and it seems that taking their adoption strategy should guarantee a good response from devs who interact with Strapi using GraphQL. They are also widely adopted so a big part of the GraphQL community will just get what they expect.

Looking forward for more interaction with the community :slight_smile:

1 Like

Dear Strapi team,

Why so many ‘data/attributes’ flying around?

I really like Strapi (there are so many more pros than cons) but have been struggling with your recent changes in v4 related to the ‘Unified response format,’ even wondering if there might be an alternate headless solution that might prove to be more effective.

If one is trying to consume a single endpoint that has 2 or 3 levels hierarchy, which easily occurs when one defines any relations, media fields, components, or dynamic zones, it seems likely that the developer (who uses Strapi to build the hierarchy) would be the one responsible for any necessary meta or pagination that runs so deeply within the model they’re constructing, making the data/attribute wrapping redundant for a majority of the use cases beyond the 2nd level.

In your documentation, you say a single entry returns an object with id, attributes, and meta. This seems logical for level 1 ( of which I would be in accord), as I would consider the endpoint to be one query (regardless of filtering parameters); any subsequent level queries are not directly part of the interface.

As an initial test, I have spent some time creating a transformation layer to remove this wrapping (in one instance, trimming by 4 data/attribute levels), but have yet to come up with a standard and clean approach to use across all my models.

In my opinion, I shouldn’t really need to create a transformation layer specifically to eliminate what in all current practices feels like an arbitrary rule for distant future-proofing.

I’ve considered several solutions: 1) restrict my models to a single dynamic zone across one level (which isn’t ideal in all cases for data-entry, and defeats the flexibility of Strapi’s types), thus keeping the response flatter; 2) create a middleware service to transform the response (as others have suggested), but this seems too cumbersome and not the best place to perform such a transformation; 3) create a plugin to handle transformations, which is not ideal but would in theory be helpful for migrations; or 4) find another headless CMS with a cleaner response format.

I would hate to have gone into production with v3 (the version and response structure that originally won me over) and be faced with adding a transformation layer to migrate to v4.

The following would be ideal for dev-friendly front-end consumption:

Apps should be able map the object with ease without transformation:
page.content.type’ instead of ‘data.attributes.page.content.type.data.attributes.name.’

For instance, with a Vue component, passing data attributes from the response should map sensibly without the front-end dev having to unnecessarily transform the object to remove verbosity (at least, that is what I wish to provide her/him):

<component v-bind:is="$compName(attrs.__component)" :attributes="attrs" /> 

instead of;


I hope you will at least consider removing the data/attributes wrapper (from both REST and GraphQL APIs) on nested objects that do not require meta/pagination, or include them only when directly called by an endpoint return one level. I hope this feedback is helpful.


Hello good,

Thanks for the work done, but I want to contribute that with version 4 converting a json to dart, go or similar is simply frustrating, you have to be doing touch-ups by hand and not a few.


Thanks a lot pal, exactly what I needed. It’s so relaxing to see recursion doing amazing stuff.

1 Like

I was about to write something similar, thought of checking if someone in the community has done something similar. This was very helpful! Have been using it happily with a few edits!

Thanks for the kind words!

I’ve been using the transformer plug-in in my last few projects and it been a blast (Transformer plugin). I’d suggest you check it out.

I personally am not using GraphQL for any new projects as it doesn’t fit my needs at the moment in combination with Strapi v4.


The Transformer plugin is great.


For the vast majority of users there aren’t too many reasons you need to reach for GraphQL :sweat_smile: Since we introduced the field selection and populate or even the nested relational filtering/sorting/ect. If anything you lose out on the ability to cache responses at the network level by using GraphQL.

(don’t worry GraphQL users, it’s not going anywhere :wink: but we are recommending to customers to use our REST APIs over GraphQL)


Sounds wonderful, but won’t doing that extra step before returning the data hurt performance-wise when you get lots of request with potentially large payloads?

@DMehaffy Thank you & Strapi team for this great product. I have been migrating a client from v3 to v4 we heavily use graphql and typescript on the frontend. We are now on a bottleneck that we cannot cross because of the added complexity of data and attributes layer to the response data. I see that there is a plugin for Rest, will the be any plugin for graphql anytime soon that addresses this issue, and whats the ETA? It will be greatly appreciated if we can get some ETA to reverse the response to v3 response stricture as I am on a time crunch for my client. The ETA will enable me to communicate this issue to my client. Thanks and hope to hear from you soon.

Based on the type of transforming the data I think it could add some latency but I think it could be negligible. It basically generates a different output for the API through a middleware so I think it’s about a couple of milliseconds but I’m not sure. It could be longer if populating more data.

1 Like

As a customer that choose strapi for its GraphQL support, it’s not very reassuring.
It’s getting very frustrating not seen the same level of feature between REST and GraphQL.