HN user

lutzh

175 karma

[ my public key: https://keybase.io/lutzh; my proof: https://keybase.io/lutzh/sigs/OtKcaPZdz7biBYFto71UtRsmoBU1XBRQXflI5HYHzeI ]

Posts9
Comments22
View on HN

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?

I put my hope in mise-en-place - https://mise.jdx.dev

What do people think? One tool per language, or one to rule them all?

Good system design 11 months ago

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 :)

Thank you for your kind words!

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.

Thanks for your feedback Gunnar, I appreciate it!

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.

Thanks for your feedback, I appreciate it!

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!

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.

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.

Thanks for your feedback! Of course we all have our "bubble", we make our own experiences, and if we share our learnings, they might not always match what other people have experienced. In practice, I feel a statement like "any event could trigger any bit of code in the entire system" a bit exaggerated. When I think of event driven systems, I think of business applications, where a large number of microservices interoperates mainly over Kafka. So the services that are triggered by an event are already limited to those subscribing to a specific Kafka topic. Of course if you follow the chain of subsequent events (i.e. service A emits an event, with leads to service B emitting events, with lead to service C and D emitting events..), you might not be aware for every event what'll happen way downstream. But you can turn this into an architectural strength, as it leads to better decoupling and separation of concerns.

On another note, as you describe GOTO as a double sided sword, now I really wonder what the positive side of GOTO is..

Agreed! For the user facing bit, I consider REST or some other form of HTTP-based a given. As a (human) user, I want to base my communication on commands and queries, and do want responses! But the services that generate those responses should not have runtime dependencies on other services. Those backend services should interoperate in an event-driven way.