Saga implementation patterns – Controller

In the previous post on saga implementation patterns, we looked at the Observer pattern. In that pattern, the saga was a passive participant in the business transaction, similar to how many fast food restaurants fulfill orders. But not all food establishments fulfill their orders in this way, and find more efficient means of doing so.

Instead of merely observing events from other entities, we can have our saga perform an active role in the process. The saga controls the flow directly, issuing commands to specific workers, waiting for replies, and moves on to the next step. It works well for processes that need to happen in a certain order:


Our saga has a specific order, and many times, steps later in the saga need information from previous steps. In order to enforce an order, we need to take control of the process. We can’t ship before we bill, and we can’t bill before we procure, etc.

Unlike the Observer saga, the Controller saga directs the workflow by issuing commands and using replies to determine the next step. If a step fails or comes back with some error condition, we can determine an alternate flow. We can take compensating actions or direct the saga into another queue for manual intervention.

The key here is that our Controller saga directs with commands, and our Observer gathers events. Like our Observer saga, we can look again to the food industry to see an everyday example of a Controller saga in action.

Fast food messaging – Which Wich

While our McDonald’s example featured many steps that could execute in parallel, with no real interaction or dependencies, our local sandwich shop of Which Wich is completely the opposite. In this shop, the entire process is a single pipeline:


Our customer begins the process by placing an order. At Which Wich, this is done in a rather ingenious manner. The customer picks a paper bag labeled with a main ingredient. On the bag are lists of toppings alongside little bubbles. The customer uses markers to color in the bubbles indicating what toppings they want on their sandwich. Finally, the customer puts their name on the bag so that when their order is completed, the person delivering the sandwich knows whom to deliver to.

Along the entire length of the store is a steel wire, where your bag is clipped to. The cashier slings your bag to the next station, where the next step processes that order, in the order the bags were received.

It’s still not *quite* a central controller in our example – we don’t have that one person whose job it is to coordinate the entire pipeline. Instead, it’s built in to our queues. If we wanted a real world example of a controller in a restaurant, we’d need to venture out of fast food into one where an executive chef managed a high-end restaurant. But I’ve never been one to let the truth get in the way of a good story.

There are quite a few benefits to this approach:

  • Steps can be explicitly ordered and correlated
  • No contention of resources, since no two steps for a single saga are executing at the same time

It’s not without its drawbacks:

  • Overall processing time can increase, since we’re forcing a serial processing of steps
  • Scaling can again be difficult because of the shared state and shared queues of many implementations

