Search code examples
architecturemicroservicessaga

Ensure state consistency by introducing a shared microservice?


Let's say I have 2 entities(aggregate roots) in different microservices.

  • Report(id, status = opened | in_progress | processed | closed, follow_up(custom form answers), investigation(custom form answers), ...)
  • Inspection(id, form_answers, ...)

I have a requirement to add a possibility to fill the custom(dynamic) form during the lifecycle of these entities.

Forms are created by users and it mustn't be possible to fill Report specific form in Inspection and vise-versa. Form structure(field types) and form submission(answers) model are the same among these entities.

My question is how to design it in microservices way, given the following domain constraints:

  • it must not be possible to edit Report follow_up once it in processed status except for some specific users
  • it must not be possible to edit Report follow_up when report is closed
  • it must be possible to fill investigation only when Report is processed
  • Form fields should be the same for every entity, which use custom forms

Approach #1

Introduce in each service a form entity and store answers in report/inspection respectively.

Pros:

  • State consistency(status checks for changing form answers is done in one aggregate, so it's easier to follow domain constraints)

Cons:

  • Code duplication(answers validation/entity structures/...)
  • Adding new field type requires to change multiple services

Approach #2

Introduce a new form service to store user-defined forms and form answers. Entities should reference answers only by id.

Pros:

  • Forms logic in one place

Cons:

  • Hard to follow domain constraints without tightly coupling or lots of saga's.

Solution

  • I'll give a bit of generic answer:

    A good microservices infrastructure is more about services solving specific business problems, and less about being interfaces for databases - this is a common mistake - a service literally looks like a proxy for database queries.

    Let me extract service ideas from your description:

    • "Forms are created by users": FormCreationService?
    • FormFillInService
    • ReportsService - it will have a state machine to make sure only correct transitions are allowed (e.g. no edit after completed)
    • InspectionService - also with a state machine

    The next step would be to describe API's for every service (please, find youtube video on "designing apis" very old talk at google).

    Then you validate api's by sequence diagrams - as a result you may merge services - in case they are too small; or split larger chunks.

    At the end of the day - you want to apply Unix philosophy for your services: "Do one thing and do it well".