Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to best share and store enum-like data between microservices?

Situation: A microservices architecture with:

  • Microservices are written in Java with Spring Boot and Hibernate
  • An options-service which provides information about Options via a REST interface
  • Option data which could be modelled as follows e.g. via an enum (representative)
    • Has some attributes like enabled status associated with it. It is unlikely that more attributes belonging to Option will be added in future which have to be directly tied to it.
    • New Options and OptionTypes have to be seldom added. They will never be deleted (just disabled if need be).
    • An Option should have a unique identifier which can be referenced
    • There should be no UNKOWN option if possible
enum OptionType {
   TYPE_A,
   TYPE_B,
   TYPE_C;
}

enum Option {
    TYPE_A_X1(TYPE_A),
    TYPE_A_X2(TYPE_A),

    TYPE_B_Z1(TYPE_B, false),
    TYPE_B_Z2(TYPE_B);

    TYPE_C_U1(TYPE_C);
    TYPE_C_U2(TYPE_C);
    TYPE_C_U3(TYPE_C);

    private final OptionType type;
    private final boolean enabled;

    Option(OptionType type){
        this.type = type;
        this.enabled = true;
    }

    Option(OptionType type, boolean enabled){
        this.type = type;
        this.enabled = enabled;
    }
}

  • Other microservices (currently 3) need to be able to access Option data. They need to know which Options exist and somehow reference an Option e.g. via its name or identifier
    • One of those services (example-service) needs to provide the Option data type as filter settings in its own REST interface to the outside world. The filter object in JSON would look something like this:
{
  "typeA": "TYPE_A_X1",
  "typeB": "TYPE_B_Z2",
  "typeC": [ "TYPE_C_U1", "TYPE_C_U2"]
  // more filter settings
}

Different approaches of storing and sharing this Option data between microservices as I see it:

  • options-service stores Option data in its own database. If I read my data from database into my Hibernate entities Option is only a String everywhere from there on.

    • Pro:
      • Easy to rename, add and remove Options
    • Con:
      • No type safety when working with Option in code e.g. when deserialising a response containing Option
      • example-service cannot easily offer Option data in its OpenAPI doc (just Strings)
      • Microservices need to query and cache Option data from options-service
  • Option data only lives in source code in an enum as e.g. modelled above and is shared between different services via a lib.

    • Pro:
      • Type safety everywhere where Options are needed. Really useful when deserializing reponses containing Options data but also for generating OpenAPI doc
      • Microservices can still reference an Option in its database via its name since it is unique
    • Con:
      • Editing the name of an Option is difficult
      • Removing an Option not possible
      • If a new Option/OptionType is added the order in which the services relying on that lib update their lib version matters. Since we cannot deserialize responses into an UNKNOWN Option type.
  • There is also the possibility of a mixed database and enum solution which comes with the big drawback that one has to maintain both sources of truth.

What is the best way to store and share the Option data between microservices? What is best practice?

like image 279
christopher.online Avatar asked Jul 02 '21 08:07

christopher.online


People also ask

Is enum a code smell?

Enums force you to use multiple switch case One primary reason ENUMs are considered code smells is that they tempt you to sprinkle switch statements throughout your code.


Video Answer


2 Answers

While enums are very helpful in most programming languages, they can become a nightmare in inter-service communication. If you use an enum in your microservice endpoints, it becomes part of the API specification. Changing them on one side will result in problems of serialization/deserialization on the other side. So you should only use enums in your API if

  • you are definitely sure they will never change (e.g. weekdays) or
  • you are the owner of the code of all participating services and are able to orchestrate a big bang redeployment.

In these cases, you may create a shared lib between your services.

If this does not apply, make your life easier and consider most enum-like data (e.g. currency codes, country codes) as simple string values that are subject to change. If you want to have a central management for these values, why don't create a microservice for it that acts as a master? That's what microservice architectures are made for. Offer some endpoints that other services can query from time to time. You don't even need a persistence layer for that.

like image 100
oliver_t Avatar answered Oct 23 '22 00:10

oliver_t


Another option : Use the first option, but with a specialised class.

  • This allow for type safety,
  • but does not require your enums to be known at compile time.
  • Still, if you need to check the validity of your Option instance, you need a service that has cached the list of allowed Options.

Example code:

import com.fasterxml.jackson.annotation.JsonValue;

public class Option {
    @JsonValue
    private String value;
        
    Option(String value) {
        this.value = value;
    }
}
like image 38
unautre Avatar answered Oct 23 '22 01:10

unautre