Event-based architecture and why it’s essential for startups
Now, what do I mean by event based architecture? The easiest analogy for most developers these days is the publish-subscribe model.
You perform a tiny bit of work in an API (say creating a record). Consequently, you need to send an email to the user, and invalidate the cache for the user that created the record. The way a lot of junior developers will engineer this, is something similar to below:
This looks pretty simple from the offset, doesn’t it? You’ve made your code nice and clean by abstracting the emailing and cache invalidation into separate functions so you can think about this logic in a separate module.
But — what happens when you need to send a notification to your company’s Slack? And then you need to run some logic to check if the user has created more than 10 records, and if so, send them a separate email to congratulate them. And then you want to run a test to send the user an SMS message as well as an email?
This is obviously a convoluted example, but it’s easily possible within your own business as requirements change quickly. What’s better, is if you structure your application like this:
This kind of architecture plays incredibly well to splitting out your application into micro-services at a later date too. We recently ripped all of our notifications and fraud detection out of our old API into separate services, and we could just pick up each module (each of which was just a set of message handlers) from the monolith, wrap it in a tiny bit of code to run it as a daemon, and then we had nice separate services.
If you’re struggling to get your head around the example above — here’s a (massively cut down for obvious reasons) example within our application — when a customer creates a booking.
booking.create (event published with the booking details to RabbitMQ) ~ sms.send.booking.create (send the therapist a notification SMS) ~ push.send.booking.create (send the therapist a notification SMS) ~ email.receipt.booking.create (send the customer a receipt email) ~ hipchat.notify.booking.create (customer services receive a notification) ~ fraud.check.booking.create (our automated fraud system back checker) ~ gosquared.booking.create (tracks the data into gosquared) ~ stats.user.booking.create (updates stats about the user) ~ many many more….
Hopefully this has given you an insight into the freedom you get when you can treat each async/background task as a completely separate part of the application. If you have any questions, feel free to leave a comment!