36 ms·
Anti-patterns in event-driven architecture
- gnat 2y agohttps://web.archive.org/web/20240608190815/https://codeopinion.com/beware-anti-patterns-in-event-driven-architecture/ https://web.archive.org/web/20240608190815/https://codeopini...
- candiddevmike 2y agoCan someone share some long term event driven success stories? Almost everything you see online is written by consultants or brand new, greenfield implementations, curious how long these systems last.
- throwawaymaths 2y agoDoes canbus count?
- cjk2 2y agoNo. We have a complete fucking disaster on our hands.
- macintux 2y agoHow old of a system? Do you feel it’s the implementation, the design, or the concept itself that went wrong? Is your system a good fit? (No stake in this one way or another, just curious.)
- cjk2 2y agoLess than 5 years. Vanity project. Built and maintained by astronaut architects. Entirely unnecessary. Poorly implemented down to the level of wire contracts being inconsistent. Overheads are insane both from engineering and operational POV.
- moandcompany 2y agoResume driven development never goes out of style
- analognoise 2y agoHail, RDD, my favorite development style.
- cjk2 2y agoI call this one FDD: Fuckwit Driven Development. Because if it was resume-driven I'd expect it to be something that they would want to put on their resume. But this is unmentionable.
- moandcompany 2y agoThere's sayings along the lines of "Victory/success has a thousand fathers, but defeat/failure is an orphan." Chances are that system, and its outcomes are described very differently on a resume
- OccamsMirror 2y agoAs long as the list of technologies used is impressive sounding you're on to a winner.
- turkey99 2y agoYes, it’s a great tool for integration. We have a product suite and it’s our chosen way to connect products.
- blowski 2y agoI was the lead developer on one for an insurance company a few years back, and it’s still in active use. Insurance is a heavily regulated domain, where an audit trail is more important than performance. There was a natural pattern for it to follow, as we were mapping a stable industry standard. I also tried doing it in a property setting, where profit margins were tight. The effort needed wasn’t worth the cost, and clients didn’t really care about the value proposition anyway. We pretty much replaced the whole layer with a more traditional crud system.
- chenster 2y agoWhat did you mean traditional crud as oppose to event-driven arch? How is it relevant to the subject in dicussion?
- blowski 2y agoEvent-driven: At runtime, the client tells the system what has happened, the system stores the event and is configured in advance for how to react to it. CRUD: Imperative. Client tells us to create/update a specific entity with some data.
- devdude1337 2y agoWhen I did game dev I often went for an even driven approach or messaging based systems combined with oop and state machines to prevent eventual consistency locally. It works great in that domain, albeit not being the most performant solution. In web or business systems it works well for some(!) parts. You just shouldn’t do everything that way - but often people get too exited about a solution and then they tend to overdo it and apply it everywhere, even when not appropriate. Always chose the golden middle path and apply patterns where they fit well.
- Salgat 2y agohttps://www.eventstore.com/case-studies/insureon https://www.eventstore.com/case-studies/insureon I can attest to this case study being 100% true. Our platform has been using EventStore as our primary database for 9 years going strong, and I'm still very happy with it. The key thing is that it needs to be done right from the very beginning; you can't do major architecture reworks later on and you need an architect who really knows what they're doing. Also, you can't half-ass it; event sourcing, CQRS, etc all had to embraced the entire time, no shortcuts. I will say though, the biggest downside is that scaling is difficult since you can't always rely on snapshots of data, sometimes you need to event source the entire model and that can get data heavy. If you're standing up a new projector, you could be going through tens of millions of events before it is caught up which requires planning. It is incredible though being able to have every single state change ever made on the platform available, the data guys love it and it makes troubleshooting way easier since there's no secrets on what happened. The biggest con is that most people don't really understand it intuitively, since it's a very different way of doing things, which is why so many companies end up fucking it up.
- Spivak 2y agoAm I dumb or is this basically the binlog of your database but without the tooling to let you do efficient querying? Like I get the "message bus" architecture when you have a bunch of services emitting events and consumers for differing purposes but I don't think I would feel comfortable using it for state tracking. Especially when it seems really hard to enforce a schema / do migrations. CQRS also makes sense for this but only when it functions as a WAL and isn't meant to be stored forever but persisted by everyone who's interested in it and then eventually discarded.
- Salgat 2y agoFor events you include a version. When you're only adding properties to the event or removing properties (assuming you defensively write the projectors), no need for a new version, but if you're creating a breaking change in event schema, you'd increment the version for the event and update your projector to handle each version. It's simpler than you'd think.
- vmaurin 2y agoI have been doing this kind of stuff both in ad tech and trust & safety industry, mainly to handle scalability. Something that looks like "Event-carried state transfer" here https://martinfowler.com/articles/201701-event-driven.html https://martinfowler.com/articles/201701-event-driven.html These system are working fine, but maybe a common ground : * very few services * the main throughput is "fact" events (so something that did happen) * what you get as "Event carried state transfer" is basically the configuration. One service own it, with a classical DB and a UI, but then expose configuration to all the system with this kind of event (and all the consumers consume these read only) * usually you have to deal with eventual consistency a lot in this kind of setup (so it scales well, but there is a tradeoff)
- jgraettinger1 2y agoPostgreSQL. The WAL is an event log, and when you squint at its internal architecture, you’ll see plenty of overlap with distributed event sourcing.
- marcosdumay 2y agoAlmost every modern software system. Anything running over the Web is event driven.
- lolive 2y ago99.99% of the data we consume on the Web comes out of databases [call it Transactional-SQL-xxx or ColumnBased-yyy or Elastic-SaaS-zzz].
- marcosdumay 2y agoWell, yes. Databases are event driven themselves. As is any web application, because the web (at least without sockets) is constrained into communicating events only. Also, most local GUI applications, because people just like events better for it.
- mrkeen 2y agoLikewise with git. There's the "top-level events" that you see (commits). But even when you're doing 'unsafe' operations, you're working with the lower-level reflog events.
- lmm 2y agoRight. The hard part is already done. Which makes it infuriating that it's all "internal". Every serious RDBMS already contains an implementation of an event-sourcing system, but you're not allowed to actually use it.
- ninkendo 2y agoChiming in with another “no” here. We adopted a message bus/event-driven architecture when moving a very popular piece of software from the cloud, to directly on the user’s device… it was a disaster IMO. The core orchestration of the system was done via events on the bus, and nobody had any idea what was happening when a bug occurred. People would pass bugs around, “my code did the right thing given the event it got”, “well, my code did the right thing too”, and nobody understood the full picture because everyone was stuck in their own silo. Event driven architectures encourage this: events decouple systems such that you don’t know or care what happens when you emit a message, until one day it’s emitted with slightly different timing or ordering or different semantics, and things are broken and nobody knows why. The worst part is that software is basically “take user input, do process A on it, then do process B on that, then do process C on that.” It could have so easily been a simple imperative function that called C(B(A(input))), but instead we made events for “inputWasEmitted”, “Aoutput”, “Boutput”, etc. What happens when system C needs one more piece of metadata about the user input? 3 PR’s into 3 repos to plumb the information around. Coordinating the release of 3 libraries. All around just awful to work with. Oh and this is a very high profile piece of software with a user base in the 9 figure range. (Wild tangent: holy shit is hard to get iOS to accept “do process” in a sentence. I edited that paragraph at least 30 times, no joke, trying every trick I could to stop it correcting it to “due process”. I almost gave up. I used to defend autocorrect but holy shit that was a nightmare.)
- tadfisher 2y agoI think the true term for this phenomenon is "decoherence" rather than "decoupling". Your components are still as coupled as they ever were, but the coupling has moved from compile-time (e.g. function calls) to runtime. The component that "handles events" decoheres the entire system because it's now responsible for the entire messaging layer between components, rather than the individual components being responsible for their slice of the system.
- jesse__ 2y agoThat's a great name for that property. I've always cringed when people say 'something something decoupling' because most of the time the end result is actually just as coupled, but ends up indirected or something. Now I have a more specific word for it, thanks!!
- mrkeen 2y agoWe've had mistakes that we've been able to course-correct from. Our users are small-businesses with organisation numbers, and we mostly think of them as unique. But they strictly aren't, so we 'overwrote' some companies with other companies. Once we detected and fixed the bug, we just replayed the events with the fixed code, and we hadn't lost any data.
- simonbw 2y agoIt's been an incredibly useful pattern for me in game development. I have a hard time imagining making a game with any level of complexity without it. You can definitely go overboard with it, but I have a hard time even imagining how some systems like collision detection/a physics engine could even work without it.
- ClimaxGravely 2y agoThat's generally been my experience as well. However I've seen some frameworks where you can do collision imperatively. For example if (sprite.collide(tilemap)) {do something} These are generally on smaller less taxing frameworks (in this case I'm referring to haxeflixel) but they do exist!
- cweld510 2y agoI work on an event-based architecture that I think is successful, but that’s because our core primitives are event-based, so there is no impedance mismatch in the way that there can be if you migrate from a request-response architecture to an evented one. Specifically, we aren’t trying to deal with databases and HTTP (both of which are largely synchronous primitives). Instead, I work on a platform for somewhat arbitrary code execution; and the code we are executing depends on our code rather than vice versa. In general, the code we execute on the platform can run for an indeterminate amount of time, and it generally has control and calls back into our code rather than our code calling into it. So our control flow is naturally callback-based rather than request/response; as a result, our system is fundamentally event-based.
- tkiolp4 2y agoNo. The usual pains are: - Producer and consumer are decoupled. That’s a good thing m right? Good luck finding the consumer when you need to modify the producer (the payload). People usually don’t document these things - Let’s use SNS/SQS because why not. Good luck reproducing producers and consumers locally in your machine. Third party infra in local env is usually an afterthought - Observability. Of rather the lack of it. It’s never out of the box, and so usually nobody cares about it until an incident happens
- throwaway24x7 2y ago> Good luck finding the consumer when you need to modify the producer It sounds like your alternative is a producer that updates consumers using HTTP calls. That pushes a lot of complexity to the producer and the team that has to sync up with all of the other teams involved. > Let’s use SNS/SQS because why not. Good luck reproducing producers and consumers locally in your machine At work we pull localstack from a shared repo and run it in the background. I almost forget that it's there until I need to "git pull" if another team has added a new queue that my service is interested in. Just like using curl to call your HTTP endpoints, you can simply just send a message to localstack with the standard aws cli https://github.com/localstack/localstack https://github.com/localstack/localstack > Observability. Of rather the lack of it. It’s never out of the box, and so usually nobody cares about it until an incident happens I think it depends on what type of framework you use. At work we use a trace-id field in the header when making HTTP calls or sending a message (sqs) which is propagated automatically downstream. This enables us to easily search logs and see the flow between systems. This was just configured once and is added automatically for all HTTP requests and messages that the service produces. We have a shared dependency that all services use that handles logging, monitoring and other "plumbing". Most of it comes out of the box from Spring, and the dependency just needs to configure it. The code imports a generic sns/http/jdbc producer and don't have to think about it
- mrkeen 2y ago> Good luck finding the consumer when you need to modify the producer (the payload) I just grep for the event's class name.
- 2y ago
- bob1029 2y agoI saw it done well in manufacturing. I think it works well when it's the only thing that can work.
- richardw 2y agoBanking, 7 ish years. Worked well for us in general. When I start needing increased confidence and truth the effort level goes way up but can be done. Definitely still worth it, has given us some solid benefits. When I say increased, I mean we want the best answer but there are some answers the bank can’t know. If someone has transferred money into your account from another bank but we don’t know that yet, optimising for absolute correctness is pointless because the vast majority of wrong answers are baked in to the process. We can send you a message and you might read it a day later. Unless we delete the message from your phone, we can’t guarantee the message you read is fully consistent with our internal state. Frankly our system is much better than the batch driven junk that is out of sync a second after it has executed. “Hey you have a reward.” “No I used it 2 hours ago you clowns.” Note this isn’t cope. In some cases we started fully sync but relaxed it where there are tradeoffs that gave us better outcomes and we weren’t giving anything material up.
- lanstin 2y agoOr worse “hey you have a reward” but it doesn’t show up in the UI for three minutes. Twitter used to do this to me all the time.
- richardw 2y agoEventually consistent means just that, I guess. But I’m sure their reasoning was a lot more sophisticated or impacted by scale than most. Cool problem.
- tlarkworthy 2y agoWebhooks? Slack automation? GitHub actions?
- lanstin 2y agoIt is a very convenient way to move higher latency operations from the realtime path to a near real time path. E.g. you want to send an email when a payment is authorized, you don’t want to wait for the whole SMTP transaction so you just post an even and reply back to the user. Also settlements of captured autos, 5st sort of thing. Even saving some user pref, start the task, reply back to user. and if it fails async send a failure msg.
- nitwit005 2y agoI've seen successful, but flawed usage. Every use I've seen sent events after database transactions, with the event not part of the transaction. This means you can get both dropped events, and out of order events. My current company has analytics driven by a system like that. I'm sure there's some corrupted data as a result. The main issue being people just don't know how to build and test distributed systems.
- mrkeen 2y agoI had an interview where I was asked how I would guarantee that an event happened in addition to a database update (transactionally). It sounded kind of impossible, I said as much, and then proposed a different approach. The interviewer persisted and claimed that it could be done with 'the outbox pattern'. I disagreed and ended the interview there. Later when I was chatting about it with a former colleague, he said "Oh, they solved the two generals problem?" > Every use I've seen sent events after database transactions, with the event not part of the transaction. Maybe this is what they were doing.
- lastofus 2y agoI don't quite see what the outbox pattern has to do with the two generals problem. The point of the outbox pattern is that a durable record of the need to send an event is stored in the DB as part of the DB txn, taking advantage of ACID guarantees. Once you have that durable record in your DB, you can essentially treat your DB as a queue (there's lot of great articles on how to do this with Postgres for instance) for some worker processes to later process the queue records, and send the events. The worker processes in turn can decide if they want to attempt at least once, or at most once delivery of the message. Of course if you choose the later, then maybe your event is never sent, and perhaps that was the point you were trying to make to the interviewer. They key takeaway though is that you are no longer reliant on the original process that stores the DB txn to also send the event, which can fail for any number of reasons, and may have no path to recovery. In other words, at least once delivery is now an option on the table.
- 2y ago
- TeeMassive 2y agoI've worked in an embedded Linux system that was a greenfield project. We needed a library that was written in a certain language, but we also wanted Python for the rest because getting the logic right with a client that changed his mind often was top priority and the data crunching was minimal. So we ended up using protobufs over a local MQTT broker and adopted a macro-service architecture. This suited the project very well because it had a handful of obvious distinct parts and we took full advantage of Conway's law by making each devs work the part where their strengths and skills were maximized. We made a few mistakes along the way but learned from them. Most of them relating to inter-service asynchronous programming. This article put words on concepts we learned through trial and errors, especially queries disguised as events.
- Osiris 2y agoThe project I'm working on is about 13 years old (ruby on rails) with over 260 engineers and the product has a very robust event driven system that is at the core of a lot of important features.
- swistak35 2y agoOut of curiosity, what is the system? Is this based on Rails Event Store, or something else (custom?)?
- rswail 2y agoWrote a public transport ticketing system that processes 100-200K+ trips/day with sub-second push of notification to mobiles of trip/payments. Event driven and CQRS "entities" made logic and processing much easier to create/test/debug. Primary issues: 1. Making sure you focus on the "Nouns" (entities) not the "Verbs". 2. Kafka requiring polling for consumers sucks if you want to "scale to zero". 3. Sharding of event consumers can be complicated. 4. People have trouble understanding the concepts and keep wanting to write "ProcessX" type functions instead of state machines and event handlers. 5. Retry/replay is complicated, better to reverse/replay. Dealing with side effects in replay is also complicated (does a replay generate the output events which trigger state changes in other entities?) Been running now for 6 years, minimal downtime except for maintenance/upgrades. In the process of introducing major new entity and associated changes, most of the system unaffected due to the decoupling.
- chenster 2y agoCan you elaborate #1 Nouns over Vers?
- rswail 2y agoA lot of people focus on the process instead of the participating entities. The focus when designing the system should be on the entities (Customer, Payment, Bill, Order, Inventory) instead of the processes (ordering, billing, fulfillment). I summarize that by saying "Nouns over Verbs". The state of each of the entities is affected by the processes, but the effect happens from changes in other entities, Customers place an Order. Customers get a Bill for the Order, Customers make a Payment, etc. The states of each of these entities is independent of the others and reacts/changes only as a result of two things, either an external "Command", or an "Event". Commands are events that occur outside of the system boundary, usually visible as part of an API (if RESTful) that uses POST/PUT/DELETE or they are imperatives from one entity to another. Commands are imperatives, Place Order, Pay Bill, Fulfill Order, etc. Events are records of occurrences in the system, expressed in the past tense and are immutable. Order Placed, Bill Paid, Order Fulfilled. Customers place an Order by POSTing to /orders (or potentially /customers/uuid/orders). Events are generated from entities inside the system. (Order being placed generates an order_placed event). The difference is that by focussing on the entities, and their state, independent of other entities, the entities can be created, tested, installed, evolved independently of other entities in the system. The thinking about them is simplified and focussed, they are naturally decoupled because they can only find out about other entities by inquiring or affect other entities by generating a Command or an Event. Any events they generate are processed asynchronously and can have multiple consumers.
- thr0w 2y ago> Can someone share some long term event driven success stories? JavaScript
- jesse__ 2y agoI think we have very different definitions of success
- lz400 2y agoAFAIK almost every stock market order processing system is event driven, and they are all usually very old systems that have been successfully running for years. I've seen some implementation in investment banks, what you're usually told is that most exchanges and banks run similar architectures. The reason for this is partially that FIX, the protocol for electronic orders in markets is event based.
- liampulles 2y agoOur system is command driven, and works well, but it is because we explicitly have less rigorous demands on the messages and the messages don't cross team boundaries. My past experience also makes me wary of event driven systems.
- deleted 2y ago[deleted]
- skellington 2y ago[flagged]
- arwhatever 2y agoI often hear the argument in favor of event-driven architecture that you can work on one part of a system in isolation without having to consider the other parts, and then I get assigned some task which requires me to consider the entire system operation, now with events that are harder to trace than function calls would have been. Now when people argue “because decoupling,” I hear, “You don’t get as much notification that you just broke a downstream system.”
- moandcompany 2y agoIntegration tests?
- worik 2y ago...happen too late
- hobs 2y agoI think generally a lot of these types of problems were actually had by folks who grew out of single node systems and had a lot of interesting ideas to solve problems that were new in those domains, GIVEN they've already solved the stateful domain problems as well. When you've never grown out of a single node domain but you do event driven "because scaling" or whatever, you've shot yourself in the foot amazingly hard.
- The_Colonel 2y agoYes, events, async, eventual consistency, decoupling represent a difficult/complex solution for some hard problems encountered when scaling high. But people often forget there are trade-offs to everything and if you don't have these hard problems, you're giving yourself only headaches. My pet-peeve is "decoupling" - it's treated as holy with only benefits and no downsides. But it's actually again a level of complexity - unless you need it, tightly coupled code will be easier to write, read, debug etc.
- scubbo 2y agoAmen. Event-driven architecture makes it easier to bury your head in the sand, and harder to implement an actually-working feature.
- pudwallabee 2y agoI have seen Kafka pulled out by its hairs and replaced with request based architecture. Event driven architecture, to me is itself an antipattern. It seems like a replacement for batch processing. Replayable messages are AWESOME. Until you encounter the complexity for a system to actually replay them consistently. As far as the authors video, while there was some truth in there, it was a little thin, compared to the complexity of these architectures. I believe that even though Kafka acts the part of "dumb pipe", it doesnt stay dumb for long, and the n distributions of Kafka logs in your organization could be 1000x more expensive than a monolithic DB and a monolithic API to maintain. Yes it appears auditable but is it? The big argument for replayability is that unlike an API that falls over theres no data loss. If you work with Kafka long enough you’ll realize that data loss will become a problem you didnt think you had. You’ll have to hire people to “look into” data loss problems constantly with Kafka. Its just too much infrastructure to even care about. Theres also, something ergonomically wrong with event drive architecture. People dont like it. And it also turns people into robots who are “not responsible” for their product. Theres so much infrastructure to maintain that people just punt everything back to the “enterprise kafka team”. The whole point of microservices was to enable flexibility, smart services and dumb pipes, and effective CI/CD and devops. We are nearing the end of microservices adoption whether it be event or request driven. In mature organizations it seems to me that request driven is winning by a large margin over event driven. It may be counterintuitive, but the time to market of request driven architecture and cost to maintain is way way lower.
- smrtinsert 2y ago> and the n distributions of Kafka logs in your organization could be 1000x more expensive than a monolithic DB and a monolithic API to maintain Not to mention certain observability vendors bleeding you for all those logs you now need to keep an eye on it. Absolutely agreed on every point
- RHSman2 2y agoThe unseen critical part of the equation
- 2y ago
- astrea 2y ago[flagged]
- aejm 2y agoWhat are people’s thoughts on using event driven architecture in games? Specifically multiplayer games, and massively multiplayer games (MMOrpgs). Another comment mentions it was helpful, how specifically, were there any tradeoffs, do certain types of games work better?
- edd25 2y agoI have not worked on an MMO before, but recently I had the chance to try out my own custom event system on a small multiplayer game (Unity, PUN2). I had most issues with differentiating which events came from which client. Additionally, I had lots of issues differentiating which events were issued locally. In the end, the code ended up being quite messy. If I were to redo the game, I'd use direct method calls where possible with regular callbacks. Generally, I found that when using event systems you have to be really careful not to over-use it, even small/single player games. Its super hard to debug when everything is an event - if you go this route, you essentially end up in a situation where everything is "global" and can be reached from anywhere (might as well just go full singleton mode at that point). Additionally, I found it difficult having to deal with event handlers which raise other events, or worse, async events, as then it becomes really hard to ensure the correct order of invocations. If you plan to use an event system, my advice would be (in Unity): - Reference and raise events only on root Game Object scripts (e.g., have a root "Actor" script which subscribes/publishes events and communicates with its children via properties/C# events) - Never subscribe or publish events in regular "child" components - Use DI/service locator to fetch systems/global things and call them directly when possible from your "Actors"
- FridgeSeal 2y agoI’m starting to get a sad about event driven stuff. I’ve used it with a good degree of success in some data pipeline and spark stuff to have stuff automatically kick off, without heinous conditional orchestration logic. I also use evented stuff over channels in a lot of my rust code with great success. However, echoing the sentiments of some other comments: most articles about event driven stuff seem to be either marketing blogspam or “we tried it and it was awful”. To be honest I look at a lot of those blog posts and about half the time my thoughts are “no wonder that didn’t work out, that’s an insane design” but is that just “you’re-doing-it-wrong-cope”? Are there success stories out there that just aren’t being written? Is there just no success stories? Is the architecture less forgiving of poor design and this “higher bar of entry” torpedoes a number of projects? Is it more susceptible to “architecture astronauts” which dooms it? Is it actually decent, but requires a somewhat larger mindset-change than most people take to it, leading to half-baked implementations? I can’t help but feel the underlying design has some kernels of some really good ideas, but the volume of available evidence sort of suggests otherwise.
- rammy1234 2y agoMy 2 cents - There is no anti-pattern specific to event driven. It is essentially asynchronous nature. It means you start with understanding the business needs and SLA. Question often comes in my experience is "can they wait?" and what's the risk of dirty data or data fetched with delay ( worst case ). event driven is always about worst case scenario and will it work then.
- therealdrag0 2y agoThe main anti pattern is making the wrong choice; using async when sync fits better.
- worik 2y ago"Event driven architecture ". Mēh! There is no avoiding it when dealing with, erm, events. Events are things that happen that you cannot predict exactly when, where, and what. The user clicked the mouse The wind changed direction Using Events to signal state change from one part of a system to another is a bad idea. Use a function call. A rule of thumb is if the producer and the consu,er are in the same system then "Event Driven Architecture " is the anti pattern
- gardenhedge 2y agoWhat if one event should trigger many actions?
- oddevan 2y agoWent in thinking I would find out a few pitfalls for the event-driven app I'm writing... > Commands only have a single consumer. There must be a single consumer. That’s it. They do not use the publish-subscribe pattern. ...oops. Now the question is how much (more) time I want to spend on a(nother) rewrite.
- chermi 2y agoI always thought it would be an interesting exercise to build an event-based controls system. There's a lot triggering action X based on event A. And actions based on composite events. I never found anyone who had done it. Edit- I should say I never saw one in the wild, quick search found some academic projects https://scholar.google.com/scholar?q=event-driven+control+system&hl=en&as_sdt=0&as_vis=1&oi=scholart#d=gs_qabs&t=1717895148440&u=%23p%3D2KAKAhWCSPkJ https://scholar.google.com/scholar?q=event-driven+control+sy...
- YZF 2y agoI've worked in a large company where some variation of event driven architecture was used everywhere and treated as the word of G-d. Fairly successfully. Mostly in applications that ran on a single machine. I've ended up in a lot of arguments about this while we were building larger distributed systems because I've come from a more request/response oriented message passing architectures. I.e. more synchronous. What I've found is that the event driven architecture did tend to lead to less abstractions and more leaked internal details. This isn't fundamental (you can treat events like an API) but was related to some details in our implementation (something along the line of CDC). Another problem with distributed systems with persistent queues passing events is that if the consumer falls behind you start developing a lag. Yet another considerations is that the infrastructure to support this tends to have some performance penalties (e.g. going through Kafka with an event ends up being a lot more expensive than an RPC call). Overall it IMO makes for a lot of additional complexity which you may need in some cases, but if you don't then you shouldn't pay the cost. What I've come to realize is that in many ways those systems are equivalent. You can simulate one over the other. If you have an event based system you can send requests as events and then wait for the response event. If you have a request/response system you can simulate events over that. If we look at things like consensus protocols or distributed/persistent queues then obviously we would need some underlying resources (e.g. you might need a database behind your request/response model). So... Semantics. Don't know if others have a similar experience but when one system is mandated people will invent workarounds that end up looking like the other paradigm, which makes things worse. There are things that conceptually fit well with an event driven architecture and then there are things that fit well with a request/response model. I'm guessing most large scale complex distributed apps would be best supporting both models.
- lmm 2y ago> What I've found is that the event driven architecture did tend to lead to less abstractions and more leaked internal details. This isn't fundamental (you can treat events like an API) I'd put it the other way: event driven architecture makes it safer to expose more internal details for longer, and lets you push back the point where you really need to fully decouple your API. I see that as an advantage; an abstract API is a means not an end. > Another problem with distributed systems with persistent queues passing events is that if the consumer falls behind you start developing a lag. Isn't that what you want? Whatever your architecture, fundamentally when you can't keep up either you queue or you start dropping some inputs. > If you have a request/response system you can simulate events over that. How? I mean you can implement your own eventing layer on top of a request/response system, but that's going to give you all the problems of both. > If we look at things like consensus protocols or distributed/persistent queues then obviously we would need some underlying resources (e.g. you might need a database behind your request/response model). Huh? > Don't know if others have a similar experience but when one system is mandated people will invent workarounds that end up looking like the other paradigm, which makes things worse. I agree that building a request/response system on top of an event sourcing system gives you something worse than using a native request/response system. But that's not a good reason to abandon the mandate, because building a true event-sourcing system has real advantages, and most of those advantages disappear once you start mixing the two. What you do need is full buyin and support at every level rather than a mandate imposed on people who don't want to follow it, but that's true for every development choice.
- DotaFan 2y agoEvent-driven architecture should be implemented across complete system (client-be) or be used in a single feature, i.e. it needs to be all or bare minimum, else it's just an absolute mess.
- deleted 2y ago[deleted]
- liampulles 2y agoOur system at work is a command driven system. We don't use messages as a source of state, but really just as Async instructions. And we store them which can be useful for retrying, data fixes, and stats. I feel like a lot of teams out there can probably benefit from this simpler approach - it's probably what a lot of people are doing unwittingly.
- onetimeuse92304 2y agoNot specifically about event-driven, but the most damaging anti-pattern I would say is microservices. In pretty much all projects I worked with in recent years, people chop up the functionality into small separate services and have the events be serialised, sent over the network and deserialised on the other side. This typically causes enormous waste of efficiency and consequently causes applications to be much more complex than they need to be. I have many times worked with apps which occupied huge server farms when in reality the business logic would be fine to run on a single node if just structured correctly. Add to that the amount of technology developers need to learn when they join the project or the amount of complexity they have to grasp to be able to be productive. Or the overhead of introducing a change to a complex project. And the funniest of all, people spending significant portion of the project resources trying to improve the performance of a collection of slow nanoservices without ever realising that the main culprit is that the event processing spends 99.9% of the time being serialised, deserialised, in various buffers or somewhere in transit which could be easily avoided if the communication was a simple function call. Now, I am not saying microservices is a useless pattern. But it is so abused that it might just as well be. I think most projects would be happier if the people simply never heard about the concept of microservices and instead spent some time trying to figure how to build a correctly modularised monolithic application first, before they needed to find something more complex.
- roncesvalles 2y agoAlso, the single most nonsensical reason that people give for doing microservices is that "it allows you to scale parts of the application separately". Why the fuck do you need to do that? Do you scale every API endpoint separately based on the load that it gets? No, of course not. You scale until the hot parts have manageable load and the cold parts will just tag along at no cost. The only time this argument makes sense is if one part is a stateless application and the other part is a database or cache cluster. Microservices make sense when there are very strong organizational boundaries between the parts (you'd have to reinterview to move from one team to the other), or if there are technical reasons why two parts of the code cannot share the same runtime environment (such as being written in different languages), and a few other less common reasons.