Practical Benefits of an Event Driven Approach
Tags: eventdriven, architecture
Published: 2022-09-20 12:13:32

There are a lot of articles that talk about Event Driven, but most of them do not give real and practical benefits of using it. This article aims to give a real and clear example.

## What is an Event Driven Approach?

Event Driven is a way to organize your system's code and architecture. When writing event-driven software, the code emits some events that will be consumed by other code or services. 
It decouples the pieces of code that emit events from those that consume it, making it easier to maintain and scale.

## Woovi

[Woovi](https://woovi.com/) is a Startup that enables shoppers to pay as they like. To make this possible, Woovi provides instant payment solutions for merchants to accept orders.
To accept instant payments, Woovi receives a webhook for each of the merchant's received payments.

## Woovi Transaction Sync

![Webhook Workflow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gbxkp2xlwfp1ghd6sdcx.png)

The picture above illustrates the new transaction payment workflow. 
In this workflow, the bank sends a new transaction to Woovi's backend. 
Inside Woovi's backend, we have the `transactionSync` code that processes the new transaction and saves it.
`transactionSync` is idempotent, to avoid duplicating transactions when a webhook is triggered twice.
It also updates the status of existing transactions if needed. It needs to handle different types of transactions, like payments, refunds, or withdraws.

## What is a Webhook/Postback URL

A Webhook/Postback URL is an HTTP endpoint that receives a new request when a new event happens.

## Transaction Sync without Event Driven
![Transaction Sync without Event Driven](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euaqlcycv7ebfev8sz3m.png)

If we don't follow an event driven approach inside `transactionSync` code, for each event we'd have to call the responsible function inside `transactionSync`.
When a `new payment` happens, we can call `newPayment` function. When a `refund is confirmed`. Then same happens for withdrawal.

Here is an analysis of what happens when we use this approach:

- If `newPayment` is slow, it will slow down `transactionSync`
- If `newPayment` breaks, it will break `transactionSync`
- To code `newPayment` you need to understand how `transactionSync` works, more cognitive load
- To test `newPayment`, you need to test `transactionSync` together, as a consequence you have a more complex test with more complex fixtures and test scenarios.
- To refactor `newPayment`, you could break `transactionSync`, these codes are highly coupled.
- We can't easily just reprocess `newPayment` without reprocessing the whole `transactionSync`

## Transaction Sync with Event Driven

![Transaction Sync with Event Driven](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h7fey75uuv5iwpxbfqi7.png)

In this approach, instead of calling directly the function to process the event. The `transactionSync` will only emit these events that will be processed by another function, job or service.

Here is an analysis of what happens when we use this approach :

- If `newPayment` is slow, it won't slow down `transactionSync`
- If `newPayment` breaks, it won't break `transactionSync`
- To code `newPayment` you don't need to understand how `transactionSync` works, fewer cognitive load
- To test `newPayment`, you do need to test `transactionSync` together, as a consequence you have simpler test scenarios with simpler fixtures.
- To refactor `newPayment`, you won't break `transactionSync`, these codes are highly decoupled.
- We can easily reprocess `newPayment` without reprocessing the whole `transactionSync`

## Event Driven in JavaScript
At Woovi we use [bull](https://github.com/OptimalBits/bull) for distributed jobs and messages using Redis. If you are starting a fresh codebase, or moving to event driven approach, we recommend to use [bullmq](https://github.com/taskforcesh/bullmq) which is a modern version of bull.

## Drawbacks
One drawback of this approach is that you need to have a queue system that will manage your events, and call your distributed jobs to process them.

## To sum it up
Following an event driven approach even without using microservices can bring a lot of benefits to your codebase. It makes it clear which events are important for your product.

It decouples code. Furthermore, it makes it easy to retry processing events. 

Finally, it makes refactoring easier; tests become simpler, and removing the temporal coupling of some code becomes possible

------------------------------------------------------------
If you wanna work with us, we are [hiring!](https://gist.github.com/sibelius/fe9bb57a2a00672459fa616523507f73)