It turns out that our above example is better suited to another messaging pattern. But to get there, we’ll look at scaling sagas first, what problems we run in to and potential solutions.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in Messaging, NServiceBus, SOA. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • In the observer pattern, wouldn’t the saga need to send the initial commands to the various food stations before waiting for events? If so, then isn’t the only difference between the observer and the controller that the controller is sequential?

    • jbogard

      Not necessarily. In our observer picture, the initial command of “Place Order” resulted in a single event that was published to all stations. Those aren’t commands sent to each food station, they’re events.

      This could also mean that the saga doesn’t publish that initial event – there isn’t a single starting command then publish, it really is just observing a process that it doesn’t initiate. Make sense?

      • A saga observing a process it doesn’t initiate makes sense. (Though I don’t think I’d model that scenario this way. Who sends the command then? I’d model as a saga being started when customer places order, sends commands to all stations and waits for replies). I’m unsure about the semantics of the events published as a result of a “Place Order” command. It seems like the stations should receive commands not events since a reply is expected.

        • jbogard

          You’re right – there are a few different ways to model this.

          I might have the saga send a bunch of commands and wait for replies, or I could have the saga publish a message and wait for events on the other side.

          But it’s not impossible for a saga to observe a process it doesn’t initiate. Imagine our grillers. They don’t initiate a saga, but there’s a clear interaction between the grilling and building of a sandwich, usually by two different people. It’s the interaction between the two that signifies a “done” sandwich.

  • Pingback: The Morning Brew - Chris Alcock » The Morning Brew #1316()

  • Krzysztof Sadowski

    In my opinion the main difference between these two approaches is that “controller sagas” are more like a routing slips pattern from EIP, where every single component needs the knowledge where to deliver the message next, based on its content. The “observer saga” is more like a dynamic routing where every component is responsible only for its part of the job and doesn’t care to whom the message should be sent.

    • jbogard

      Not quite – imagine a scenario where the executive chef is barking orders to workers. When a step is done, the executive chef then directs the next worker to begin. Each worker would have different messages, unlike a routing slip, where it’s the same message.

      • Krzysztof Sadowski

        Ok. So your point is that we have a coordinating component here (executive chief), who is responsible for delegating orders to workers, while in routing slip each component passes the same message/document the next one in pipeline?

  • How is the Saga initiated? Is the Saga itself a Command Handler? Or is there some abstraction (e.g. SagaManager), which is a Command Handler signed up to the command bus? Or am I missing some piece completely? Thanks

    • jbogard

      It could be, but it’s really the subsequent messages that make it a controller/observer.

      In our McDonald’s example, we could have the initial “PlaceOrder” command begin the saga, or the “OrderAccepted” event do it instead. Either way, the lifecycle is either dictated by requests/responses or an events all around.

  • Is that really a saga? It looks more like a workflow because it touches multiples services (payments, shipping, fraud). From what I know, which is not a lot tbf, a saga would live inside one of those.

    If actions need to occur in a certain order, then a message is put back on the queue until it can be processed – i.e. the other actions have completed and left the system in the required state.

    Genuine questions.

    • jbogard

      I’m not sure what the difference is – you could implement a workflow inside an NServiceBus saga. A saga could live inside each one, yes. But I might still have something orchestrating the whole affair.

      • I was meaning a business workflow, as in a use case of the system which spans multiple services.

        I read the article again and can see what you mean now. I wasn’t used to seeing sagas used like this when – Udi and others always seem to be talking about pub/sub. I’m sure this has its place though.

        • jbogard

          This is the model I prefer for coordinating workflows inside a bounded context. Makes things much more explicit and obvious.

          • Gotcha. That makes a lot of sense Jimmy. Cheers

  • Pingback: Saga implementation patterns – variations | Jimmy Bogard's Blog()

  • Pingback: Scott Banwart's Blog › Distributed Weekly 199()

  • Pingback: Saga Pattern | Itsy bitsy of Technology()

  • Nick

    If we think of Validate, Fraud, Warehouse etc as encapsulated, distributed microservices where does the Saga live? Should all of the Saga’s share their own microservice, or do they go into one of the other existing services? I’m looking to incorporate NServiceBus into an Azure Service Fabric application.

    • jbogard

      Someone owns the saga’s logic. It’s not community-owned. Either it belongs in its own service, as it’s a business function owned by that service, or you have a coordinating service, that should have its own business-centric name and behaviors i.e., not “Manager” or “Processor”, that’s just an ESB by another name.

      And Azure Service Fabric != microservices.

      • Nick

        Thanks for the clarification regarding Saga location. Regarding you comment on Service Fabric not using a microservice pattern can you clarify why you are claiming that? Aside from MS referring to microservices throughout their documentation they state “Microservice applications are composed of small, independently versioned, and scalable customer-focused services that communicate with each other over standard protocols with well-defined interfaces.”.

        • jbogard

          Sure, microservices is not about any specific technology. You can implement a monolith with Service Fabric, or microservices with plain MVC.

          Beware vendor docs that mention microservices – they are there to sell you something. Service Fabric is just actor model stuff, that’s been around for ages.

          • Nick

            I totally agree. In retrospect I should have spoken more generic and mentioned that I was using a microservice pattern instead. Thanks.

          • jbogard

            So the good thing about this stuff is all the “Pure” SOA docs from the past 10-15 years still apply. Check out the EIP book and the SOA Patterns books, all directly applicable.