Skip to content
27 min read

What are the best practices to build digital products with event-driven architecture

Why we created Breeze? The first reason concerns digital user experiences. There are two aspects of user experiences that we want to tackle as part of Breeze, the first is how to make sure conversational interfaces are an integral part of every application. The second concerns highly personalized applications. Multi-device design is a given. That isn’t something we need to do anything special about, but personalization and conversational interfaces are the two key aspects that we want to be able to provide for and both of them have components in Breeze, which allows you to build conversational interfaces as well as create personalized experiences using AI.

Code generator

We also realize that a large part of our effort to build UI is wasted in building things like forms, reports and templates. And, we don’t want to deal with these things again, but we can’t wish them away. So, we’ve created a very flexible forms engine, reports engine and templates engine; which allows us to define forms not just along the conventions that have been used in server-side HTML applications. These are generating code in Angular and React. Our approach when we talk about any of these engines is to automate the development process, and not create it as a monolithic engine which later becomes a dead weight. So, the most important thing in any of the engines, whether a forms engine, reports engine or a template engine, is the code generator. This will generate the code that you would have otherwise had to write. You can then take that code, modify it and maintain it when required.

That’s a big deviation from conventional frameworks, because conventional frameworks tend to tie you down and none of us want to invest in unnecessary effort which forces us to continuously maintain legacy code forever.

So, one of the most important principles that we kept in mind while designing Breeze was to generate the code so that the engine becomes an accelerator rather than a burden to the application’s architecture.

Build for change

The second reason we created Breeze was to build for change. We know that today’s applications are not built to last, they’re built to change. The entire principle of microservices and event driven architecture is to keep changing applications fast. There are two important aspects to business applications, entities and workflows. Practically every application would have some business entities, workflows, or sagas that span multiple entities. So, we’ve created two engines, an API engine basically helps you create an entity microservice almost out of the box, and a workflow engine, which allows you to define your orchestration between multiple microservices or manual tasks, by using a BPMN diagram. There’s nothing wrong with BPMN, because BPMN already incorporated service tasks, meaning you could orchestrate between microservices using a workflow that was defined using BPMN. The problem lies in the execution engines of conventional workflows, which are monolithic and non-scalable, and we cannot really use them as an orchestration engine for scalable architecture, like microservice architecture. So, we retained specific components from conventional workflows, such as how to use user defined workflows, but our execution engine is very different.

Event-driven Architecture

One of the principles that drives these engines is event driven architecture. Events become a core part of any application, and when we build application architecture we have to look at the event as our primary data model, rather than as a secondary afterthought, while our objects become views on your events. Let’s say a customer comes and expresses an interest in a product of yours, you have to look at this event and find out what objects are interacting that particular event, and those are secondary in nature. You have to capture the fact that this event occurred.One very important part of event driven architecture concerns how in all conventional data models today, the primary keys are entity keys. When we build a user having a primary key or an ID, other objects such as an order, a product, have primary keys and then we build relations between these entities. In an event driven architecture What is the primary key? Time is the primary key. What happens at a specific time is considered the event. The identification of the event becomes the core entity, around which other entities form metadata about that event, and your view of the metadata of an event may change from time to time. Yet we treat time as a secondary field. We ask when the order was captured and answer with a specific time. But that order may have taken place due to several business events that we lost track of, and how are you going to be able to build an AI model if you don’t even know the journey that the user took, when coming to a particular entity that is represented in your database. Therefore, I find event driven architecture to be much deeper in its implications than merely rewriting our applications by putting up an event queue. The easiest thing to do is to use something like Kafka and assume that we are going to magically convert our applications into event driven architecture, but unfortunately that isn’t the case. The last point is equally important, we don’t know how fast and how big our applications are going to get. The cloud certainly helps from an infrastructural perspective, but what do we do about application performance? A monolithic architecture might be much easier to manage than a distributed architecture, and if all we wanted to do was to get the product out faster to market, it is not necessary to build a distributed architecture, because that actually tends to be more difficult to maintain.

Scalable architecture

But the important thing is about performance, so when a start-up tries to quickly put something together and put out a prototype, it may possess all the necessary features, but it is unlikely to be scalable, because you cannot really scale up your API infrastructure, or your data infrastructure, and all of these problems become technical debt that you have to take on in phase two or phase three. So, the objective of Breeze is to design the application to be scalable on day one. It needs to be event driven on day one and we need to be able to build for change, as well as making sure that our user interfaces are exceptional.

