Messaging Patterns for Modern Software Solutions | Irina Dominte (Scurtu) | .NET Day 2026
Read full transcript 32 segments
-
Irina, thank you for Irina, thank you for joining us. joining us. joining us. How are you? How are you? How are you? Greetings. I'm so happy to Greetings. I'm so happy to Greetings. I'm so happy to be here. After a be here. After a break of several years. Thank you for break of several years. Thank you for inviting me. inviting me. inviting me. Yes, we were just saying, Yes, we were just saying, Yes, we were just saying, yes, exactly. It's very yes, exactly. It's very yes, exactly. It's very nice to see you. nice to see you. nice to see you. We were talking before we We were talking before we We were talking before we started, started, started, trying trying trying to remember how many .NET to remember how many .NET to remember how many .NET Days we've done over the Days we've done over the Days we've done over the years, and we lost count years, and we lost count . This is just terrible. We'll have to . This is just terrible. We'll have to check. However, uh ... ... ... part of many of part of many of part of many of them. So, them. So, them. So, welcome back. welcome back. welcome back. A lot of time has passed. I have A lot of time has passed. I have A lot of time has passed. I have n't seen you for a long time. n't seen you for a long time. n't seen you for a long time. Yes. Yes, I think Yes. Yes, I think Yes. Yes, I think this year's this year's this year's JetBrains event is the first and JetBrains event is the first and JetBrains event is the first and only event. I only event. I only event. I took a break from took a break from took a break from speaking and speaking and speaking and focused on focused on focused on other things, like other things, like other things, like running the newsletter and... running the newsletter and... running the newsletter and... Well, thanks for Well, thanks for Well, thanks for joining us. joining us. joining us. Well, thank you again for Well, thank you again for Well, thank you again for inviting me. inviting me. inviting me. Yes, it is a great honor for us Yes, it is a great honor for us Yes, it is a great honor for us . That's good. Okay . That's good. Okay , uh, if you're ready, , uh, if you're ready, , uh, if you're ready, I think we'll share I think we'll share I think we'll share your slides. Yes, your slides. Yes, your slides. Yes, we see them, and if we see them, and if we see them, and if you are ready, please you are ready, please you are ready, please begin. begin.
-
begin. Of course. Thank you very much. Of course. Thank you very much. So today I'm going to So today I'm going to try to quickly try to quickly try to quickly introduce you to introduce you to introduce you to three very three very three very important patterns, important patterns, important patterns, or at least what or at least what or at least what I consider to be very I consider to be very I consider to be very important patterns important patterns important patterns in messaging systems in messaging systems in messaging systems . A . A little about myself. I am from little about myself. I am from Romania. I am a software architect Romania. I am a software architect at Particular. at Particular. I blog and I blog and I blog and recently started a recently started a recently started a newsletter called newsletter called newsletter called Eventually Consistent. The pun Eventually Consistent. The pun Eventually Consistent. The pun is intentional, because I've is intentional, because I've is intentional, because I've always had a always had a always had a subscribe button on my blog, but subscribe button on my blog, but subscribe button on my blog, but I couldn't seem to I couldn't seem to I couldn't seem to set up a set up a set up a workflow for workflow for workflow for sending emails to sending emails to sending emails to people. So I told people. So I told people. So I told myself I would start. myself I would start. I think I've I think I've been running this mailing list for a month now, and been running this mailing list for a month now, and been running this mailing list for a month now, and the topics are usually the topics are usually the topics are usually about about about messaging or messaging or messaging or distributed systems. distributed systems. So let's So let's dive into the story a little, dive into the story a little, dive into the story a little, okay? We all place okay? We all place okay? We all place orders. We orders. We orders. We order food, order food, order food, we order, I don't know, we order, I don't know, we order, I don't know, things online, right? And we're things online, right? And we're things online, right? And we're waiting for the package, waiting for the package, waiting for the package, right? So, there is a right? So, there is a right? So, there is a connection between us and the connection between us and the connection between us and the various systems, and various systems, and various systems, and we expect we expect we expect delivery to be on time delivery to be on time delivery to be on time when we need what we when we need what we when we need what we ordered. And ordered. And ordered. And historically, if we're historically, if we're historically, if we're talking about talking about talking about messaging, it's messaging, it's messaging, it's been used been used been used since ancient times.
-
since ancient times. We We used to use carrier used to use carrier used to use carrier pigeons to pigeons to pigeons to send send send messages, then messages, then messages, then horse-drawn carriages, and so on. horse-drawn carriages, and so on. So a form of So a form of asynchronous asynchronous asynchronous communication has always communication has always communication has always been a part of our been a part of our been a part of our lives. But what hasn't lives. But what hasn't lives. But what hasn't been a part of our been a part of our been a part of our lives is lives is lives is asynchronous asynchronous asynchronous messaging as such messaging as such messaging as such in distributed in distributed in distributed systems. We have always systems. We have always relied on HTTP to some extent in our relied on HTTP to some extent in our work, but there is one work, but there is one work, but there is one caveat. With HTTP, we had no caveat. With HTTP, we had no delivery guarantees. We made delivery guarantees. We made a request, received a request, received a request, received a response if we were a response if we were a response if we were lucky, but that was it. There lucky, but that was it. There lucky, but that was it. There was nothing in the protocol was nothing in the protocol was nothing in the protocol that that that guaranteed us that guaranteed us that guaranteed us that the request would actually be the request would actually be the request would actually be received on the received on the received on the server side. Let's server side. Let's server side. Let's think think think about this for a moment. When we about this for a moment. When we about this for a moment. When we make a request via HTTP make a request via HTTP , we hope that , we hope that , we hope that the server is up and running, the server is up and running, the server is up and running, right? But if the right? But if the right? But if the server server server crashes, the contents of our crashes, the contents of our crashes, the contents of our request will be lost.
-
request will be lost. There is no way for the server to know about this and to know about this and repeat our request. repeat our request. repeat our request. So everything gets lost in So everything gets lost in So everything gets lost in transmission, right? transmission, right? That's why I made it That's why I made it my personal my personal my personal mission to talk mission to talk mission to talk about asynchronous about asynchronous about asynchronous messaging messaging , because I , because I learned the hard way many years ago how learned the hard way many years ago how important it is to have important it is to have important it is to have delivery guarantees delivery guarantees delivery guarantees if you want to if you want to if you want to build a reliable and build a reliable and build a reliable and resilient system. So resilient system. So resilient system. So one thing I one thing I one thing I want to emphasize: HTTP want to emphasize: HTTP want to emphasize: HTTP is inherently is inherently is inherently synchronous. No matter synchronous. No matter synchronous. No matter how much async/await we how much async/await we how much async/await we add to our code, the add to our code, the add to our code, the protocol itself protocol itself protocol itself remains remains remains synchronous, right? synchronous, right? So we can do So we can do whatever we want, it whatever we want, it whatever we want, it will still be synchronous. Is will still be synchronous. Is n't that right? If, n't that right? If, for example, we for example, we for example, we use GRPC use GRPC use GRPC for communication between for communication between for communication between services or services or services or microservices, we will microservices, we will microservices, we will still face the still face the still face the same problem. GRPC same problem. GRPC same problem. GRPC uses HTTP/2, a uses HTTP/2, a uses HTTP/2, a newer version of HTTP, but newer version of HTTP, but newer version of HTTP, but it's still the same it's still the same it's still the same protocol. It has protocol. It has protocol. It has many limitations. So many limitations. So , if we're talking about a , if we're talking about a , if we're talking about a real system in the real system in the real system in the AI era, how can we not AI era, how can we not AI era, how can we not use HTTP?
-
use HTTP? Well, at first it's not that Well, at first it's not that simple, but if we simple, but if we simple, but if we look at look at any system, any system, any system, for example, we have an for example, we have an for example, we have an ordering component ordering component ordering component that needs to that needs to that needs to interact with interact with interact with a catalog that contains the a catalog that contains the a catalog that contains the inventory of our inventory of our inventory of our products and so on. products and so on. The most common The most common method would be: okay, method would be: okay, method would be: okay, we'll just make an HTTP we'll just make an HTTP we'll just make an HTTP API call. It's easy, API call. It's easy, API call. It's easy, everyone knows it. everyone knows it. Any junior developer Any junior developer Any junior developer would know how to would know how to would know how to do this, right? HTTP do this, right? HTTP request, you do GET, POST, request, you do GET, POST, request, you do GET, POST, etc., and you get a etc., and you get a etc., and you get a response back. But response back. But response back. But if you really want to if you really want to if you really want to have a reliable system, have a reliable system, have a reliable system, you will have to you will have to you will have to implement queues implement queues implement queues instead of these HTTP instead of these HTTP requests. So, now in requests. So, now in requests. So, now in our old our old our old architecture, the architecture, the architecture, the client- client- server architecture, which is one of the server architecture, which is one of the server architecture, which is one of the simplest in the IT simplest in the IT world, the terminology world, the terminology world, the terminology is changing. And now is changing. And now is changing. And now we no longer have a we no longer have a we no longer have a client and a server, client and a server, client and a server, instead we have a publisher instead we have a publisher instead we have a publisher or sender that or sender that or sender that sends not requests but sends not requests but sends not requests but events or commands, and we events or commands, and we events or commands, and we have subscribers have subscribers have subscribers or consumers or consumers or consumers listening to these events listening to these events listening to these events that we publish from that we publish from that we publish from the publisher. So, I want the publisher. So, I want the publisher. So, I want to emphasize that we to emphasize that we to emphasize that we should make the most of should make the most of asynchrony, asynchrony, as it has its as it has its as it has its advantages, but advantages, but advantages, but at the same time we at the same time we at the same time we face face face problems. So when
-
problems. So when problems. So when we we we modernize, we modernize, we modernize, we face a lot of face a lot of face a lot of complexity, and that complexity, and that complexity, and that complexity is already complexity is already complexity is already being addressed being addressed being addressed with the right with the right with the right patterns. And that's exactly what patterns. And that's exactly what patterns. And that's exactly what I want to talk about with the I want to talk about with the I want to talk about with the template I'm template I'm template I'm going to going to going to present. So, present. So, present. So, let's say we have an let's say we have an let's say we have an order service order service order service that receives some that receives some that receives some changes, and we want to changes, and we want to changes, and we want to save those orders, save those orders, save those orders, right? In the right? In the right? In the orders table. Nothing orders table. Nothing orders table. Nothing complicated. This is a very complicated. This is a very complicated. This is a very simple architecture. simple architecture. But what if, upon But what if, upon receiving an order, receiving an order, receiving an order, we want to we want to we want to publish or publish or publish or notify some notify some notify some other system that other system that other system that a change has occurred a change has occurred a change has occurred or an order has been received or an order has been received or an order has been received . Maybe . Maybe . Maybe we want to inform the we want to inform the CEO, right? That CEO, right? That the order has been received, the order has been received, the order has been received, or we want to, I don't know or we want to, I don't know , notify the , notify the , notify the marketing department. And we marketing department. And we marketing department. And we want to do this in a want to do this in a want to do this in a completely decoupled completely decoupled completely decoupled way, without way, without way, without using HTTP. using HTTP.
-
Now we have several Now we have several options. One is to options. One is to options. One is to first first first save the order save the order save the order in the database and in the database and in the database and publish an event publish an event publish an event that will notify the other that will notify the other that will notify the other system. So, we have system. So, we have system. So, we have two steps. Saving two steps. Saving two steps. Saving in the database and in the database and in the database and publishing. Or we publishing. Or we publishing. Or we could potentially could potentially publish the event first and publish the event first and then save then save then save the order to the the order to the the order to the database. So which one database. So which one database. So which one is correct? Well, we is correct? Well, we is correct? Well, we could even could even could even try to save try to save try to save them at the same time, right? But is them at the same time, right? But is them at the same time, right? But is it possible? Not it possible? Not it possible? Not quite. Because we quite. Because we quite. Because we will get what we at will get what we at will get what we at Particular Software have called Particular Software have called Particular Software have called the terms: the terms: zombie records and zombie records and zombie records and ghost messages ghost messages . And that essentially you . And that essentially you . And that essentially you find yourself in find yourself in find yourself in limbo in limbo in limbo in your system. your system. your system. Think about it. We Think about it. We Think about it. We can, for example, can, for example, when you have a when you have a ghost message ghost message , you have a message , you have a message that was sent, that was sent, right? Or you, right? Or you, sorry, have a record in the sorry, have a record in the sorry, have a record in the database with database with database with an order that is an order that is an order that is saved, but there is no saved, but there is no saved, but there is no notification. And with notification. And with notification. And with zombie records, you would, uh zombie records, you would, uh , have the opposite: , have the opposite: , have the opposite: there is a notification, but there is a notification, but there is a notification, but there is no corresponding there is no corresponding there is no corresponding record in the database.
-
record in the database. So, uh, how do So, uh, how do you prevent this? Because in a you prevent this? Because in a you prevent this? Because in a distributed world, distributed world, distributed world, it's essentially it's essentially all or nothing, right? all or nothing, right? You need to have You need to have some kind of transaction between some kind of transaction between some kind of transaction between these systems, but these systems, but these systems, but that's problematic because that's problematic because that's problematic because how do you establish how do you establish how do you establish a transaction between a a transaction between a a transaction between a database and another database and another database and another system? In our system? In our system? In our case, let's say a case, let's say a case, let's say a message broker, message broker, message broker, RabbitMQ, Azure Service Bus, etc. RabbitMQ, Azure Service Bus, etc. So, ideally, we So, ideally, we need an atomic need an atomic need an atomic transaction to transaction to transaction to make sure that these make sure that these make sure that these two events, these two two events, these two two events, these two steps—actually, not to steps—actually, not to steps—actually, not to confuse them with events confuse them with events —happen —happen —happen at the same time. So both at the same time. So both at the same time. So both publishing and publishing and publishing and database changes must database changes must database changes must happen together. happen together. Actually, at the same time, Actually, at the same time, so that there are no so that there are no so that there are no gaps during the gaps during the gaps during the audit. audit.
-
So, in any So, in any distributed system, distributed system, distributed system, errors are inevitable. It's errors are inevitable. It's errors are inevitable. It's not a problem if not a problem if not a problem if something goes wrong. something goes wrong. The problem is when The problem is when and what happens and what happens and what happens when when when failures occur. In asynchronous failures occur. In asynchronous messaging, failures messaging, failures can occur at can occur at can occur at various stages before the various stages before the message is sent message is sent because you because you because you rely on another rely on another rely on another system or system or system or message broker. After message broker. After message broker. After sending, perhaps sending, perhaps sending, perhaps before processing before processing before processing the message, the message, the message, perhaps before perhaps before perhaps before saving something to the saving something to the saving something to the database. So, all of database. So, all of database. So, all of these steps add these steps add these steps add complexity to the system, and complexity to the system, and complexity to the system, and you have to treat you have to treat you have to treat each component as something each component as something each component as something that can that can that can fail. So you can fail. So you can fail. So you can prepare prepare prepare accordingly. And accordingly. And accordingly. And understanding how to understanding how to understanding how to detect, detect, detect, classify, and classify, and classify, and possibly possibly possibly implement implement implement retry policies retry policies retry policies is critically is critically is critically important. For example, important. For example, important. For example, in in message-based systems, failures message-based systems, failures on the on the on the recipient side will not recipient side will not recipient side will not affect the affect the message senders, message senders, right? Because this right? Because this right? Because this message message message will remain somewhere will remain somewhere will remain somewhere in the in the in the message broker, on disk message broker, on disk , in the database, somewhere else.
-
, in the database, somewhere else. So if something So if something happens while happens while happens while trying to process trying to process trying to process the message, I don't know the message, I don't know , maybe the schema , maybe the schema , maybe the schema has changed, this error has changed, this error has changed, this error can be retried can be retried and it won't affect and it won't affect the sender. Not like the sender. Not like the sender. Not like it would be with HTTP, where it would be with HTTP, where it would be with HTTP, where the sender the sender the sender would get a failure status code would get a failure status code would get a failure status code or be unable to or be unable to or be unable to move on from that move on from that move on from that step. Because step. Because step. Because messages are messages are messages are persistent, even persistent, even persistent, even error error error messages messages messages will remain in the will remain in the will remain in the system until you system until you system until you can fix them can fix them can fix them and and and reproduce them. And this reproduce them. And this reproduce them. And this increases the stability of the increases the stability of the increases the stability of the system. So, how do system. So, how do system. So, how do you implement all these you implement all these you implement all these useful things to useful things to useful things to prevent crashes? Well, prevent crashes? Well, prevent crashes? Well, the answer is that the answer is that the answer is that you can't you can't you can't prevent crashes, but prevent crashes, but prevent crashes, but you can you can you can apply the apply the apply the right patterns right patterns right patterns so that the system doesn't so that the system doesn't so that the system doesn't suffer. We just suffer. We just suffer. We just established that HTTP is not established that HTTP is not established that HTTP is not as good as we as good as we as good as we previously thought. And previously thought. And previously thought. And having distributed having distributed having distributed systems without at least systems without at least systems without at least some of the patterns some of the patterns some of the patterns I'm going to I'm going to I'm going to talk about is talk about is talk about is not having a reliable not having a reliable not having a reliable system. Isn't that right? We have system. Isn't that right? We have system. Isn't that right? We have only scratched only scratched only scratched the surface. So, the the surface. So, the the surface. So, the first template first template first template I want to I want to I want to talk about is Outbox. And the talk about is Outbox. And the talk about is Outbox. And the Outbox template Outbox template Outbox template applies to the applies to the applies to the problem we problem we problem we just talked about. So
-
just talked about. So just talked about. So we will take the same we will take the same we will take the same system. We are system. We are system. We are planning changes to the planning changes to the planning changes to the ordering service, whether ordering service, whether ordering service, whether it's the API or it's the API or it's the API or lower-level services. It doesn't lower-level services. It doesn't lower-level services. It doesn't matter how you matter how you matter how you structure your structure your structure your code, but this is a general code, but this is a general code, but this is a general overview. So, essentially, overview. So, essentially, overview. So, essentially, the changes are saved to the changes are saved to the changes are saved to the order, and the order, and the order, and then we need to then we need to make it so that make it so that the event that the event that the event that is published is published is published is also saved to the is also saved to the is also saved to the database. So, how do we database. So, how do we database. So, how do we solve this? It's pretty solve this? It's pretty solve this? It's pretty simple. We simple. We simple. We are introducing an are introducing an are introducing an additional table additional table additional table called "outbox" called "outbox" . And since . And since we now have a single system and we now have a single system and we now have a single system and database, we can database, we can database, we can apply apply apply a transaction to it. And a transaction to it. And a transaction to it. And the transaction will be able to the transaction will be able to the transaction will be able to simultaneously save simultaneously save simultaneously save the order and the event to be the order and the event to be published. Right? So, we're Right? So, we're bringing everything together under bringing everything together under bringing everything together under one roof. OK. one roof. OK. one roof. OK. We save We save We save the order, we the order, we the order, we save the event, but save the event, but save the event, but how exactly do we how exactly do we how exactly do we publish that publish that publish that event? We event? We event? We no longer have "zombie records no longer have "zombie records " or "phantom " or "phantom " or "phantom messages," but how do messages," but how do messages," but how do we now retrieve we now retrieve we now retrieve a message a message a message stored in a table?
-
stored in a table? stored in a table? After all, it's not an event, it's After all, it's not an event, it's After all, it's not an event, it's just a record in the just a record in the just a record in the database. Well, this database. Well, this database. Well, this issue is already solved issue is already solved issue is already solved if you if you if you are using are using are using a framework like a framework like a framework like MassTransit, NServiceBus or MassTransit, NServiceBus or MassTransit, NServiceBus or others, as they others, as they others, as they already have a already have a already have a small component built into them. small component built into them. You won't have to You won't have to do anything; it will do anything; it will do anything; it will itself take these events from the itself take these events from the itself take these events from the outbox table and outbox table and outbox table and deliver them to the deliver them to the deliver them to the system that system that sends sends messages. This messages. This messages. This example that I took... example that I took... This is the most famous, This is the most famous, most most most used used used option, but there may option, but there may option, but there may be others, right? If be others, right? If be others, right? If you're using Azure you're using Azure you're using Azure or AWS, it's basically a or AWS, it's basically a or AWS, it's basically a message broker. And message broker. And message broker. And after that, the outbox “worker” ( after that, the outbox “worker” ( background process) background process) background process) will publish the event from the will publish the event from the will publish the event from the database to the database to the database to the message broker. And message broker. And message broker. And from there, consumers from there, consumers from there, consumers will be able to receive this will be able to receive this will be able to receive this event. So what does this event. So what does this event. So what does this fix? Well, the fix? Well, the fix? Well, the “outbox” template eliminates “outbox” template eliminates “outbox” template eliminates the loss of messages the loss of messages the loss of messages because they will because they will because they will be stored in the be stored in the be stored in the database until they database until they database until they are ready to be are ready to be are ready to be sent to sent to sent to the broker, and from there to the the broker, and from there to the the broker, and from there to the consumers. This consumers. This consumers. This will fix any will fix any will fix any inconsistent states inconsistent states inconsistent states that may be occurring in that may be occurring in that may be occurring in your system. Events your system. Events your system. Events sent without a sent without a sent without a corresponding record corresponding record corresponding record in the database, or a in the database, or a in the database, or a saved order saved order saved order without an event. And in without an event. And in without an event. And in distributed distributed distributed systems, two-phase systems, two-phase systems, two-phase commit is not always a
-
commit is not always a commit is not always a practical solution. practical solution. It also prevents It also prevents retries retries retries that create that create that create duplicates. Good? So duplicates. Good? So duplicates. Good? So let's take a look at the let's take a look at the let's take a look at the code. You will be able to code. You will be able to code. You will be able to access the access the access the code and run it code and run it code and run it yourself if yourself if yourself if you want. I you want. I you want. I have prepared an example have prepared an example have prepared an example using using using MassTransit and NServiceBus. So, MassTransit and NServiceBus. So, MassTransit and NServiceBus. So, let's take a let's take a let's take a look at this look at this project. Not this one. That's for project. Not this one. That's for later. Of course? You later. Of course? You later. Of course? You should see Visual Studio. should see Visual Studio. should see Visual Studio. And I apologize for And I apologize for And I apologize for using Visual Studio. using Visual Studio. using Visual Studio. I've I've I've started using started using started using Rider fairly recently and didn't want to mess anything up live Rider fairly recently and didn't want to mess anything up live . My next . My next purchase will be a Mac, so purchase will be a Mac, so purchase will be a Mac, so Rider is the one for me. And Rider is the one for me. And Rider is the one for me. And I'm trying to learn I'm trying to learn I'm trying to learn and master Rider. But and master Rider. But and master Rider. But for the presentation, I didn't for the presentation, I didn't for the presentation, I didn't want to take any risks and want to take any risks and want to take any risks and see how it would see how it would see how it would go. So, let's go. So, let's go. So, let's talk about talk about talk about architecture. It's architecture. It's architecture. It's quite simple.
-
quite simple. quite simple. In general, we have the In general, we have the In general, we have the Orders API as an Orders API as an Orders API as an entry point into our entry point into our entry point into our application. Then application. Then application. Then we have certain levels. This is how we have certain levels. This is how we have certain levels. This is how I like to divide I like to divide I like to divide my code. You can my code. You can my code. You can do it differently. do it differently. do it differently. The idea is The idea is The idea is that in that in that in messaging or messaging or messaging or event-driven event-driven event-driven systems, you systems, you systems, you need libraries need libraries need libraries to reuse to reuse functionality. If you put everything If you put everything in one folder or API, in one folder or API, in one folder or API, you will have to you will have to you will have to share the API itself, which is share the API itself, which is share the API itself, which is not what you want to not what you want to not what you want to do. Let's do. Let's do. Let's see what we have here see what we have here see what we have here . We have an . We have an . We have an order controller order controller order controller who accepts who accepts who accepts orders. And orders. And there is nothing there is nothing complicated inside the order acceptance method. It will complicated inside the order acceptance method. It will complicated inside the order acceptance method. It will save the order in the save the order in the save the order in the database. It will database. It will database. It will publish an publish an publish an order receipt event order receipt event . And also, at the same time, the . And also, at the same time, the order creation event, right? So, order creation event, right? So, you can you can you can publish as publish as publish as many events or many events or many events or send commands as you want send commands as you want send commands as you want depending on your depending on your depending on your subject area subject area subject area and Additionally, we and Additionally, we and Additionally, we can segment can segment can segment consumers as we consumers as we consumers as we see fit.
-
see fit. For example, I have an administrator notification here that administrator notification here that listens for certain listens for certain listens for certain types of events and reacts types of events and reacts types of events and reacts to them. I also have a to them. I also have a to them. I also have a RabbitMQ instance RabbitMQ instance RabbitMQ instance running in Docker. These are running in Docker. These are running in Docker. These are queues where at the end of these queues where at the end of these queues where at the end of these queues there are consumers queues there are consumers queues there are consumers waiting for waiting for waiting for messages to messages to messages to be placed in these be placed in these be placed in these queues. And I think that's it queues. And I think that's it queues. And I think that's it . Let's . Let's . Let's run the application run the application . And, of course, I have a . And, of course, I have a . And, of course, I have a database. Let database. Let database. Let me show it to you. me show it to you. me show it to you. I have a brand new I have a brand new I have a brand new database. Empty. It database. Empty. It database. Empty. It contains an contains an contains an orders database with several orders database with several orders database with several tables. Customers, tables. Customers, tables. Customers, order items, order items, order items, orders, and they are orders, and they are orders, and they are linked to the outbox. And as linked to the outbox. And as linked to the outbox. And as you will see, you will see, you will see, it is empty now. Let's it is empty now. Let's it is empty now. Let's see what see what see what happens when we happens when we happens when we use Postman to use Postman to use Postman to send a send a send a random random random order. Okay, I'm order. Okay, I'm order. Okay, I'm sending. You see sending. You see that I got a that I got a that I got a 202 accepted response. The 202 accepted response. The 202 accepted response. The API itself has just accepted API itself has just accepted API itself has just accepted the order, and the order, and the order, and theoretically it should theoretically it should theoretically it should be in the database. We are be in the database. We are be in the database. We are not yet checking
-
not yet checking not yet checking whether the products in whether the products in whether the products in the order are in stock, the order are in stock, the order are in stock, etc. We just etc. We just etc. We just work on the work on the work on the "Yolo" principle. And you'll "Yolo" principle. And you'll "Yolo" principle. And you'll see that these two see that these two see that these two tables, I'll tables, I'll tables, I'll show you the code now. These two show you the code now. These two show you the code now. These two tables, actually tables, actually tables, actually three together with the input ones three together with the input ones , which we , which we , which we will talk about soon. Created by will talk about soon. Created by will talk about soon. Created by RabbitMQ. Oh, sorry. RabbitMQ. Oh, sorry. RabbitMQ. Oh, sorry. MassTransit. Okay, MassTransit. Okay, MassTransit. Okay, let me show let me show let me show you in the Orders API what you in the Orders API what you in the Orders API what this looks like. In general, this looks like. In general, this looks like. In general, I'm using the I'm using the I'm using the free version of free version of free version of MassTransit now that MassTransit now that MassTransit now that it's become it's become it's become commercial because I commercial because I commercial because I just wanted to just wanted to just wanted to show you the pattern, show you the pattern, show you the pattern, not the tool. So, not the tool. So, not the tool. So, how to do it? You how to do it? You how to do it? You add Entity Framework Outbox. add Entity Framework Outbox. add Entity Framework Outbox. You pass a You pass a You pass a context, and every context, and every context, and every time you time you time you save something to the save something to the save something to the database, it database, it database, it connects to connects to connects to that connection and that connection and that connection and also stores also stores also stores the information in the the information in the the information in the output messages table output messages table . You see some . You see some . You see some information about the information about the delivery service being turned off, etc. You delivery service being turned off, etc. You are setting up MassTransit.
-
are setting up MassTransit. are setting up MassTransit. We indicate that We indicate that We indicate that we are using RabbitMQ. we are using RabbitMQ. we are using RabbitMQ. We have a We have a We have a retry policy. And we retry policy. And we retry policy. And we configure multiple configure multiple configure multiple endpoints. endpoints. endpoints. Let's look right Let's look right here in RabbitMQ and here in RabbitMQ and see that we have see that we have see that we have two...let's two...let's two...let's try to zoom in a little bit try to zoom in a little bit try to zoom in a little bit . We have "order . We have "order . We have "order created" and "order received", two created" and "order received", two created" and "order received", two messages messages messages waiting for us, which waiting for us, which waiting for us, which means that the consumers are means that the consumers are means that the consumers are not running, because as not running, because as not running, because as you can see, the messages are you can see, the messages are you can see, the messages are not lost, they are not lost, they are not lost, they are waiting there to be waiting there to be waiting there to be processed. And when I processed. And when I processed. And when I run a working run a working run a working instance of the instance of the instance of the admin notifications, they admin notifications, they admin notifications, they will be picked up, and will be picked up, and will be picked up, and as a result we as a result we as a result we will see will see will see the message in the the message in the the message in the console window. And console window. And console window. And you will see them you will see them you will see them disappear from here. disappear from here. disappear from here. OK. Now we have OK. Now we have OK. Now we have two systems. We have two systems. We have two systems. We have RabbitMQ, which is a broker, RabbitMQ, which is a broker, RabbitMQ, which is a broker, and we have a database, and we have a database, and we have a database, which, well, you know what that is which, well, you know what that is which, well, you know what that is , right? So, , right? So, , right? So, we have to we have to we have to treat them as treat them as not being part of the not being part of the not being part of the same world, and I'll same world, and I'll same world, and I'll show you how show you how show you how Outbox actually works.
-
Outbox actually works. I'll uncomment this I'll uncomment this line of code because it will line of code because it will line of code because it will buy us some time, buy us some time, buy us some time, it will save the records in the it will save the records in the it will save the records in the Outbox tables, and we Outbox tables, and we Outbox tables, and we can see what's can see what's can see what's really really really going on behind going on behind going on behind the scenes. Okay, the scenes. Okay, the scenes. Okay, let me let me let me stop that too. Okay, stop that too. Okay, stop that too. Okay, send it. Let's send it. Let's send it. Let's send a few and send a few and send a few and query the query the query the database. Now you'll database. Now you'll database. Now you'll see that I have see that I have see that I have three orders in the three orders in the three orders in the orders table orders table orders table here. That's them, and we'll here. That's them, and we'll here. That's them, and we'll see a bunch of see a bunch of see a bunch of records saved in the records saved in the Outbox message table. I'll try to Outbox message table. I'll try to expand to full expand to full expand to full screen and zoom in a little screen and zoom in a little screen and zoom in a little . You'll . You'll . You'll see that these are events, see that these are events, see that these are events, "order receipt created" and "order "order receipt created" and "order "order receipt created" and "order created", so two for created", so two for created", so two for each order each order each order we create. You we create. You we create. You will see that each will see that each will see that each Outbox has an ID, so they Outbox has an ID, so they Outbox has an ID, so they belong to the same belong to the same belong to the same Outbox. And the Outbox. And the Outbox. And the outbox state is related to outbox state is related to outbox state is related to this table here, this table here, this table here, right? Three, that is, this one, right? Three, that is, this one, right? Three, that is, this one, foreign keys, etc.
-
foreign keys, etc. And we can see And we can see the contents of the the contents of the the contents of the message body, you see, message body, you see, message body, you see, along with other along with other along with other metadata added by metadata added by metadata added by MassTransit. But now MassTransit. But now MassTransit. But now let's take a look at let's take a look at let's take a look at RabbitMQ. You'll see here, uh RabbitMQ. You'll see here, uh RabbitMQ. You'll see here, uh , it's working, , it's working, , it's working, waiting, but I waiting, but I waiting, but I can also do something. can also do something. can also do something. Wait. I am going to Wait. I am going to Wait. I am going to stop the stop the stop the RabbitMQ instance. You'll see it's RabbitMQ instance. You'll see it's RabbitMQ instance. You'll see it's off, and off, and off, and then I'll be able to then I'll be able to then I'll be able to send out a few send out a few send out a few orders and the system orders and the system orders and the system will just work. And will just work. And will just work. And I'll query the I'll query the I'll query the table again, and you'll table again, and you'll table again, and you'll see more see more see more saved things. But saved things. But saved things. But they are all events they are all events they are all events waiting to be waiting to be waiting to be processed by consumers. processed by consumers. And once again And once again , RabbitMQ is still , RabbitMQ is still , RabbitMQ is still down. But I don't down. But I don't down. But I don't lose the things I send lose the things I send lose the things I send . So, they . So, they . So, they are stored are stored are stored directly in the directly in the directly in the database. So now, as soon as database. So now, as soon as database. So now, as soon as I start the I start the notification workflow, I'll notification workflow, I'll start RabbitMQ again, because start RabbitMQ again, because start RabbitMQ again, because the worker will process the worker will process the worker will process the messages in the messages in the messages in the table, send them to the table, send them to the table, send them to RabbitMQ, and from there RabbitMQ, and from there RabbitMQ, and from there the consumer will pick them up. And the consumer will pick them up. And the consumer will pick them up. And you will see them here. There are you will see them here. There are you will see them here. There are quite a few of them. Quite quite a few of them. Quite quite a few of them. Quite a lot— a lot— a lot— meaning all the ones that are here.
-
meaning all the ones that are here. Now they should Now they should disappear because they have been disappear because they have been disappear because they have been processed. And that's it. processed. And that's it. Here's how it works. Here's Here's how it works. Here's how you prevent how you prevent how you prevent message loss and message loss and message loss and how you add an how you add an how you add an extra layer of extra layer of extra layer of reliability to your reliability to your reliability to your system. Okay, but I system. Okay, but I system. Okay, but I just want to point out just want to point out just want to point out that this reliability is that this reliability is that this reliability is on the on the on the sender side, right? Not the sender side, right? Not the sender side, right? Not the processing side. So processing side. So processing side. So why why why use it? Well, use it? Well, use it? Well, for all of these reasons, for all of these reasons, for all of these reasons, and of course, and of course, and of course, reliability. The reliability. The reliability. The outbox table can also outbox table can also outbox table can also serve as an serve as an serve as an audit log for released audit log for released audit log for released events. You can events. You can events. You can configure MassTransit and configure MassTransit and configure MassTransit and other frameworks that other frameworks that other frameworks that already have this template already have this template already have this template to not clear the to not clear the to not clear the outbox tables, and outbox tables, and outbox tables, and use them use them use them as an audit log. So, as an audit log. So, as an audit log. So, to have to have to have end-to-end reliability on the end-to-end reliability on the end-to-end reliability on the message handling side, message handling side, message handling side, you also need to you also need to you also need to consider the inbox template consider the inbox template . The inbox template is what . The inbox template is what . The inbox template is what happens on happens on happens on the broker side when the broker side when the broker side when a message a message a message is processed. So, is processed. So, is processed. So, that's one side of that's one side of that's one side of the coin, and that's the other the coin, and that's the other the coin, and that's the other side of the coin, right?
-
side of the coin, right? When a message When a message is published, what is published, what is published, what happens from the happens from the happens from the broker's point of view broker's point of view broker's point of view onwards. So if we onwards. So if we onwards. So if we look beyond the broker look beyond the broker look beyond the broker , we will have a , we will have a , we will have a consumer or consumer or consumer or processing service, such as an processing service, such as an processing service, such as an email service, email service, email service, etc., just like etc., just like etc., just like we have for we have for we have for creating creating creating messages or messages or messages or receiving orders receiving orders . So, the message . So, the message . So, the message arrives and arrives and arrives and is stored in a is stored in a is stored in a special table special table special table with a unique with a unique with a unique identifier. And identifier. And identifier. And it checks whether it checks whether it checks whether the message has already the message has already the message has already been processed. If been processed. If been processed. If the message has already the message has already the message has already been processed, it been processed, it been processed, it skips it. skips it. skips it. Right? So Right? So Right? So now we have another now we have another now we have another table that acts as a table that acts as a table that acts as a registry of what has been registry of what has been registry of what has been sent and sent and sent and processed. You processed. You processed. You will see this will see this inbox state, which is now inbox state, which is now empty because we empty because we empty because we have consumed all the have consumed all the have consumed all the messages. So we'll messages. So we'll messages. So we'll have to have to have to try again a little bit.
-
try again a little bit. I will also stop I will also stop the consumer now and send the consumer now and send the consumer now and send another order to another order to another order to take a look. Okay, take a look. Okay, take a look. Okay, let me take a look. We do let me take a look. We do let me take a look. We do not process. not process. Let's see, Rabbit does Let's see, Rabbit does n't have that. Hmm. Okay n't have that. Hmm. Okay . The status of incoming . The status of incoming . The status of incoming messages, here it is. messages, here it is. messages, here it is. So, in principle, So, in principle, So, in principle, every message every message every message is saved. The is saved. The consumer ID will be consumer ID will be assigned assigned assigned by the framework. And then by the framework. And then by the framework. And then you see how many you see how many you see how many times it was times it was times it was received, when it was received, when it was received, when it was consumed, when it was consumed, when it was consumed, when it was delivered, and so on delivered, and so on . By default, . By default, . By default, all brokers have all brokers have all brokers have at least, sorry, at least, sorry, at least, sorry, not all brokers.
-
not all brokers. not all brokers. Most brokers Most brokers Most brokers have a delivery policy have a delivery policy called " at least once". at least once". at least once". So, the message So, the message So, the message will be delivered will be delivered will be delivered at least once. at least once. at least once. So imagine processing a So imagine processing a So imagine processing a payment "at least payment "at least payment "at least once." We certainly would once." We certainly would once." We certainly would n't want that, n't want that, n't want that, right? So, inbox is a right? So, inbox is a right? So, inbox is a way to prevent a way to prevent a message from being processed twice or thrice , because you can , because you can , because you can see whether the see whether the see whether the message has been consumed message has been consumed or not, right? And that's why or not, right? And that's why or not, right? And that's why it can act it can act it can act as a registry for as a registry for as a registry for messages. messages. Preventing mistakes . So it also . So it also . So it also performs performs performs message deduplication, without message deduplication, without message deduplication, without having to having to having to worry about worry about worry about how to know if a how to know if a message or message or email has been sent, email has been sent, email has been sent, etc., right? It does etc., right? It does etc., right? It does this automatically this automatically this automatically by looking at an by looking at an automatically created table. So, automatically created table. So, if we want to have if we want to have if we want to have end-to-end reliability end-to-end reliability , we need to , we need to , we need to consider the outbox and inbox consider the outbox and inbox consider the outbox and inbox together. And this is a love together. And this is a love together. And this is a love relationship. And even relationship. And even relationship. And even if you haven't heard of the if you haven't heard of the if you haven't heard of the inbox pattern as a inbox pattern as a inbox pattern as a separate term, you separate term, you separate term, you should know: if there is should know: if there is should know: if there is an outbox, then the an outbox, then the an outbox, then the other other other part is probably involved, even if part is probably involved, even if part is probably involved, even if it is not mentioned it is not mentioned . So, one side . So, one side . So, one side is from is from is from the application to the the application to the the application to the message bus, and the other is message bus, and the other is from the bus to the consumer
-
from the bus to the consumer . So these two parts . So these two parts . So these two parts work together. You will work together. You will work together. You will be able to run be able to run be able to run this code. There are also this code. There are also this code. There are also steps there if you steps there if you steps there if you want to try it want to try it want to try it yourself. And the third yourself. And the third yourself. And the third pattern I'll show you is pattern I'll show you is pattern I'll show you is saga. So, in saga. So, in saga. So, in distributed distributed distributed systems, we systems, we systems, we usually have to usually have to usually have to coordinate the work of coordinate the work of coordinate the work of many systems. many systems. Order payment, Order payment, storage, delivery, storage, delivery, storage, delivery, whatever. The number of whatever. The number of whatever. The number of your microservices your microservices your microservices depends on your depends on your depends on your subject area. The subject area. The Saga pattern Saga pattern applies and should be applies and should be applies and should be used used used whenever you have whenever you have whenever you have something like a something like a something like a workflow or workflow or workflow or message that message that message that needs to go through needs to go through needs to go through a series of services to a series of services to a series of services to achieve a achieve a achieve a result, and you result, and you result, and you want to check the want to check the want to check the status of the process at status of the process at status of the process at each stage, each stage, each stage, right? This allows right? This allows right? This allows for reliable, for reliable, recoverable asynchronous communication, as you recoverable asynchronous communication, as you cannot cannot cannot rollback within rollback within rollback within an architecture an architecture an architecture spanning multiple spanning multiple spanning multiple services. So there are two services. So there are two services. So there are two types of Saga: orchestration, types of Saga: orchestration, types of Saga: orchestration, where, like a conductor in an where, like a conductor in an where, like a conductor in an orchestra, you tell orchestra, you tell orchestra, you tell each musician what to each musician what to each musician what to play. And choreography play. And choreography , where , where , where event-driven microservices event-driven microservices event-driven microservices operate independently, operate independently, operate independently, with
-
with with minimal minimal minimal coordination. So coordination. So coordination. So if we look at these if we look at these if we look at these two types of Saga, they two types of Saga, they two types of Saga, they would look something like would look something like would look something like this. With this. With this. With orchestration, you have a orchestration, you have a orchestration, you have a central node central node central node that coordinates everything, that coordinates everything, that coordinates everything, acting as a “god class” that acting as a “god class” that acting as a “god class” that starts services, starts services, starts services, invokes them, and invokes them, and invokes them, and sends sends sends messages to other messages to other messages to other components. Or components. Or components. Or choreography where everything is choreography where everything is choreography where everything is very loosely connected very loosely connected . And every system, . And every system, . And every system, every service every service every service knows exactly what to do. knows exactly what to do. So, orchestration So, orchestration will act as the will act as the will act as the central driver of the central driver of the central driver of the workflow, right workflow, right ? It will coordinate the ? It will coordinate the ? It will coordinate the life cycle. This is a life cycle. This is a life cycle. This is a mostly mostly mostly centralized centralized centralized approach. You approach. You approach. You will use will use will use it when you want it when you want it when you want full control full control full control and when you have complex and when you have complex and when you have complex error handling. And error handling. And error handling. And choreography is a choreography is a choreography is a different case, where different case, where different case, where each component each component each component knows exactly what to do.
-
knows exactly what to do. You have a full flow of You have a full flow of services that services that services that exchange exchange exchange messages back messages back messages back and forth, and they know and forth, and they know what to do to each other . But there is a problem: it is . But there is a problem: it is . But there is a problem: it is very difficult very difficult very difficult to set up. You to set up. You to set up. You need to know where need to know where the messages are going. You will the messages are going. You will need need visualization tools and visualization tools and systems like OpenTelemetry systems like OpenTelemetry systems like OpenTelemetry to track the message path to track the message path through the system. So, to sum up: So, to sum up: don't reinvent don't reinvent don't reinvent the wheel. These are the wheel. These are the wheel. These are problems that have already problems that have already problems that have already been solved. Don't write been solved. Don't write been solved. Don't write your own system to your own system to your own system to handle outbox, inbox, or saga; handle outbox, inbox, or saga; handle outbox, inbox, or saga; even though it even though it even though it seems simple with AI, you seems simple with AI, you seems simple with AI, you can miss can miss can miss important nuances that important nuances that important nuances that really really really matter. matter. Use Use ready-made tools, ready-made tools, ready-made tools, abstractions over abstractions over messaging infrastructure, and messaging infrastructure, and libraries like libraries like libraries like MassTransit, Brighter, Rebus, or MassTransit, Brighter, Rebus, or MassTransit, Brighter, Rebus, or Service Bus that Service Bus that Service Bus that will help you with this will help you with this will help you with this and eliminate the and eliminate the and eliminate the need need need to reinvent the wheel to reinvent the wheel . Well, thank you. I hope . Well, thank you. I hope . Well, thank you. I hope this was a useful this was a useful this was a useful walkthrough of the topic.
-
walkthrough of the topic. So, thank you very much. If So, thank you very much. If you have any questions, I'm you have any questions, I'm you have any questions, I'm right here in the chat. right here in the chat. Hi Irena, Hi Irena, thank you very much again for this. It thank you very much again for this. It thank you very much again for this. It was really very was really very was really very interesting. And I just interesting. And I just interesting. And I just want to assure you want to assure you want to assure you that we are not against that we are not against that we are not against using Visual Studio. using Visual Studio. using Visual Studio. This is normal. That's This is normal. That's This is normal. That's good. good. good. But I just wanted But I just wanted But I just wanted to emphasize to emphasize to emphasize No, it's okay. No, it's okay. No, it's okay. as as as Glad you're Glad you're Glad you're switching to Mac. You will switching to Mac. You will switching to Mac. You will join us. join us. join us. Join us. Join us. Join us. Yes. Yes. Yes. Sorry. Yes. Yes. Yes. Sorry. Yes. Yes. Yes. Sorry. Yes. If you Yes. If you Yes. If you need any advice on need any advice on need any advice on Rider, just let us Rider, just let us Rider, just let us know. But in know. But in any case, any case, any case, fantastic session. fantastic session. fantastic session. Thank you very much. Very Thank you very much. Very Thank you very much. Very useful information useful information useful information about messaging systems about messaging systems about messaging systems . . . Quick question. Quick question. Quick question. We only have a couple of We only have a couple of We only have a couple of minutes to catch up minutes to catch up minutes to catch up on a few, but should on a few, but should on a few, but should I use I use I use outbox every time outbox every time outbox every time I use the I use the messaging system? Not necessarily, but Not necessarily, but if you want a if you want a if you want a serious system, I serious system, I serious system, I advise advise advise using it using it . And if your data is, . And if your data is, . And if your data is, of course, important enough not to of course, important enough not to lose it. Brokers lose it. Brokers can be can be can be unavailable, just like unavailable, just like unavailable, just like databases, right? So it's databases, right? So it's databases, right? So it's worth having as worth having as worth having as many levels of many levels of many levels of resilience as possible, if resilience as possible, if resilience as possible, if possible. A possible. A comment came in comment came in suggesting that we suggesting that we suggesting that we could could could use use use SignalR functionality for the SignalR functionality for the SignalR functionality for the agent to agent to agent to resolve everything in resolve everything in resolve everything in real time, real time, real time, handle all handle all handle all errors, and do push errors, and do push notifications. How notifications. How notifications. How would this work, say, would this work, say, would this work, say, with atomicity and with atomicity and with atomicity and participation in participation in participation in distributed
-
distributed distributed transactions? Would transactions? Would transactions? Would something like something like something like real-time be an real-time be an real-time be an effective solution, effective solution, effective solution, or would it be better or would it be better or would it be better to stick with these to stick with these to stick with these patterns and patterns and patterns and abstractions, like you abstractions, like you abstractions, like you said, and things like said, and things like said, and things like MassTransit and so on? MassTransit and so on? Well, SignalR solves a different Well, SignalR solves a different problem, problem, problem, uses a different uses a different uses a different type of connections. type of connections. Asynchronous Asynchronous messaging in messaging in messaging in general in general in general in distributed distributed distributed systems is not systems is not systems is not real-time. That's why real-time. That's why real-time. That's why the term "ephemeral the term "ephemeral the term "ephemeral consistency" was consistency" was consistency" was introduced, introduced, introduced, because you have to because you have to because you have to design your design your design your system so that you system so that you system so that you know: an event know: an event know: an event has occurred, something has occurred, something has occurred, something will happen, but you don't will happen, but you don't will happen, but you don't know exactly when it know exactly when it know exactly when it will happen, right? SignalR will happen, right? SignalR will happen, right? SignalR gives a gives a gives a real-time feel. And I real-time feel. And I real-time feel. And I think this is a separate think this is a separate think this is a separate connection, and there are connection, and there are connection, and there are many other many other many other things involved here. I don't know things involved here. I don't know things involved here. I don't know how how how relevant outbox is and whether relevant outbox is and whether relevant outbox is and whether it works with SignalR, as it works with SignalR, as it works with SignalR, as it is designed to it is designed to it is designed to solve a different solve a different solve a different set of problems.
-
set of problems. set of problems. Of course. Of course. Of course. Mm. OK. Um, I Mm. OK. Um, I Mm. OK. Um, I also like also like also like your point your point your point at the end of the session about at the end of the session about at the end of the session about not having to not having to not having to rewrite everything, rewrite everything, rewrite everything, reinvent the wheel, reinvent the wheel, reinvent the wheel, etc. However, I don't etc. However, I don't etc. However, I don't quite understand the quite understand the quite understand the implementation of some of implementation of some of implementation of some of these patterns. Hmm, these patterns. Hmm, these patterns. Hmm, how much of it do how much of it do how much of it do you have to write you have to write you have to write yourself, and how much yourself, and how much yourself, and how much is already ready? So I is already ready? So I is already ready? So I wasn't sure what wasn't sure what wasn't sure what exactly was the code exactly was the code exactly was the code you were writing and what you were writing and what you were writing and what was provided "out of was provided "out of was provided "out of the box" by RabbitMQ, Mass Transit, the box" by RabbitMQ, Mass Transit, the box" by RabbitMQ, Mass Transit, or other similar or other similar or other similar platforms. platforms. Well, actually, I did Well, actually, I did n't write anything. The code you n't write anything. The code you n't write anything. The code you write write write using using transportation abstractions like Mass transportation abstractions like Mass Transit and Service Bus Transit and Service Bus Transit and Service Bus is truly business is truly business code. You control code. You control code. You control how to handle the type of how to handle the type of how to handle the type of event or event or event or message, but all the message, but all the message, but all the technical details technical details technical details are implemented are implemented are implemented by the platform. I didn't by the platform. I didn't by the platform. I didn't create a table create a table create a table for outbox. I just for outbox. I just for outbox. I just added a feature, added a feature, added a feature, right? With some right? With some right? With some properties, that's all. properties, that's all.
-
properties, that's all. Outbox was there, Outbox was there, Outbox was there, activated on the activated on the activated on the side I was side I was side I was interested in. And that's it. interested in. And that's it. interested in. And that's it. Same for inbox, right? Same Same for inbox, right? Same Same for inbox, right? Same with sagas. You with sagas. You with sagas. You have to define have to define have to define the steps, but everything that the steps, but everything that the steps, but everything that happens behind happens behind happens behind the scenes, like the scenes, like the scenes, like saving the saving the saving the saga states in the database— saga states in the database— I didn't do that. I'm I didn't do that. I'm I didn't do that. I'm only interested in my only interested in my only interested in my business logic, and that's business logic, and that's business logic, and that's really all. I really all. I really all. I let the framework let the framework let the framework do all the hard do all the hard do all the hard work and the wrapper work and the wrapper work and the wrapper around the around the around the message broker. So yes, that's why message broker. So yes, that's why message broker. So yes, that's why I want I want I want to emphasize: don't to emphasize: don't to emphasize: don't reinvent the wheel reinvent the wheel . I just turned on . I just turned on . I just turned on a few settings and that's it a few settings and that's it a few settings and that's it . The code is what . The code is what . The code is what I care about, the business I care about, the business logic. logic. logic. Yes, that's cool. It Yes, that's cool. It Yes, that's cool. It just wasn't entirely just wasn't entirely just wasn't entirely clear to me which clear to me which clear to me which parts you had to parts you had to parts you had to build yourself, build yourself, build yourself, because as I said, because as I said, because as I said, there's a lot of there's a lot of there's a lot of infrastructure with infrastructure with infrastructure with database tables database tables database tables and so on. and so on. and so on. But it's nice to know that But it's nice to know that AND there's another part AND there's another part that I think is really that I think is really that I think is really great: I don't great: I don't great: I don't have to speak the have to speak the have to speak the broker's language. I broker's language. I broker's language. I just use C just use C # with the methods # with the methods # with the methods the framework provides, and that's it. I the framework provides, and that's it. I the framework provides, and that's it. I know what a know what a know what a consumer is, what a consumer is, what a consumer is, what a sender is, and that's it sender is, and that's it sender is, and that's it . I'm not . I'm not . I'm not particularly concerned about how particularly concerned about how particularly concerned about how to confirm to confirm to confirm the message that the message that the message that it was successfully it was successfully it was successfully consumed, etc. I don't care consumed, etc. I don't care consumed, etc. I don't care . I was . I was . I was struggling with this for a while, and it wasn't struggling with this for a while, and it wasn't struggling with this for a while, and it wasn't much fun, much fun, much fun, at least with RabbitMQ and at least with RabbitMQ and at least with RabbitMQ and native APIs. Yes.
-
native APIs. Yes. native APIs. Yes. So, last So, last So, last question. Someone question. Someone question. Someone asked what happens asked what happens if you have a long if you have a long if you have a long downtime with the downtime with the downtime with the outbox pattern? And first I have outbox pattern? And first I have outbox pattern? And first I have to ask: what do you to ask: what do you to ask: what do you consider a long consider a long consider a long downtime? Is it a minute, downtime? Is it a minute, downtime? Is it a minute, 10 minutes, an hour, a day 10 minutes, an hour, a day ? ? I guess it depends I guess it depends on the business, right on the business, right ? And ? And ? And how big the how big the how big the blow can be. blow can be. Downtime can be Downtime can be long, even 30 long, even 30 long, even 30 seconds can be seconds can be seconds can be long for certain long for certain long for certain business areas. Isn't that right business areas. Isn't that right ? An hour can also ? An hour can also ? An hour can also be a long time. But be a long time. But be a long time. But at the same time, since you at the same time, since you at the same time, since you don't lose don't lose don't lose the message, you'll the message, you'll the message, you'll be able to resume your be able to resume your be able to resume your work. You'll run work. You'll run work. You'll run two consumers two consumers two consumers instead of one and instead of one and instead of one and be able to process everything be able to process everything be able to process everything that's accumulated in the that's accumulated in the that's accumulated in the database, right? And database, right? And database, right? And you will say: it was a you will say: it was a you will say: it was a load jump load jump . This happens. So, yeah, . This happens. So, yeah, . This happens. So, yeah, that's not something that can be that's not something that can be that's not something that can be clearly defined as clearly defined as clearly defined as acceptable acceptable acceptable downtime, right? downtime, right?
-
It's actually what It's actually what your boss finds your boss finds your boss finds acceptable. acceptable. Stakeholders or something. Stakeholders or something. If it's 2 minutes before the If it's 2 minutes before the boss calls, then it's a short boss calls, then it's a short downtime. downtime. downtime. And if it's not on And if it's not on And if it's not on the weekend, the weekend, that's fine. Okay, that's fine. Okay, fantastic. Thank fantastic. Thank fantastic. Thank you very much for you very much for you very much for talking to us, talking to us, talking to us, showing us all these showing us all these showing us all these patterns, and answering patterns, and answering patterns, and answering our questions. our questions. our questions. I think it's time to I think it's time to I think it's time to move on to our move on to our move on to our next speaker. next speaker. next speaker. So, thank you very much, Anya.
Summary
The main theme is the importance of asynchronous messaging patterns in distributed systems. Key subjects include the evolution of messaging from ancient times to modern tech, with specific mention of HTTP's limitations. The practical takeaway is that while we expect timely delivery for orders, a proper understanding and implementation of asynchronous messaging patterns are crucial for reliable distributed systems.