1

Imagine you have a user registration form, where you fill in the form: First Name, Last Name, Age, Address, Prefered way of communication: Sms, Email (radiobuttons).
You have 2 microservices:

  • UserManagement service
  • Communication service

When user is registered we should create 2 aggregates in 2 services: User in UserManagementContext and UserCommunicationSettings in Communication.
There are three ways I could think of achieving this:

  1. Perform 2 different requests from UI. What if one of them fails?
  2. Put all that data in User and then raise integration event with all that data, catch it in CommunicationContext. Fat events, integration events shouldn't contain domain data, just the ids of aggreagates.
  3. Put the message in the queue, so both contexts would have the adapters to take the needed info.

What is the best option to split this data and save the information?

Anuj Khandelwal
  • 1,214
  • 1
  • 8
  • 16
DmitriBodiu
  • 1,120
  • 1
  • 11
  • 22

2 Answers2

4

Perform 2 different requests from UI. What if one of them fails?

I don't think this would do. You are going to end up in inconsistent state.

I'm for approach 3#:

  1. User is persisted (created) in your user store.
  2. UserRegistered event is sent around, containing the ID of the user.
  3. All interested parties handle UserRegistered event.

I'd opt for slim events, because your services may need different user data and its better to let them to get this data on their own rather than putting all the things into the event.

Alex Buyny
  • 3,047
  • 19
  • 25
  • 1
    This is my preferred approach also. You have a bit of a process so a *process manager* is in order. This would contain all the required state and issue the relevant commands from the orchestration implementation. It would also subscribe to any required events and respond accordingly, typically by issuing commands :) – Eben Roux Feb 22 '19 at 04:51
  • @EbenRoux its nice to see you again! could you please elaborate your comment into an answer? For now I used saga inside the bounded context, my question require using saga in an ApiGateway as I see it. – DmitriBodiu Feb 25 '19 at 07:38
  • I wouldn't want to steel Alex's thunder as I think he covered the gist of it :) --- if there is something in particular you'd like me to elaborate on I could do so. Orchestration *may* be a separate BC although I usually have the process managers defined as first class citizens in the relevant domain. The orchestration endpoint is usually separate from the domain endpoint as far as the messaging goes simply because the orchestration endpoint may communicate with other BCs whereas the domain endpoint only services domain requests. – Eben Roux Feb 25 '19 at 15:01
1

As you mentioned to store communication settings, assuming that communication data are supposedly not part of the bounded context of UserManagement Service.

I see a couple of problems with approach #3 proposed in other answer. Though I think approach #3 in original answer is quite similar to my answer.

  • What if more communication modes are added? Naturally, it should only cause Communication Service to change, not UserManagement Service. SRP. Communication settings MS should store all communication settings related data in its own datastore.

  • What if user updates his communication settings preference only? Why user management service should take burden of handling that? Communication settings change should just trigger changes in its corresponding micro-service that is Communication Service in our case.

  • I just find it better to use some natural keys to identify & correlate entities across micro-services rather than internal IDs generated by DB. Consider that tomorrow you decide to use completely different strategy to create "ids" of user for UserManagement service e.g. non-numeric IDs, different id generation algorithm etc. I would want to keep other micro-services unaffected of any such decisions.

Proposed approach:

  • Include API Gateway in architecture. Frontend always talks to API Gateway.
  • API Gateway sends commands to message queue like RegisterUser to be consumed by interested micro-services.
  • If you wish to keep architecture simple, you may go with publishing a single message with all data that can be consumed by any interested micro-services. If you strictly want individual micro-services to see only its relevant data, create a message queue per unique data structure expected by consuming services.

API Gateway in microservices architecture to perform writes

Vishal Shukla
  • 2,848
  • 2
  • 17
  • 19
  • "I just find it better to use some natural keys to identify & correlate entities across micro-services rather than internal IDs generated by DB" - I couldn't manage to follow this one. Could you please elaborate? – DmitriBodiu Feb 25 '19 at 07:40
  • "rather than internal IDs generated by DB" - We are not discussing the process of id generation here, do we? it could be generated by db, or client has to provide it. Or it could be generated by some domain service. – DmitriBodiu Feb 25 '19 at 07:42
  • "API Gateway sends events to message queue like RegisterUser" - seems like RegisterUser is a command, not an event? – DmitriBodiu Feb 25 '19 at 07:43
  • So Communication Service Message adapter would convert RegisterUser command into CreateUserCommunicationSettingsCommand and invoke the app layer. Is that the idea?@Vishal Shukla – DmitriBodiu Feb 25 '19 at 07:46
  • this solution means we have a monolithic UI, right? I remember Udi Dahan showed some solution, where on UI he merges different components in one html form, and when form is submitted, an event is fired, each component catches it, and sends separate requests to each service, so all vertical slice from UI to DB is separated. – DmitriBodiu Feb 25 '19 at 09:59
  • 1
    @DmitriBodiu, internal IDs generated by DB: I just meant to differentiate between "natural key" vs "Generated ID". Natural key has a characteristic that you can uniquely identify entity with just domain properties. By using custom ID generation, I think it is possible to achieve the same if API Gateway first generates ID using some service or on its own and then publishes command (which I referred as event) to be consumed by interested micro-services. – Vishal Shukla Feb 25 '19 at 10:11
  • 1
    "So Communication Service Message adapter would convert RegisterUser command into CreateUserCommunicationSettingsCommand and invoke the app layer. Is that the idea?" - yes, exactly. – Vishal Shukla Feb 25 '19 at 10:12
  • 1
    "this solution means we have a monolithic UI, right?" - Yes, that's right. – Vishal Shukla Feb 25 '19 at 10:17
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/189004/discussion-between-dmitribodiu-and-vishal-shukla). – DmitriBodiu Feb 25 '19 at 14:14
  • Now I'm wondering what to do if one of the commands fail? What if user was registered in one context, but because he didn't chose mandatory communication option (Email or sms) communication microserver validation fails? – DmitriBodiu Nov 27 '19 at 13:08