cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

Separation of query/message layer from transport layer

monohusche
Node Link

Hi there,

we are currently exposing a GraphQL layer ("BFF") on top of a universal REST layer (both for queries and mutations) while using PostgreSQL as our standardised data store in the backend.

At the same time, we do realise the implicit differences between READ and WRITE processing (=CQRS).

While the mutation/business logic is clearly vertically separated by product lines, all successful transactions (no matter which product) result in events being emitted which are injected into a "single customer view" service that feeds our (GraphQL) queries.

Needless to say, this "single customer view" represents a backend enterprise graph from a conceptual level, and using Neo4J instead of a relational database would most likely result in massive improvements, both dev and runtime (due to avoiding the impedance mismatch)

So, we are considering to replace the backend data store for the READ side with Neo4J. Of course, this also includes utilising the neo4j-graphql-js Apollo plugin (as per GrandStack).

The only issue is that our security boundary still sits to the right of GraphQL (GraphQL being part of the frontend), so we can't allow Apollo to directly connect to Neo4J via bolt.

In essence, we only need the transpilation capability (transform a GraphQL query to a Cypher Query). This cypher query would then be wrapped into a HTTP message that can be validated by our edge API gateway layer (only header level, i.e. tokens etc.) before being forwarded to a facade service ("SingleCustomerView Service") which owns the Neo4J database.

TLDR:

It seems, the neo4k-graphql.js package bundles message/payload translation (GraphQL query to cypher query) together with protocol translation (HTTP --> Bolt), rather than making these two "pieces" available as separate modules.

We only need the payload transformation (GraphQL --> Cypher) while keeping the transport layer intact (HTTP).

Can this be done today ?

4 REPLIES 4

Is there a way to convert graphql to cypher on the client?

Yes, but doing it the way you're asking is a fairly edge use-case. That means you are likely going to have to fork the neo4j-graphql project, and adjust it to meet your needs.

Security is you main concern?

This sounds suspiciously like you're trying to shoehorn Neo4j/GraphQL into old corporate security standards. Ultimately, you want to write GraphQL in your app, have a middleman authenticate a token, and Neo4j under the hood? Such a system would result in only one way to prevent abuse: strict and rigid control of those tokens.

That said, why not simply pass the GraphQL onto the "SingleCustomerView Service", and put the neo4j-graphql-js behind the middleman? You'd accomplish the same goal, without needing any custom development, and could also implement GraphQL validation at the middle layer.

monohusche
Node Link

Fair point.

As mentioned, we consider GraphQL part of the frontend, i.e. from an ownership perspective, all content/code within GraphQL is driven by frontend needs and owned by the respective frontend team.

Moving GraphQL into the "SingleCustomerView" itself as per your proposal means that we conceptually make GraphQL part of the backend, i.e. it becomes the main API (at least for this service) rather than a "massaging" facade BFF layer which is part of the frontend.

The issue that neither option addresses (whether backend or frontend) is the fact that the GraphQL schema contains both frontend and backend content/definitions. While the types are ultimately owned by the backend, especially the query types are clearly specific to the frontend.

so the same component (schema) is co-owned by different teams which sounds like an antipattern to me.

Of course, this is orthogonal to my original challenge/post, so not really related to Neo4J and the plugin

The only additional comment that I have is that modularity/separation of concerns is a good principle to apply in any case.

If neo4j-graphql.js would cleanly separate between "layer 8" (=payload/query transformation) and "layer 7" (=transport protocol transformation), then we could implement such a change in an iterative way, rather than combining both changes (replacement of backend data store + replacement of API layer) which is more risky and less agile.

But point taken, thanks!!

Ah, I wasn't suggesting moving the entire thing behind the middleman and having the queries live outside of the app. More... use the middleman as a proxy.

              APP                                     gateway                                   service                             Neo4j
      GraphQL query                ---  token validation  --->  neo4j-graphql-js execute query  --->   data
                                                                                                                                                      |
      data response handler    <-------------------------------  forward response                 <--- response data

Sorry, had some significant misunderstanding about GraphQL.

Your points make total sense, thx !!