My goal is to create an architecture in which services should be able to deploy independent of each other and are completely autonomous, but what do you do when you have 2 services that reads from DB the same object type?
In my case I have a socket server (micro service 1) and a http server (micro service 2). Using the http server my users creates an asset called: A, this asset gets stored on a DB and a mongoID is returned. Then, using another protocol and the ID, there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB. This two services will have to share the model of A in order to map it to an object, but this means the 2 services will have to share code, and that's not ok.
Do I need another service? or should I make only service1 able to read from DB and then make the second one talks to service 1?
They should not share any data between them, aside from an ID used for correlating the Authentication context's "User" with the other context's "User". They can each have their own representation of what a "User" is, and their own domain model, which just the information needed to perform their business responsibility.
In the shared-database-per-service pattern, the same database is shared by several microservices. You need to carefully assess the application architecture before adopting this pattern, and make sure that you avoid hot tables (single tables that are shared among multiple microservices).
Microservices help solve the issue of coupling, to achieve that you need to keep your services/components autonomous, which means they can't share anything, not code assemblies or any resources, especially not the database.
If you need a read only copy of the data you can use patterns like publish subscribe to save a local copy of some information your component needs (subscribe to an event like NewUserCreatedEvent
: new user was created and his id is this guid for example), there should be only one owner of the user data in the system and the owner is the only one who can modify the state of the data he owns, the rest of the components in the system can keep a local copy of reference data for read only purposes.
this asset gets stored on a DB and a mongoID is returned. Then, using another protocol and the ID, there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB
In your scenario the client that creates the user should provide the id (a guid), the component that owns the user (therefore it's the one that creates it) will publish an event the other component (service) subscribes to and stores the data it needs in it's own database.
Does that make sense?
... there are calls to the socket server that needs to check that validity of that ID, thus, needs to read from DB. This two services will have to share the model of A in order to map it to an object, ...
Well - no, they do not need to share code! The only thing they actually need, is a common understanding of the schema of the DB (I assume you're using MongoDB). Whether that understanding is coming from shared class definitions in shared libraries or from duplicated class definitions in separate libraries does not really matter. Many developers will now start screaming at me for violating the DRY (Don't repeat yourself) principle, but with microservices many things are different to what we're used to!
In her answer, Priti Singh states that:
Two microservices should not share same data model
which in correct in a microservice context and considered good practice! Let me show you why:
In the microservice pattern, services should be independant of other sevices and have well-defined interfaces. Having two different services reading the same DB makes that DB another "service" (I KNOW, weird, right?!?). By definition this database now needs a well-defined interface - which is kind of difficult in a schemaless DB ;-) Another reason not to make a DB act like a service is, that changes in one service will always have some influence on the other service accessing the data. This means, changing the "schema" on one service might force you to change another service as well, just to keep your system running! That's a headache when you consider a full-blown microservice system with >100 services.
That is why your second idea:
... or should I make only service1 able to read from DB and then make the second one talks to service 1?
is much better. Keep your database hidden behind a service with a well-defined interface that can be versioned. Like this you can refactor inside service 1 as your heart desires without necessarily influencing other services. Once you need to make a breaking change on your interface - give it a new version and start migrating other services to use the new interface.
The underlying controversy in your question is the one of Coupling vs. Duplication. Sharing an interface definition and database is coupling (the wakes-you-up-at-night-after-a-small-change kind of coupling) but duplicating the database schema to both services is duplication. I believe that coupling will kill you long before duplication does, but taking your second approach, having the http-service access the socks-service which then accesses the database should remove duplication as well as reduce coupling!
Let me know if this was helpfull!
Two microservices should not share same data model. You can create a service which is solely responsible for managing data persistence, and can use it in other services.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With