Skip to main content

Particular Software Blog

Latest articles

  • Redesigning the NServiceBus pipeline yet again: The nerd sniping of Daniel Marbach

    Two fish, one representing a trim-capable pipeline, the other representing an impossible performance improvement, both eyeing a fish hook lowered into the water

    Daniel and I 1 have worked on improvements to the NServiceBus pipeline multiple times before: a 10x speed-up in 2017, and another 5x improvement in 2022. We thought we were all done with that.

    So, quite unexpectedly, this is the story of how I accidentally nerd sniped Daniel into redesigning the NServiceBus pipeline yet again.

    One little comment from me, and Daniel made the pipeline start 330x faster and run 25-29% faster on the success path, while still producing zero allocations along that path.

    Do I feel a little bad about it? Yes. Will I get over it? Also probably yes.

    Read more

    1. David, your author, and Daniel's nemesis. Ok, not really. Daniel and I are great buds, but I digress…

    2. And given that, it logically follows that one of the first things to get trimmed away would be the compiler code itself.

    3. If you analyze it another way, there were 5 years between the first two performance enhancements, and then 4 years between the previous one and this one. Assuming a linear decrease in time between pipeline improvements, can we expect another groundbreaking performance enhancement in just 3 years? You'll have to check back with us in 2029 to find out.

    4. Andrew Lock does a fantastic job explaining new .NET features like this one, but an even better job at highlighting why it matters. If you don't follow his posts, you should!

    5. If you're interested, our code is open source, you know…

    6. Our first iteration of prewired invokers used exactly that: 130 lines of hardcoded switch-case factory code that mapped each context type to its corresponding InvokerNode<TIn, TOut type.

    7. Daniel had his revenge on me during the editing of this post. After I recalled the XKCD origin of the term "nerd sniping" I was drawn in by the "infinite grid of one-ohm resistors" (my original degree was in Electrical Engineering) sending me far down a rabbit hole that included a trip to Physics Stack Exchange and, far too many minutes later, a realization that I no longer remember enough calculus to understand the math going on there.

  • Preparing NServiceBus for trimming and AOT

    Trimming a tree

    Trimming a tree blindfolded is probably not the best idea in the world. The best-case scenario is “at least the tree didn’t die.” The worst-case scenario is a trip to the emergency room. 1

    The .NET ecosystem is getting into the tree-trimming business (in a manner of speaking), and we’re starting to make changes to NServiceBus to ensure you won’t be caught trimming your apps with a blindfold on.

    Trimming and ahead-of-time compilation (AOT) reward code that the compiler can see. That changes some of the design assumptions for a framework like NServiceBus, which until now has relied on runtime discovery to maintain a productive developer experience.

    Read more

    1. Those scissors are sharp!

    2. This is because source generators do not perform well when driven off implemented interfaces, so Microsoft recommends you Never Do That®. Scans using an attribute are the fastest and most optimized code path, which is important because a source generator can technically run every time you press a key in your IDE.

    3. To check a package for yourself, navigate to the NuGet package page, click the Open in NuGet Package Explorer link such as this one for Npgsql, open the lib folder, then (generally) the latest net*.0 directory, and then click on the assembly DLL. Now look below for any AssemblyMetadata values. A package is trimmable if the key IsTrimmable has value True, and is AOT-compatible if IsAotCompatible has value True.

    4. That's right, if the source generator generates code that refers to your handler type, it will no longer be flagged as having no references!

  • Our new Small Business Program

    Sketch image showing gradual discount levels
    Update 2026-03-31: Particular has contributed the SmallBusinessProgram repository to the Use What Works community organization. Update 2026-01-15: Following Dylan Beattie’s video about licensing models in the .NET ecosystem, and the discussions it triggered in the community, we have decided to open-source our Small Business Program. We’re making it available under the CC-BY license so that everybody can reuse, mix, and modify it without worry of copyright infringement. We hope this will make it that extra bit easier for others to… Read more
  • AWS Enhancements

    Cartoon image conveying building construction around AWS

    Check out the latest enhancements to NServiceBus support for AWS. All of these updates aim to give you more control, fewer surprises, and a smoother experience when building distributed message-based systems on AWS.

    Read more

    1. 30 seconds by default

    2. Check out our blog post Infrastructure soup or our pipeline behavior documentation for more info.

  • Resistance is futile...unless you have ServicePulse

    Screen on the Star Trek Enterprise providing an imagined futuristic view of ServicePulse
    ServicePulse helps you recover from failures

    We are the Borg. Your messages have failed and will be assimilated. Resistance is futile.

    Distributed systems are a lot like Star Trek’s infamous Borg Collective: massively parallel, highly interconnected, and sometimes, drones services go down or are inaccessible. After all, even with a galaxy-class architecture, things sometimes go wrong. Messages can fail due to transient errors, unexpected exceptions, or configuration hiccups. However, well-designed distributed systems take a stronger cue from the Borg; they are built to be resilient. But how? Let’s explore a more peaceful quadrant of the galaxy to illustrate how this works.

    Read more

    1. In the 24th century, this would probably be NServiceBus version 168?

    2. Do you think that's still a thing in the 24th century?

  • It's a Trap! The Two Generals' Problem

    In distributed systems, coordination is hard—really hard—especially when both parties depend on mutual confirmation to proceed, but there’s no guarantee their messages will arrive. This classic dilemma is known as the Two Generals’ Problem. Like most problems in computer science, it’s easier to understand when explained with lasers, spaceships, and sarcastic smugglers.

    Let’s set the stage: It’s Return of the Jedi and the second Death Star looms large over the forest moon of Endor. The Rebel Alliance’s plan hinges on a synchronized attack — Han Solo leads the ground team to destroy the shield generator, while Lando Calrissian leads the space fleet to attack the Death Star itself.

    For the mission to succeed, both parties must execute their part of the plan. If either side decides to abort, the other must as well, or it will be a disaster.

    And here’s the twist: Han and Lando can only communicate through spotty, insecure rebel comms. Sound familiar?

    Read more
  • Achieving lean controllers: Incremental refactoring with Transactional Session

    It doesn’t matter if you’re developing using MVC, WebAPI, or Razor pages—you want your controller code to be nice and lean. The more bloated that code is, the more coupling you have, and the closer you are to an unmanageable big ball of mud.

    You probably already know that, but I’d bet not all of your controller code is as lean as you’d like it to be. Is it?

    So that leaves the question… How do we get there?

    Read more

    1. In a good way. Boring code is reliable code!

    2. It's almost always the tables!

    3. Implementations exist for SQL databases, Cosmos DB, Azure Tables, DynamoDB, MongoDB, and RavenDB.

  • Managing success and growing pains

    Every software system evolves through different stages of complexity. They start simple—attempting to solve a problem that might not yet be well-defined. As they grow, problems become more well-defined, and then they grow some more. Just like with lanky teenagers, this growth can sometimes cause growing pains. A skilled architect knows how to watch for the signs of these growing pains and how to apply more robust architectural patterns to ensure the system can continue to grow and flourish.

    This post is the story of the growing pains experienced by our friends at VECOZO, a system integrator that ensures safe communication between numerous healthcare-related companies. They knew it would be irresponsible to design every piece of software to handle massive scale, even if it only had a few users. So, when the architects started to see telltale signs, they knew it was time to deploy more robust architectural patterns.

    As you read on, maybe you’ll find that some of the challenges they faced sound familiar…

    Read more
  • 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.