If you look at the blueprint that we defined last year, you’ll find that Breeze covers personalized UI in the frontend, It has an API abstraction layer which allows the frontend to be independently developed from the backend. You will also see the API abstraction layer which allows the frontend to be largely independent of the backend by using GraphQL as well RESTful APIs. in the backend, which starts from entity and workflow microservices, we start building the entire stack at the backend by using a loosely coupled architecture. But if you have truly independent micro services, they should not be calling each other’s APIs. They should be talking through an event queue. And if you’re truly event driven, and events are your primary data model, then those events need to persist in the data lake. Because that’s the only place that you can keep such a large amount of unstructured data, due to the fact that each event is different from the other event. Therefore, if you don’t have a Schema-less data lake architecture which allows you to store raw data without any restrictions, you’re not going to successfully be able to keep track of events. So, unfortunately for us none of these components can work without the other.That is not to say that we’ve never built applications with only some of these components. We have called certain applications microservices because they’re independently deployed services, but they’re still tightly integrated and call each other’s APIs. that’s why I said this degree of adoption of micro-services you may still say instead of monolithic, I’ll just split my application into multiple services, but they still talk to each other that’s one level of adoption and then you get to the next level and say, hang on I cannot sustain this and so I have to make them event driven but my data is still all entity based, and I still don’t have a store for events and then you end up creating a data lake. So all of these go in sequence, but if you have something like Breeze, you should be able to start doing all of this right from day one, rather than delaying and adding technical debt to your application. The idea that we want to incorporate in creating Breeze was to state that we do not want to reinvent and keep adding technical debt as we move forward.

How to build an application on Breeze

If you look at a typical scenario of how we would build an application using breeze, what you see on the screen in white is everything that breeze will provide out of the box. So, you should be able to get a platform which allows you to build your personalized UI applications using your business rules in your entity and workflow micro-services, integrating with your existing business applications and being able to derive insights based on your business needs from the data lake.

We have custom built components. When we say custom built, you do not necessarily have to build them from scratch, as we do have accelerators or code generators which will help you to define your microservices, create UI components, define analytics or integrate with business applications. We did a survey of our own products last year and found that on an average when it came to the number of story points that we spent in building platform services, such asIdentity Access Management, logging, cashing, work-flow and other common denominator capabilities that every application needs, between 30 to 35% off our story points in our backlog went to platforms services. So, as you can imagine we are reinventing the wheel and may not necessarily be getting it right every time. Which means not only are you spending 35 percent off your budgets on platform services, which ideally should have been ready out of the box, you may not do it right. Why do most people not do it right? The simple reason is that they don’t add any competitive advantages to their application. Why spend so much effort in building a scalable IAM application when you can just get it ready out of the box from somewhere else. Then they short-circuit the whole process and put the application on AWS IAM. This is an easy decision to make in day one, but they then create a technical debt because tomorrow if it turns out that the application needs to run on the edge, and they’re not able to do IAM calls over the network with Amazon all the time, they’ve then got to reinvent their IAM, which is the core of the whole application. If you don’t have Identity and Access Management your application is just not going to work. A small decision like which IAM platform to use can have huge impacts on technical debt as you go forward in your application. So, the point is we would typically reinvent the wheel for every product, asking which IAM platform to use, such as the cloud, an opensource application. Or something else. All of these questions take a lot of time to answer and we make bad decisions because we don’t prioritize them, leading to you spending a lot more effort in the long run. So, in making breeze we first found the need to be able to pick the best in class open source components, whether IAM, workflow, or any of other capabilities. The second thing we found was that if we create any of the code, it should be released with an MIT license. MIT and Apache licenses mean that you can effectively use any component of breeze as part of your product with no intellectual property encumbrances on that code. This means that you’re going to be able to do what you want with it depending on how your roadmap moves forward.

