Skip to main content

Particular Software Blog

Latest articles

  • What they don't tell you about migrating a message-based system to the cloud

    Migrating a message-based system from on-premises to the cloud is a colossal undertaking. If you search for “how to migrate to the cloud”, there are reams of articles that encourage you to understand your system, evaluate cloud providers, choose the right messaging service, and manage security and compliance.

    Curiously, what’s often missing from the discussion is details, like how to handle all the other on-prem systems that integrate with your system, both upstream and downstream, that can’t be upgraded at the same time. This gets even more tricky when those integrations are over on-prem-only technologies, like MSMQ, that don’t integrate out-of-the-box with cloud alternatives like Azure Service Bus or Amazon SQS. It’s as if they’re saying, “Have you documented your system? Great! Have you chosen a cloud provider? Awesome! Do you have all the services in place? Wonderful! Now go rewrite all your code… we’ll wait…are you done yet?..What are you looking at me for? I’ve already told you to plan carefully, I can’t do EVERYTHING for you”

    Read more
  • Using anti-requirements to find system boundaries

    We all love building greenfield projects. 1 But inevitably, starting a new project involves lots of meetings with business stakeholders to hash out initial requirements and canonical data models. Those are…not so fun.

    When one of those meetings occurs after a carb-heavy lunch, it’s easy for your mind to drift away…back to those university lectures about entity design. Think of the nouns and what attributes they have. A dog and a cat are both animals and have 4 legs. Except now it’s Customers, Orders, Products, and Shopping Carts.

    Is this the best way to build a system, though? Didn’t we do the exact same thing on the previous greenfield project we’re now rewriting? Surely we won’t make all the same mistakes we made last time…right?

    Read more

    1. Or a rewrite of the greenfield project from 5 years ago, but that's another story.

    2. We'll know the project has hit the big time when we can no longer make the diagram fit on one page and remain readable. That's OK. I hear the copy shop down the street has a large format printer we can use…

    3. Spoiler alert: sometimes, these inventory numbers are totally fake and designed to scam you into feeling more pressure to buy! In other cases, you can continue to sell even when there's negative inventory by putting an item on backorder and notifying the customer when it becomes available. Here, let's pretend that we need this inventory to be accurate, at least as much as eventual consistency will allow.

    4. Anti-requirements or antirequirements, with or without the dash. Or, you can call them de-requirements or even dequirements? We'll stick with anti-requirements in this post.

    5. For another example of this kind of decomposition, check out Putting your events on a diet.

    6. You don't always have to ask them about anti-requirements directly. Using anti-requirements as a mental device on your own is just as valuable.

    7. Never ever had so much fun with a thesaurus. 😉

    8. Be careful with this anti-requirement too. In some contexts, inventory and shipping time could be related if a predictive algorithm determines that items with low inventory are likely to oversell, which means we can't promise 24-hour delivery. As always, it depends, so ask the business stakeholders to be absolutely sure.

    9. Harvard Business Review says the [most productive meetings have fewer than 8 people] because the number of people attending tends to have an inverse relationship with meeting productivity. And honestly, even 8 feels like a lot if you want to accomplish anything!

    10. Both terms have been abused so much they're almost meaningless, so take your pick.

    11. In vertical slice architecture, each service is responsible for all of the traditional "layers" (i.e., UI, Application, Domain Logic, and Database) within the slice that can be defined, in part, using anti-requirements. Check out videos on vertical slice architecture by Jimmy Bogard or Derek Comartin for more.

    12. This video uses the same shopping cart example as this article. Remember that the ViewModel composition code shown in the video is already out-of-date. Using ServiceComposer is a lot more user-friendly.

  • Increase your system's observability with OpenTelemetry support in NServiceBus

    When code breaks, our first move is carefully inspecting the call stack. It helps us find the needle in the haystack by understanding how, where, and why the failure occurred, including how we got there.

    However, in a message-based system, we no longer have a single call stack. We’ve exchanged it for a haystack of call stacks, which makes finding the needle (the root cause of the failure) even more difficult.

    Read more

    1. The .NET tracing API for OpenTelemetry uses the term Activity instead of Span from the OpenTelemetry specification. However, throughout this post, we will use the OpenTelemetry specification terminology of Span and its related terms.

    2. Even .NET Framework

    3. This package has been deprecated for NServiceBus version 8 and above in favor of the built-in implementation.

  • Lost messages are just as bad as lost luggage

    You’re standing in the airport, waiting to pick up your bag. Did you ever stop to think about all the software systems involved in tracking your luggage on your journey? From the moment you drop it off at your departure airport to the moment you breathe that sigh of relief as it shows up on the baggage carousel is a complex story of messaging and system integrations.

    I recently had the opportunity to chat with the lead developer for the luggage arrival system at a major Asian international hub. 1 He told me how using NServiceBus made it possible to get all the systems in the airport to work together reliably.

    Read more

    1. Unfortunately, it's impossible to name names without getting a bunch of lawyers involved. The names have been changed (well, just omitted) to protect the innocent.

    2. Well, hopefully. The bag source messages really represent the bags checked in from the outbound port, not the aircraft. So there's no way to know whether a bag made it onto the aircraft! 😬

  • Cancellation in NServiceBus 8

    NServiceBus endpoints have always been good at running reliably, but they could have been better at stopping. And when you want an endpoint to stop, you want it to stop…now.

    In NServiceBus 8.0, which is now available, we have introduced support for cooperative cancellation, which will give you greater control over how an NServiceBus endpoint behaves when you need to shut it down.

    Let’s talk about what cancellation is, how it relates to NServiceBus, and how we’re delivering cancellation in NServiceBus 8 without forcing a massive breaking change on your existing systems.

    Read more

    1. If you remember the upgrade to NServiceBus 6, we had a similar interface change to support async/await. While we still stand by that change now, it's not something we care to repeat.

    2. This technically means anywhere one of your method parameters implements ICancellableContext. This is a new interface we added as it includes both IPipelineContext (from which IMessageHandlerContext derives) as well as IBehaviorContext.

    3. ...or behaviors. But message handlers are far more common, so we'll focus on them here.

    4. NServiceBus already has an analyzer that makes sure you don't forget to await a Task returned by one of our APIs, and a suite of saga analyzers to make saga development easier.

    5. Come on, admit it, you do. I do too. Let's just all agree most of those messages aren't worth our time, right?

    6. silent and none may sound like the same thing, but they're not. If you choose silent, you don't get any squigglies or dots in the code, but if you hover your mouse over the code, you'll still get the analyzer message. If you choose none, then the analyzer won't report diagnostics at all.

  • Banish ghost messages and zombie records from your web tier

    Because it’s hard to write idempotent code effectively, NServiceBus provides the outbox feature to make your business data transaction and any sent or received messages atomic. That way, you don’t get any ghost messages or zombie records polluting your system. 1

    But the outbox can only be used inside a message handler. What about web applications and APIs?

    With the new NServiceBus.TransactionalSession package, you can use the outbox pattern outside of a message handler too.

    Read more

    1. For details on ghost messages, zombie records, and why they pose a problem for distributed systems, check out our blog post What does idempotent mean?

    2. Which is sad for the messages, I guess?

    3. …which you can learn about in our webinar Implementing an Outbox – model-checking first.

  • How we achieved 5X faster pipeline execution by removing closure allocations

    Divers in front of a gigantic shark

    The NServiceBus messaging pipeline strives to achieve the right balance of flexibility, maintainability, and wicked fast…ummm…ability. It needs to be wicked fast because it is executed at scale. For our purposes, “at scale” means that throughout the lifetime of an NServiceBus endpoint, the message pipeline will be executed hundreds, even thousands of times per second under high load scenarios.

    Previously, we were able to achieve 10X faster pipeline execution and a 94% reduction in Gen 0 garbage creation by building expression trees at startup and then dynamically compiling them. One of the key learnings of those expression tree adventures is that reducing Gen 0 allocation makes a big difference. The less Gen 0 allocation used, the more speed can be squeezed out of the message handling pipeline, which ultimately means more speed for our users.

    Read more
  • Let's talk about Kafka

    Statue of Franz Kafka in Prague, Czech Replubic
    Head of Franz Kafka, a kinetic sculpture in Prague, Czech Republic

    We get a lot of questions about Kafka. Is it good? Does it live up to the hype? And most frequently, when are we going to support Kafka in NServiceBus.

    But to fully answer these questions, it’s essential to understand what Kafka is, and more importantly what it isn’t, and then think about the kinds of problems that Kafka solves. So, let’s dive into the (heavily footnoted) details…

    Read more

    1. An overloaded term if ever there was one, but that's a subject for another post. Suffice it to say, this does not mean the same thing as an NServiceBus event.

    2. This is a bit of an oversimplification. Ordering in Kafka is only guaranteed per partition, and the number of partitions heavily influences how your topic can scale with the load.

    3. While this may sound like a small detail, it's one of the most important aspects that make technologies like Kafka so popular for data distribution. Guaranteed ordering is one of the fundamental requirements to ensure correct data replication.

    4. That is, assuming that the retention period or maximum size has not been reached, at which point Kafka will start overwriting data. On the other hand, queues will not apply retention settings by default, and if your queue gets full, it will reject further writes until you consume messages from it to free up space. That may sound bad, but it ensures you don't overwrite critical business data.

    5. A NACK or negative acknowledgment

    6. See how NServiceBus retries message processing to determine if a message is a poison message before forwarding it to an error queue in I caught an exception. Now what?

    7. See Error Handling Patterns for Apache Kafka Applications and Kafka Connect Deep Dive – Error Handling and Dead Letter Queues for more information.

    8. …and the folks at Kafka will back us up on this one.

  • Simpler configuration in ServiceControl

    The Particular Service Platform is packed full of features that help you monitor your NServiceBus systems. Among other things, it enables you to:

    • manage messages that require a manual retry
    • see when endpoints go offline and back online
    • detect connectivity problems with databases, brokers, and other systems using custom checks
    • troubleshoot message processing performance, both per-message and across an entire flow, using ServiceInsight

    Many of these capabilities have been developed over time as separate plugin packages. Each one has brought its own code-first configuration API. This approach has led to a situation where getting the most from the platform means installing six different NuGet packages and calling seven different configuration APIs.

    We knew we could make it easier. What if it was just one package, and one configuration API?

    Read more
  • More powerful Cosmos DB persistence

    The key to a successful Cosmos DB system is its data partitioning strategy. Like the rows of shrubs in a hedge maze, the logical partitions that divide data must be carefully planned, because that affects the scalability of the system and defines the boundaries for logical transactions.

    In version 1.1 of our CosmosDB persistence package, we’ve made defining the partition key for each message processed by NServiceBus much more straightforward, without needing a custom pipeline behavior. We’ve also added pessimistic concurrency support for more reliable processing of sagas with high contention patterns.

    Read more

    1. Maybe a little too powerful in this case, as there's a risk that the behavior for identifying the Cosmos DB partition could break the outbox feature.

    2. Unless you want to.

    3. For more details, see Optimizations to scatter-gather sagas.