I use Hyvor Talk - https://talk.hyvor.com - for ad-free and privacy respecting commenting on my blog. I really wanted something that I can just use as a service, not host anything myself. But it's quite expensive.
If I where to ditch it to save the money, I'd look into integrating Mastodon into the page, I saw somewhere that they used Mastodon as their comment system (it's basically a thread on Mastodon that is embedded in the blog page).
I'm sure rv is great, but am I the only one who needs one such tool not only for Ruby, but also Python, JavaScript, and Java, at least, and finds it weird to run 4+ of those?
The only thing I know about “good system design” is that it doesn’t exist in the abstract. Asking whether an architecture is good or bad is the wrong question. The real question is: Is it fit for purpose? Does it help you achieve what you actually need to achieve?
I could nitpick individual points in the article, but that misses the bigger issue: the premise is off.
Don’t chase generic advice about good or bad design. First understand your requirements, then design a system that meets them.
Wow, thank you so much, that's flattering. And motivating - I shall start blogging again this month, and try to stick to a monthly cadence. Make sure to subscribe to the RSS feed or follow me on Bluesky or Mastodon, to get notified for new posts :)
I looked and Flix a while ago and found it really interesting - so much so that I wrote an article "Flix for Java Programmers" about it. Might actually be a bit outdated by now.. need to look at Flix's recent development again.
In the Unison language, code is stored in a database, with a hash code of its content as the key. Quoting https://www.unison-lang.org :
A new approach to Storing code. Other tools try to recover structure from text; Unison stores code in a database. This eliminates builds, provides for instant nonbreaking renames, type-based search, and lots more.
> Yes, sort of, but mostly no. Events do not "trigger" anything. The recipient of an event may perform an action in response to the event, but events cannot know how they will be used or by whom.
I don't see the difference. Maybe it's a language thing. But I'd say if a recipient receives an event and perfoms an action as consequence, it's fair to say the event triggered the action. The fact that the event triggers something doesn't mean the event or the publisher must know at runtime what's being triggered.
Regarding your suggestions, I think your proving my point. Of course the whole "there are two types of.." is a generalization, but given that, you seem to fall in the first category, the one I called "DDD engineer/architect".
My response to the first three would be: Why? I know some literature suggests this. I've applied this pattern in the past. And I wrote "This is totally legitimate and will work.". But we also need to ask ourselves: What's the actual value? Why does the kind of event / the business reason have to be encoded as the name/type of the event? Honest question. Doesn't having it in the event payload carry the same information, just in a different place?
I don't want to be following what might be seen as "best practices" just for the sake of it, without understanding why.
I know of a few systems that started of with domain events that were named & typed "properly" according to the business event. And after a while, the need for wide events carrying the full state of the source entity arose. If you look at talks and articles from other EDA practioners (e.g. the ones on https://github.com/lutzh/awesome-event-driven-architecture#r...), you'll see that's not uncommon.
This regularly leads to having to provide the wide events in addition to the "short" events. This is extra effort and has its own drawbacks. I just want to save the readers the extra work.
Your categorization makes total sense and fits well with what I called the "spectrum". I only mentioned the "id-only" events to show what the one end of the spectrum would look like. What I call the "trigger" events would be what you call "delta" events. I should have written that more clearly.
Interestingly a few people advocated for id-only events as a response to the article. I have some issues with that pattern.. already thinking about a follow-up article to elaborate on that.
Thanks for your feedback. I realize I should have elaborated the example a bit more, it's too vague. So, as I wrote in some other reply as well, please don't over-interpret it. The point was only to say that in order to differentiate the events, we don't necessarily need distinct types (which would result in multiple schemas on a topic), but can instead encode it in one type/schema. Like mapping in ORM - instead of "table per subclass", you can use "table per class hierarchy".
Thanks for your feedback! Very good point on the naming. fwiw the idea was if you buy a cinema ticket, you are usually presented with some sort of seating plan and select the seat (basically putting them into the shopping cart). So SeatSelected would be the equivalent of "ItemAdded" to the shopping cart in an e-commerce application I guess.
Please don't over-interpret the example. There isn't even a definition what that booking aggregate contains. The point was really only to say that in order to differentiate the events, we don't necessarily need distinct types (which would result in multiple schemas on a topic), but can instead encode it in one type/schema. Think of it like mapping in ORM - instead of "table per subclass", you can use "table per class hierarchy".
Reg. the "technical" question: Kafka or any log-based message broker (or any message queue) would not prevent you from that. Any service can publish/send and/or subscribe/receive.
Regarding if it's a problem or a regular occurrence: No, really not. I have never seen this being a problem, I think that fear is unfounded.
Good catch! Indeed, without me realizing it, this trigger/data duality is pretty much what Event Message and Document Message are in "Enterprise Integration Patterns" (which is what the post you linked refers to). As it happens, in the book the authors also speak about "a combined document/event message", which is how me mostly use events in EDA today, I think.
> The triggering of the action is a direct consequence of the information an event contains. Whether or not an action is triggered should not be the responsibility of the event.
I agree, but still for different consumers events will have different consequences - in some consumers it'll trigger an action that is part of a higher-level process (and possibly further events), in others it'll only lead to data being updated.
> If you are writing events with the intention of having them invoke some specific actions, then you should prefer to invoke those things directly. You should be describing a space of things that have occurred, not commands to be carried out.
With this I don't agree. I think that's the core of event-driven architecture that events drive the process, i.e. will trigger certain actions. That's not contradicting them describing what has occurred, and doesn't make them commands.
> By default I would only include business keys in my event data. This gets you out of traffic on having to make the event serve as an aggregate view for many consumers. If you provide the keys of the affected items, each consumer can perform their own targeted lookups as needed. Making assumptions about what views each will need is where things get super nasty in my experience (i.e. modifying events every time you add consumers).
This is feedback I got multiple times, the "notification plus callback" seems to be a popular pattern. It has its own problems though, both conceptual (event representing an immutable set of facts) and technical (high volume of events). I think digging into the pros and cons of that pattern will be one of my next blog posts! Stay tuned!
Article observing that events in event-driven architecture are both triggers of actions and carriers of data, and that these roles may conflict in the event design. Submitted by author.
When speaking about event-driven architecture in the past, people have told me it’s not for them because they build web applications and/or REST APIs. That made me think of a phrase from functional programming (functional core, imperative shell) and I wrote a short blog post about how there’s still value in being event-driven.
100 years ago Josef Hartwig designed a chess set for Bauhaus with the same principle: "the shape of each piece reflects how it moves: pawns and rooks move in straight lines and are represented as rectangular prisms, the bishops feature diagonal lines, the king has both straight and diagonal elements, and the knights are L-shaped"
See https://en.wikipedia.org/wiki/Josef_Hartwig#Chess_sets
Thanks for your feedback! Delayed e-mail can have of course have many other reasons than the service supposed to send it being down. But let's go with your example. Let's say you have a LoginService, and a MessagingService, and if you request a password reset, the LoginService sends a ResetRequested event. Now if the MessagingService is down, you'd still get told to check your inbox, although the e-mail hasn't even been sent. That's a bad user experience. Agreed.
Your suggested solution is to make the communication between LoginService and MessagingService not event driven. So if the MessagingService is down, you can "hard error". But how much better is the experience then, really? As a user, you request the reset, and after a few seconds (you're already annoyed and checking if your internet connection is down), you get an error message that you can't reset your password right now. I'd argue that option is equally unacceptable.
What you need to do, is to make the MessagingService better. In an event driven system, each participating service makes a promise. The MessagingService must give service level guarantees, it must be built and scaled to be able to process all the events it's listening to. If it has an error, not you should get the error message - you are the last person able to do something about it - but someone who fixes it. If you want a better user experience, don't build unreliable services and then apologize for the inconvenience. Built better (more reliable, more scalable) software. In the end, that's what event-driven architecture is about.
If I where to ditch it to save the money, I'd look into integrating Mastodon into the page, I saw somewhere that they used Mastodon as their comment system (it's basically a thread on Mastodon that is embedded in the blog page).