javaspringneo4jmicroservicesspring-data-neo4j-5

Neo4J In Microservices Architecture


To keep in line with DDD and Bounded Contexts, its well known that when you create your microservices you should keep separation of concerns.

One of the main benefits of Neo4J is keeping your "connected" data in Neo4J so relationships between them are efficiently queried.

These two opposing forces seem to make an microservice architecture decision difficult when choosing to use Neo4J.

Do you have multiple microservices connect to Neo4J db and persist their own domain accordingly?

OR

Do you have one microservice with a db connection to Neo4J that controls persistance and querying?

Both dont seem quite right...


Solution

  • The pattern of database-per-service is discussed here, and breaks down the options to:

    1. Shared database, but private tables per service.
    2. Shared database, but private schema per service.
    3. Separate database per service.

    Obviously 3 is going to be the most expensive, as you would want each Neo4j instance to be on its own server so it has dedicated memory and hardware, and if you need a clustering solution then this becomes a separate cluster-per-service. Not recommended, especially if just ideology is the driver for this decision.

    1 and 2 are better options, especially if the data accessed across microservices is related intrinsically, as Neo4j works best when storing connected data, and loses its value the more the data is siloed between multiple databases.

    That said, there are some challenges with these options.

    Neo4j does not use tables, and does not currently have separate schema to divide visibility of data between different users.

    While you can have the microservice only use defined queries that only touch specific parts of the graph, this is often looser control than is required.

    You can instead use the subgraph access control approach, and this is the one I would most recommend for your needs.

    This boils down to creating procedures that encapsulate the queries you want to be available for each microservice (that either use the Java API directly, or make a Cypher query from the procedure code), and then creating custom roles for each microservice (without read permissions), but allowing them to invoke the appropriate procedures. This ensures that the custom role per microservice is only allowed to interact with the graph through the allowed procedures (and the procedures of course can do whatever they want without being constrained by the roles or permissions of the calling user).

    As far as a multi-tenancy approach, keeping data separate between different graphs on a single database, that is a feature of high interest right now, and implementation is in the works. Look for this in upcoming releases in 2018. That said, whether this would be useful to you or not depends upon the implementation of this feature, and the nature of your data.