53

Imagine a scenario of two different microservices. One to handle Authentication within the service, the other one takes care of User Management. They both have a concept of a User, and will talk about Users through calls to each other.

Where would the Domain model of a "User" belong though? Would they both have a different representation of what a User is on the level of the database? What about when we have a UserDTO to be used in API calls, would they both have one for their respective API's?

What is the general accepted solution for this kind of architectural issue?

31

In a Microservices architecture, each one is absolutely independent of the others and it must hide the details of the internal implementation.

If you share the model you are coupling microservices and lose one of the greatest advantages in which each team can develop its microservice without restrictions and the need of knowing how evolve others microservices. Remember that you can even use different languages in each one, this would be difficult if you start to couple microservices.

If they are too related maybe they are really one like @soru says.

Related questions:

  • 16
    I can't completely agree, If they are completely independent then you have 2 monoliths. The idea is to have smart endpoints and dumb pipes. In enterprise context, you end up (currently my nightmare) hitting the wall because there is an implicit common domain model, (implicit because we didn't foresee it) and each service is reinventing a % of the wheel. And the ecosystem of micro-services is growing with a focus put 100% in functionality and team ownership, messing it up with domain model. We have teams creating new services, consuming others, duplicating much effort. Still unsolved. – juanmf Jan 21 '16 at 21:02
  • 4
    We have also left aside a very important Architecture Significant Non Functional Requirement, performance. These services needing other services' output, render a multilevel communication approach for each client RQ. Adding latency that can't be addressed unless a heavy refactor and possibly micro-service merging is made. – juanmf Jan 21 '16 at 21:07
  • 1
    Plus, not having a common understanding of the domain model, caused teams to apply unnecessary "unmarshalling + object-object transformations" to adapt micro-services responses to the model that the calling micro-service adopted. I know that coupling all services to a common domain model lib can bring other operational issues, but I find neither option satisfying. – juanmf Jan 21 '16 at 21:37
  • 1
    @juanmf It would be very valuable if you could post a question about your issues. I'm also interested in hearing opinions on this matter... – Milos Mrdovic Apr 24 '18 at 10:08
  • I'll try to sit and write something that makes sense – juanmf Aug 30 '18 at 23:00
11

If two services are sufficiently intertwined that it would be a pain to implement them without sharing DTOs and other model objects, that's a strong sign you shouldn't have two services.

Certainly the example makes little sense as two services; it's hard to imagine a specification for 'User management' so complicated it would keep a whole team so busy they don't have time to do authentication.

If for some reason they were, then they would communicate using what are basically arbitrary strings, as in OAuth 2.0.

4

You can think of them as two separate Bounded Contexts (in Domain-Driven Design parlance). 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.

Remember that a domain model doesn't try to model a real world "thing," but what that thing is in a particular context (such as Identity/Authorization Management, or Human Resources, etc).

0

They both have a concept of a User, and will talk about Users through calls to each other.

I also agree with what @soru said. If one service needs another service's data, than their boundaries are wrong.

A nice solution is what @pnschofield came up with -- treating your services as Bounded context.

Talking about the subject, put shortly: shared domain models kill service autonomy, turning your microservice system into distributed monolith. Which is apparently even worse than a monolith.

So there is still a general question unsolved -- how to define service or context boundaries, so that they thrive in high cohesiveness and loose coupling goodness.

I came up with a solution to treat my contexts as a business-capability. It's a higher-level business-responsibility, business-functionality, contributing to overall business-goal. You can think of them as of steps your organisation needs to walk though in order to obtain business-value.

My typical sequence of steps I take when identifying service boundaries is the following:

  1. Identify higher-level business-capabilities. Usually they are the similar among organisations from the same domain. You can get a feeling of what it looks like checking Porter's value chain model out.
  2. Within each capabilities, delve deeper and identify sub-capabilities.
  3. Note the communication between the capabilities. Look at what an organisation does. Usually, communication is concentrated within capabilities, notifying the rest about the result of its work. So when implementing the technical architecture, your service should communicate via events as well. This has multiple positive consequence. With this approach your services are autonomous and cohesive. They don't need synchronous communication and distributed transactions.

Probably an example of this technique would be of some interest to you. Don't hesitate to let me know what you think about, since I've found this approach really profitable. Sure it can work out for you as well.

0

Microservice is not about "share nothing", but "share as little as possible". In most cases "User" is really common entity (just because User is identified by some shared identificator - userId/email/phone). Such kind of entities shared by definition. The User model is out of scope one microservice. So you must have some global schema, where User (just their most common fields) should be placed. In strict case is id only.

protected by gnat Mar 25 at 21:19

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.