10 principles for your event driven architecture

/\\: Fabien PORTES - Jun 7 '23 - - Dev Community

Today I had the opportunity to assist at the Serverless day event in Paris. This event is dedicated to fostering a community around serverless technologies. There have been many conferences especially about AWS lambdas optimization and architecture and event driven architectures. These topics are indeed key in the serverless world.

One conference particularly held my attention. Luc VAN DONKERSGOED, AWS Hero gave us 10 principles to avoid chaos in a serverless event driven architecture journey. I will summarize them in this article to make you find peace of mind in case you are working on a microservices event driven architecture.

The principles are divided in 3 categories.

Event design

Use Json, not text, yaml, Avro or Protobuf

Using json as a unique message format is the way to go in the event driven architecture paradigm because json is evolutive. Your events payload is likely to evolve and json can support you in this evolution with the introduction of new keys without breaking changes.

Json is also extensively and natively supported by most of the services and libraries you can work with.

The benefits of compression from an Avro or Protobuf format is not worth it as it will require some extended decompression steps. Yaml is also not recommended because it is made for humans not for machines and usually needs a specific parser to be decoded.

Use event enveloppe for metadata

Your event will benefit from transporting metadata related to it, like a unique identifier, time at which it was generated etc… These metadata should be part of the json payload in a dedicated entry. The payload itself should appear in the data entry so that the payload looks like the following:

{
  "metadata": {
        "event_id": "uuid",
        "event_time": "Timestamp"
    },
    "data": {
        "height_kg": 12,
        "width_cm": 14
    }
}
Enter fullscreen mode Exit fullscreen mode

Metadata will help in the observability of your microservices architecture.

Use unique event id

You should embed in the metadata of your event payload a unique id of your event. You can easily generate a uuid to do so. Unique identifier of your event is crucial to trace events and make observability of your solution real.

By following these 3 first principles you can design event payload in a way that will let you make them evolve easily. Now we need to evolve and communicate within our microservices.

Communicate and evolve

Use schemas and contract

The first step to enable serene communication between your microservices is to use a contract between your microservices. These will make a consumer services not to know anything about the producer service but only know the contract that bound the producer to its output. This will ensure decoupling of producer and consumer service.

Maintain backward compatibility

Once you define a contract between your microservices, you should include in your metadata entry the version of the event schema. In case of a breaking change, the event version will evolve and the consumers of these events will know what version of the schema to use to adapt to it. This will ensure you can maintain backward compatibility.

Maintain schema registry

For a consumer to retrieve the schema of an event, we need a central place to store the schema of your events. This is the responsibility of the schema registry, a single source of truth of all the schemas of the events generated by your microservices.

You can use json schema to declare the schema of your event version.

Use an event broker as a transportation layer

This is the key piece to decouple your microservices. Once you have a schema registry to store the contract between your microservices, you will want to use an event broker to completely decouple them. The event broker will receive the events of the producers and forward them to the consumers. In case of a failure of a consumer the event broker will act as a buffer for the events and the consumer will treat the events queue once it is back alive.

There is now no more interaction microservice to microservice but just producers that push events to the event broker and consumers that read events from the event broker. We now need some principles to integrate and support our event driven architecture.

Integrate and support

Use event supporting APIs

As your architecture evolves you will need to add entries to your data payload of your event. For example a consumer can need the color of a car while another needs the brand and another one the price. It can be tempting to add all of these information to your event payload but at some point the payload will get too big.

Instead you should make the producer expose a ressource APIs to get more information about the resource of an event. The event will hold the identifier of the ressource and you will query the producer to know more about the resource attributes. This way you can keep your payload size relatively small.

Use the storage first pattern

In order to avoid unpredictable latency of microservices, you should use the storage-first pattern. A consumer should first store the message, acknowledge the reception of the message and then process it from the storage. This way your microservices are even more loosely decoupled.

In addition, as your events hold a unique identifier and you store them, you can ensure the single processing of a unique event. Indeed you can check when an event arrives if it is already stored and if so implement the desired logic. This principle can also help make your architecture idempotent.

Trace your events

Last principle is about tracing your event for the observability of your microservices. You can include in the metadata section a unique trace id and span id that will help you build a monitoring system that can follow the trace of individual steps of a request. The trace id will identify the request while the span id identifies the steps. This information can be cascading in the event metadata section of the events.

I thank Luc VAN DONKERSGOED and I hope these principles will help you find peace of mind in case you're in the process of building an event driven architecture with microservices. If not, you can ask me for further guidance !

Thanks for reading! I'm Fabien, data engineer at Stack Labs.
If you want to discover the Stack Labs Data Platform or join an enthousiast Data Engineering team, please contact us.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .