It's interesting reading this because I implemented a Node.js solution for this problem years ago but it fell on deaf ears. GraphQL was getting all the attention at the time.

https://github.com/socketcluster/ag-crud-rethink

I wrote it for RethinkDB but it could be adapted to any database as it doesn't rely on changefeeds.

I then ended up building a complete serverless solution around it: https://saasufy.com/

It borrows many concepts from REST but works over WebSockets. Why WebSockets? Two major reasons:

- It had to support real time subscriptions/updates so that the views could automatically update themselves when data changed (e.g. with concurrent users). I didn't want to force the developer to manage channels manually as it can be a major headache to get the subscription order right and to recover from disconnections without possibility of missing any update messages. Also, my library SocketCluster already supported client side pub/sub with clustering/sharding on the back end so I wanted to leverage that mechanism.

- WebSocket frames are tiny and don't have all the overhead of HTTP requests so it's possible to have field-level granularity which is important for avoiding resource update conflicts. This is something that the GraphQL developers also figured out at some point. But the challenge with true end-to-end field-level granularity is that loading a single resource would require a potentially large number of requests to be made; hence HTTP requests are not suitable for this (imagine HTTP headers containing cookies being sent for every single field of a resource), however, WebSocket frames are ideal for that as they have tiny headers. You can handle maybe 100 WebSocket frames for the same cost as a single HTTP request.

End-to-end, field-level granularity is powerful as it allows subscriptions to be set up automatically per-field and access control can be enforced automatically at both the resource and field level (for each of create, read, update, delete and subscribe operations). It's also very useful for caching because different views may display different fields of the same resources with some shared fields so caching field values allows different views to share cache.

The overarching philosophy behind end-to-end field-level granularity is that it allows the system to treat each field of a resource as an independent entity with its own subscription/synching mechanism, access control and cache.

SocketCluster was designed to facilitate extremely cheap pub/sub channel creation (both in terms of CPU and memory) and automatic cleanup so it seemed like a good use case to build on top of my existing work. The code of ag-crud-rethink is quite simple... Only about 1.5k lines of code and probably could have been a lot smaller without all the bells and whistles.

The view mechanism also supports real time updates. It can be thought of as a parameterized collection. You define a 'view' with one or more parameters to control the filtering and/or sorting (though you can construct essentially any query on the back end). The idea is that the parameters for the view are provided by the client. This means that you can represent any view of a collection as a simple string which can be used as a channel name; this is useful for efficiently delivering real time updates since we only want to deliver resource change notifications to views which include that resource. During writes, field names can be cheaply matched against view parameters to decide which instances of the views need to receive the notification. Only clients which are looking at an affected view right now will receive the notification.