0

So say I have a system built on an Event Driven Microservice Architecture,

I have a service that invites new team members to an organization. The service publishes an object that looks like so

{
  ...
  "from": "my_name@mail.com",
  invites: [
      "friend@mail.com",
      "coworker@mail,com"
   ]
  
}

An email service is responsible for sending emails to the list of invites.

Let's assume that multiple services are listening to this event

Say I change the structure of the data

...
   "invited_team_members" : [
     {
       "name": "John",
        "email": "friend@mail.com"

      },
       {
       "name": "Tony",
        "email": "coworkergmail.com"

      },
    ]

...

How do I ensure I don't have to update every single micro service that is subscribed to this data object?

Adrian K
  • 9,880
  • 3
  • 33
  • 59
Katty Kay
  • 51
  • 1
  • 5

2 Answers2

0

Use event message versioning. It's relatively simple to create different versions of an event but just take care it really is a version and a completely new event. You should be able to transform or convert the old version into the new version, if you cannot you are likely to be looking at just a new/different event.

You can find guidance on this quite easily, but I find this page from MassTransit docs quite useful:

https://masstransit-project.com/architecture/versioning.html#versioning-existing-message-contracts

robs
  • 840
  • 10
  • 15
0

How do I ensure I don't have to update every single micro service that is subscribed to this data object?

It depends if your changes are "breaking changes" or not. A breaking change is one that will 'break' the consuming services, meaning they will be forced to re-code to cater the new event signature.

It also depends if you are talking about trying to avoid creating breaking changes or limit the impact of them when they happen.

The following guidance assumes you are publishing services consumed by external 3rd parties, but should also be helpful for internal ones as well - i.e. if you/your team are the only developers.

Breaking Changes

  • Adding optional fields will not break existing consumers because the optional field can be ignored - assuming that's all that has changed.
  • Changing the data structure or adding mandatory fields would force a breaking change.

Therefore, if you don't want to break the consuming services then you can't break the existing contract / API specification that your service is providing and which they are consuming.

Versioning

Versioning can help here, but it means adding a new version of the service and letting consuming services migrate to the new service when they are ready. Doing this means you won't break (have to update/re-code) every consuming service now, but you will have to migrate them at some point. It also means you'll have to provide and maintain all active versions of the API for a period of time.

You can use major version number increments to indicate breaking changes, and minor version number increments for non-breaking changes: v[major].[minor] E.g.

 - MyAPI v1.0
 - MyAPI v1.1 - added new optional field (non-breaking change)
 - MyAPI v2.0 - changed data structure (breaking change)

If you are going to use a versioning approach, and support multiple versions, set and provide some policy around this so that service providers and consumers all have consistent expectations, e.g. you might say something like:

Version N-1.x will be supported (where N is the current version, 
and -1.x is the previous major release and it's non-breaking updates).

E.g, on release of v3.0, v2.x remains in support, all v1.x versions fall out of support:

- MyAPI v1.0 - Unsupported
- MyAPI v1.1 - Unsupported
- MyAPI v2.0 - Supported
- MyAPI v2.1 - Supported
- MyAPI v2.2 - Supported
- MyAPI v3.0 - New Version

If v3.1 was released v2.0-2.2 would remain in support. If v4.0 was released then v2.x would fall out of support. You can still release patches for older versions to fix bugs - e.g. if v3.x is the current version, you could still publish v2.3.

You should also set expectations around major release cadence so that consumers know roughly how long they'll have a stable version for, and when the older versions will fall out of support.

Adrian K
  • 9,880
  • 3
  • 33
  • 59