If I understand correctly, you're suggesting to cache on a data-layer level (below the app in the stack) instead of what we do - above the app in the stack - just in front of the client.
That is also a valid approach. It'll need more custom code in your application and has the disadvantage, that your origin will still be hit on every request, while we fully cache on the edge - cached queries won't hit your server anymore and will take load off origin and have the minimum latency possible.
> making sure, that when content changed, to invalidate it properly on the edge is not trivial
The trivial way to do this is simply not to invalidate. Include a version in the cache key. When content changes, the version increases, and clients get new versions. (I think this is sometimes called lazy cache invalidation). It works well with LRU caches. It's still a hit for the top-level keys, but you avoid all the heavy data load and rendering.
Granted, that doesn't solve every case, but I'm not sure it's fair to say that it'll take more custom code when the initial approach took "months building custom caching" that never really worked. Also, I think you'll find your origin under less load due to having fewer variants.
[0] https://blog.codecentric.de/en/2020/05/how-to-secure-a-graph...
Could you not abandon GraphQL? Returning non-customized responses, while taking more bandwidth, is much more cache friendly for the client, proxies and particularly servers - where you can do simple yet powerful things (e.g. version-based invalidation and pre-generated payloads).
Like, I went to https://spectrum.chat/explore and clicked on "Tech. It uses GraphQL to load the communities.
Why not just hit /v1/communities?category=tech
which would loosely translate into one of:
-- if you want to serialize the object on each get
select * from communities where tags @> array['tech']
-- if you can look up the communities in a cache by id
select id from communities where tags @> array['tech']
-- if you have a high read / write and can just pre-serialize the payload and then glue together the response
select summary from communities where tags @> array['tech']