This year we did another important exercise in the process to evaluate breeze as an overall platform for most of the applications that they plan on building. We involved a third-party audit for breeze, and so we had an organization called Cross lake do the technical due diligence and look at all our code. They went through the licenses, they went through performance analysis such as how much testing we have done, whether we are performing unit testing or automated testing. They went through all these matters with a fine-toothed comb. The summary they gave us was that we passed with flying colours. So, it was a great sort of validation of the effort that we’ve put in. We want to make sure that we don’t want to write code here unless we want to change it. Therefore, everything is unit tested, documented in wikis and all the code is documented. We have Swagger API definitions for each and every platform service, GraphQL is supported by each and every platform service, all of the components are event driven and event aware from day one.

It’s all open source

If you look at the range of open source platforms we have incorporated as part of Breeze, It covers most of the best platforms in their class. The important question here is, how did we decide which platforms to use, such as Keycloak for identity access management. The answer is that we spent months together researching every different IAM platform before we decided that we wanted to use Keycloak. We also have used Keycloak with several customers in the past as well, so it’s not just a theoretical comparison exercise. We’ve actually used multiple IAM platforms in products that Accion has built and we have talked to each of those product teams to look at the advantages and disadvantages of different implementations they used, and based on that we made our decisions on which platforms to use.

I’ll give an example of an actual situation. A key component of any platform service is the workflow engine. In our workflow we decided to go with Camunda, which is the best open source workflow platform in its class. But Camunda is billed as a monolithic workflow application, which means it is not going to be able to scale for the orchestration of microservices. What then happened has been very good news for us. Camunda itself began coming out with a new engine called Zeebe, which is a scalable microservices orchestration framework. Now Zeebe is not yet released, but it is likely to be released in 2019, as we have been following zeebe for the last two years and participating in its open source development process. It is an open source platform and we have been involved in the development right from day one, because we knew that this is something that we are going to require as well. The important thing to note here is that if you had used breeze and you knew that it was using Camunda, and we decided to change it from Camunda to Zeebe, the biggest benefit you’re going to get is that the APIs, or the integration is abstracted away from the core platform. This means that the APIs that you are going to use in your microservices for building workflows will not change if we change the platform from Camunda to Zeebe. That is our guarantee. Because it’s not just to you as a customer of ours, we are ultimately going to use Breeze to build our own applications as well, so we don’t want to reinvent the wheel and create unnecessary technical debt for ourselves either.

Platform services

There will be new features which may not be supported by the old platform, or some old features which may get redundant in the future, so there will be feature changes, but we want to make sure that we don’t create unnecessary technical debt.

The idea is to make sure that Accions efforts move in a direction where we can create long term value for our customers, rather than merely giving you development services. We want to be able to use breeze as a model which allows us to own and drive your platform services, which don’t give you significant competitive advantages and we’ll be able to own and maintain them for you and make sure that we’re keeping all of the best engines in mind while we maintain them. In addition to some of these open source engines, we ourselves have developed many off the engines that are incorporated in Breeze. Zephyr is a conversational interface platform, Alizeh is the personalization engine which also uses A.I, we’ve built a notifications engine and an extremely powerful event response system which allows you to respond to events in multiple ways. We have built an API engine which is a code generator for entity micro services. We have even created forms reports and template engines for the UI components.

There’s a lot of effort that has gone into building these. Another invisible part of Breeze is the automated deployment. Now, we’re going to try and show you what we have done, as our principles of automated deployments start from the development process.

The simple question I want to ask you is, when you as a developer will write your code as part of a sprint, How do you test it? In a microservices environment, you may have hundreds of microservices and there may be dependencies which are not direct dependencies, so you can’t merely call an API. You have to raise an event and then see whether the resultant action took place or not. How are you going to be able to test this in a sprint? When mid-sprint everything is in motion, all the other services are moving at the same pace as you. So, how do you test an application like this? in a monolithic application it was always easy, because all the code was embedded as part of a single code base, but in microservices testing is no longer a no-brainer.

So the DevOps process has to make sure that in every sprint we have versioned micro services, which are deployed in containers, that anytime you want to be able to create a combination of microservices, which represents a particular state of the entire application, you should be able to test any microservice with any combination of other microservices using event driven architecture. This is not a trivial matter, it may sound simple, but today’s default configuration in Kubernetes is that if you create a microservices ID and you redeploy your code in GitHub, it just wipes out your old code and creates a new container. How do I keep track of versions of my microservices, and how do I make sure that the right version moves from development to QA to production? It’s a non-trivial exercise and there is a lot of work that needs to be done to get this right. That’s the invisible part of Breeze. Of course we use a lot of the technologies to do that.