<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: rdoria1</title>
    <description>The latest articles on DEV Community by rdoria1 (@rdoria1).</description>
    <link>https://dev.to/rdoria1</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F446024%2F90adf93a-7796-478b-b557-e547efff2ab6.png</url>
      <title>DEV Community: rdoria1</title>
      <link>https://dev.to/rdoria1</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rdoria1"/>
    <language>en</language>
    <item>
      <title>My experience building backends with Booster Framework</title>
      <dc:creator>rdoria1</dc:creator>
      <pubDate>Wed, 16 Dec 2020 22:57:02 +0000</pubDate>
      <link>https://dev.to/rdoria1/my-experience-building-backends-with-booster-framework-307l</link>
      <guid>https://dev.to/rdoria1/my-experience-building-backends-with-booster-framework-307l</guid>
      <description>&lt;p&gt;When developing a new backend application, there is bunch of things we need to think about: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which language am I going to use? &lt;/li&gt;
&lt;li&gt;Do I need any framework? Which one?&lt;/li&gt;
&lt;li&gt;Do I know how to model my problem? (models, relations etc..)&lt;/li&gt;
&lt;li&gt;Where am I going to deploy my application? &lt;/li&gt;
&lt;li&gt;What kind of DB do I need? (SQL, noSQL etc..) &lt;/li&gt;
&lt;li&gt;How will I expose my service? &lt;/li&gt;
&lt;li&gt;Do I need a cloud provider? Which resources do I need?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Needless to say this is overwhelming, specially nowadays with the amount of options available to solve each problem. &lt;/p&gt;

&lt;p&gt;The truth is that this is very time consuming. &lt;strong&gt;Looking for the best posible available option is almost always a very expensive decision and it's a trap.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Instead, I believe it's always better to have a default choice. The problem is, how do we choose one? Well, it is basically an option we have high trust and confidence it will just work, something that is reliable to solve the problem you have. Once we have something working we can improve from there.&lt;/p&gt;

&lt;p&gt;The key point here is that it is delusional to think that at the beginning of a project we should test all the posible solutions to make the best possible decision from the very beginning.  &lt;/p&gt;

&lt;p&gt;I'm starting to think &lt;strong&gt;my default choice to develop backend applications can be the Booster Framework.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm mostly familiar with AWS when it comes to Cloud providers so let's imagine a regular development process &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I open my IDE, start writing some code&lt;/li&gt;
&lt;li&gt;Open AWS console (or change terraform if using infra as code) then change some param in Dynamo DB&lt;/li&gt;
&lt;li&gt;Then I remember I need to change another params in my API gateway then I open another tab with the AWS console&lt;/li&gt;
&lt;li&gt;Then I go back to my code and forget what I was doing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do you see where I'm going? This constant context switching between Infrastructure and Business logic (the code in my IDE) can be expensive and overwhelming specially at the beginning of a project or when crafting a prototype.&lt;/p&gt;

&lt;p&gt;I needed to build an account backend application quickly, a simple backend to add and subtract values, get balances etc.. so I decided to do it with Booster, I was done in like 2 hours. I didn't need to think about Infrastructure. Everything is deployed seamlessly, no context switching, no AWS console tabs, no Infra to handle. In this sense, it is very similar to the Serverless experience we get when writing a Lambda function in AWS for instance, but this even goes beyond that. &lt;/p&gt;

&lt;p&gt;Give it a try &lt;a href="https://www.booster.cloud/"&gt;https://www.booster.cloud/&lt;/a&gt; &lt;/p&gt;

</description>
      <category>serverless</category>
      <category>node</category>
      <category>aws</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Redefining Event Sourcing</title>
      <dc:creator>rdoria1</dc:creator>
      <pubDate>Fri, 30 Oct 2020 17:40:32 +0000</pubDate>
      <link>https://dev.to/boostercloud/redefining-event-sourcing-1m52</link>
      <guid>https://dev.to/boostercloud/redefining-event-sourcing-1m52</guid>
      <description>&lt;p&gt;Event Sourcing is complex and involves multiple concepts, patterns, and architectures. At The Agile Monkeys, we have been working with it for several years and we would like to share our vision of the main concepts around Event Sourcing.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Events&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Things that have happened (yes in the past).&lt;/p&gt;

&lt;p&gt;e.g. a customer has placed an order.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;State&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Something that evolves and changes over time with a finite number of possible values.&lt;/p&gt;

&lt;p&gt;e.g. A SKU can have multiple states (in stock, out of stock, soon to be available, discontinued, etc.)&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Events + State&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Events = Things that have happened that changed some state.&lt;/p&gt;

&lt;p&gt;e.g. Customer placed an order and therefore the order is in the PLACED status and the inventory of the item decreased by 1 etc.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Event Storage&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Permanent Storage where events are persisted.&lt;/p&gt;

&lt;p&gt;e.g. Can be a DB (NoSQL, SQL…) or maybe object storage (S3...) &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Event Sourcing Contract: 3 Main Concepts&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Store the full history of events (aka state changes) in the Event Storage: of course, we mean only the events we intended to store, the ones we designed to persist. &lt;/li&gt;
&lt;li&gt;Events are chronologically ordered: This allows to reconstruct the state of the system at any given point in time.
&lt;/li&gt;
&lt;li&gt;Immutable events: it’s an append-only system (no update nor removal). &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Data Removal&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Because of data privacy policies (like GDPR in Europe), there are some cases where users want to delete their data. Allowing this would break the Event Sourcing Contract we just described (immutable events). &lt;/p&gt;

&lt;p&gt;How can we support this use case?&lt;/p&gt;

&lt;p&gt;We can encrypt the data. When users request to delete their data, we are going to delete the encryption key. &lt;/p&gt;

&lt;p&gt;This design solves both problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By dumping the key we are making data unusable which fulfills the purpose of deleting the data from the user perspective.&lt;/li&gt;
&lt;li&gt;We are not opening unwanted doors by actually deleting the data (no permissions, no repo with delete methods, etc.) so we are still respecting the contract we described.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Event Sourcing usually works with&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Domain-Driven Design&lt;/li&gt;
&lt;li&gt;CQRS &lt;/li&gt;
&lt;li&gt;Event-Driven Architecture&lt;/li&gt;
&lt;li&gt;MicroServices &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Event sourcing excels when used together with the 4 concepts above. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Domain-Driven Design&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Uses conceptual maps (called object models) of the domain (easily maps to an actual business concept/idea) that incorporates both behavior and data.&lt;/p&gt;

&lt;p&gt;Creates common concepts/vocabulary to easily communicate with other technical teams and business people.&lt;/p&gt;

&lt;p&gt;e.g In the e-commerce business, a must-have object model would be an order (defined by its ID, customer ID, date, status, etc..)&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Domain Event&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Captures something that happened that changed the state of a domain model. &lt;/p&gt;

&lt;p&gt;e.g. A person changed their address, which changes the Address domain model given an AddressChanged event.&lt;/p&gt;

&lt;p&gt;We can then use the knowledge gained from the changes to do something useful with it.&lt;/p&gt;

&lt;p&gt;e.g. Since the person moved to a new place, we can send them reminders to update their address for all their bills.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Event Sourcing + DDD&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Stores the full history of domain events in the Event Storage.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Event Sourcing + Event-Driven Architecture&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Misconception: They are not the same! &lt;/p&gt;

&lt;p&gt;Event-Driven Architecture: System which is based on components communicating mainly or exclusively through notification events.&lt;/p&gt;

&lt;p&gt;When talking about “event” in event sourcing we are actually referring to the state change and not a “notification” as in the event-driven architecture (queues, bus, streams, async communication in general).&lt;/p&gt;

&lt;p&gt;domain event != notification event&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Event Sourcing + Microservices&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;When working with microservices architecture, we need to notify multiple services about state changes (domain events) so they can react to them. &lt;/p&gt;

&lt;p&gt;Usually, this is done with notification events (so we are using an event-driven architecture).&lt;/p&gt;

&lt;p&gt;In this case, notification events are domain events. &lt;/p&gt;

&lt;p&gt;e.g. Domain events persisted in the Event Storage. In an event-driven architecture, we need to notify Service A and B about them. In this case, we can call them notification events, as we decided to use async communication for this purpose. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Reading Data&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Don’t use your Event Storage as a Read Model. &lt;/p&gt;

&lt;p&gt;You might be tempted to query your Event storage to find the latest state for a given event. &lt;br&gt;
This can be slow for large systems. It might work for very small systems but reconstructing the full history to find the latest state for regular usage of your system doesn’t sound like a very good idea.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. CQRS - Read Model&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;A pattern that requires having separate classes for reading and writing data. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This allows us to have different models to read and write data. &lt;/li&gt;
&lt;li&gt;This also means the repositories (and therefore the DBs) can be different for reading and writing data. For instance, we can write to a relational DB (the writing part is the Event storage) and then read from a NoSQL DB.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CQRS generally has 2 main concepts: commands (write) and queries (read).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A command can return a value: Most likely the returned value will have to do with operation confirmation or identifiers and nothing to do with state changes and this operation is expected  to be asynchronous.  A domain event will be put into a queue (stream etc..) and be processed at a later stage. &lt;/li&gt;
&lt;li&gt;A query does not change any state, its only goal is to read. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This separation makes the following scenario possible.&lt;/p&gt;

&lt;p&gt;Let’s say we decide our Event Storage will be a NoSQL DB. Our Read Models will live in our Services and they will be separate DBs, they can be relational DBs.&lt;br&gt;
The Event Storage will remain our source of truth but each Read Model will be designed to render the data as needed per each service. That’s its only goal. &lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Snapshotting&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Since we are storing everything in the Event storage, one very common question is “How do we avoid reading all the data to find the latest state for a given domain model?” The solution is to create snapshots from time to time. Snapshots are actually part of the Event Storage itself. Let’s give an example to make it clearer.&lt;/p&gt;

&lt;p&gt;One of the classic examples of event sourcing is the bank card we use to perform withdrawal and credit operations. Domain events will persist these operations. In order to know the current balance of the account, we need to reconstruct all the operations from the beginning. Snapshotting here can be used to have the balance computed every 5 operations. In the worst case,  we would need to get the latest snapshot + 4 domain events to know the current balance, thus decreasing the number of reads significantly. &lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Snapshotting vs Read Model: Replay events&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If Snapshotting is used to reconstruct the latest state for a given domain model, why would we use Read Models? &lt;/p&gt;

&lt;p&gt;When working with a micro-service architecture they are used for different purposes.&lt;/p&gt;

&lt;p&gt;Imagine adding a new micro-service, therefore a new ReadModel DB. We need to reconstruct the latest history of domain events from the Event Storage so we’ll use the Replay events feature to achieve this.&lt;/p&gt;

&lt;p&gt;Replay Events is a feature of event sourcing and is a byproduct of 2 of the main concepts we defined: full history of domain events + ordered domain events. We can replay the full history of what happened and get the latest state for a given domain model.&lt;/p&gt;

&lt;p&gt;This can be a very time-consuming operation if we are talking about millions of domain events. The fastest way to do this is using Snapshotting.&lt;/p&gt;

&lt;p&gt;In this case we can seamlessly add a new microservice.  We are using snapshots for a different purpose as we are still using read models to read data from a given Microservice and not the snapshot from the Event storage. &lt;/p&gt;

&lt;p&gt;The same situation applies if we decide to completely dump a Read Model and change it for a new one. Our source of truth remains the Event Storage and we just need to replay all the events and create our new read model.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Benefits of Event-Sourcing&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Data-driven business &lt;br&gt;
When starting a new business/new product etc.. we just don’t know how much our data is worth. Even if the goal is clear at that point in time, it’s always a better idea to keep all the data to possibly use it at some point in the future (storing data is cheap now) Example: Let’s imagine we are creating a new e-commerce site and we are in charge of specifically adding features and then the checkout process to cart items. In this case, what matters the most is the final state of my cart before the user places the order. The fact that the user has added and then removed items doesn’t really affect the checkout process and the correct functioning of the website. Nevertheless, we should keep the full event history of adding/removing items from the cart. Even if not useful now, it can help us analyze the customer behavior and see why they added and deleted those items. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Audit/Logging&lt;br&gt;
By reliably persisting the full history of events we will be able to debug our applications more easily by finding the full history of events for a given domain model. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Since it’s an append-only system, we never lose data. We can’t delete any data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;High-Security Standard naturally by design: We can’t update or remove data. If a system gets hacked, data could still be appended meaning the current state of a given domain model would change. In any case, not losing any data is a great benefit. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Great fit for analytics: Since we have the full history of everything that happened, we analyze the past and use data to drive the business. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Disadvantages of Event-Sourcing&lt;/strong&gt;
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Mental shift for developers: There are a bunch of concepts that need to be mastered here, event sourcing, DDD, CQRS, event-driven architecture etc. It can be overwhelming.&lt;/li&gt;
&lt;li&gt;It should not be used for all scenarios. Like any other pattern, it doesn’t make sense in some cases. &lt;/li&gt;
&lt;li&gt;Unless we use the Event Storage for the read models (which is definitely not the best practice or not even possible in some cases), we are introducing data redundancy which can lead to potential inconsistencies and also eventual consistency.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;This is how we work with event sourcing in Booster.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>eventsourcing</category>
      <category>data</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Saga Patterns by Example </title>
      <dc:creator>rdoria1</dc:creator>
      <pubDate>Tue, 11 Aug 2020 15:49:26 +0000</pubDate>
      <link>https://dev.to/theagilemonkeys/saga-patterns-by-example-fod</link>
      <guid>https://dev.to/theagilemonkeys/saga-patterns-by-example-fod</guid>
      <description>&lt;h2&gt;
  
  
  Moving from Monolithic application to microservices
&lt;/h2&gt;

&lt;p&gt;A very common scenario nowadays is migrating Monolith applications to a new Microservice Architecture. &lt;/p&gt;

&lt;p&gt;We are not going to focus on explaining these architectures in this article. Instead, we are focusing on a very specific issue when it comes to dealing with Microservices: Data Consistency.&lt;/p&gt;

&lt;p&gt;With MicroServices we are usually going to follow a &lt;strong&gt;One Database per service&lt;/strong&gt; pattern. Imagine business transactions spanning across multiple services, meaning one transaction completion or failure will impact subsequent transactions. We need to maintain &lt;strong&gt;data consistency&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;We can’t use ACID local transactions, we need to solve this issue differently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Saga
&lt;/h2&gt;

&lt;p&gt;We’ll need &lt;strong&gt;Saga: Sequence of local transactions.&lt;/strong&gt;&lt;br&gt;
Each local transaction will&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Trigger the associated action (This will generally be a DB update, but can also be something like sending an email to a customer etc..)&lt;/li&gt;
&lt;li&gt;Publish a message/event to trigger the next local transaction&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the local transaction fails, there will be a series of compensating transactions to undo preceding local transactions. Undoing things doesn’t necessarily mean deleting data in case the action is a DB transaction, but rather updating some state to &lt;strong&gt;FAILED&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Enough theory, let’s get to a specific business which we will use to explore the specifics of what we described and to understand Saga.&lt;/p&gt;
&lt;h2&gt;
  
  
  Enrollment Credit Card
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvdc1g72h0lfbqrxvi2gy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvdc1g72h0lfbqrxvi2gy.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s imagine a Bank has an &lt;em&gt;Enrollment to New Credit Card&lt;/em&gt; process. Whenever a customer wants to ask for a new Credit Card, they will enter a bunch of data through some Forms. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;This data will get to a Card Service that will create the data needed to create Digital Credit Card on the fly (in the meantime the actual physical card gets processed and sent)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For this purpose it will first check the provided customer’s data is accurate and can be validated  through the Identity Service (maybe this service will use a third party service like Equifax to check the customer’s identity)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Then, the Calculation Service will determine the credit limit for the new credit card based on internal calculations and other factors&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Once everything is successfully completed the Card Service can finally return all the data for the new Digital Credit Card to the customer that was computed in the beginning.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Choreography Pattern
&lt;/h2&gt;

&lt;p&gt;Saga comes into 2 different flavors. First, we’ll explore the simplest and most direct one: The Choreography pattern. &lt;/p&gt;
&lt;h3&gt;
  
  
  Use Case
&lt;/h3&gt;

&lt;p&gt;The best way to describe this is to show the diagrams of the sequences of transactions happening just after the customer has entered all the required data in the form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgvbylcc03bfwgvfk2pue.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgvbylcc03bfwgvfk2pue.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The input data will get to the Card Service that will create a new record in the Card DB. Note we have a status value, which will play a key role here. For now it’s set with &lt;strong&gt;VERIFYING&lt;/strong&gt; value.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw5axtn9djqa5j20kw0j2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw5axtn9djqa5j20kw0j2.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the record is successfully persisted, a new event will be streamed by Card Service and consumed by Identity Service. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk514k36mli2bqfc7xw3h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk514k36mli2bqfc7xw3h.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Identity service will consume the event, then it will execute its internal logic and persist a new record in the Identity DB. The &lt;strong&gt;isVerified&lt;/strong&gt; attribute will be a boolean stating if the identity was indeed verified or not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqckb6aaaf3cgd00z488i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqckb6aaaf3cgd00z488i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the record is successfully persisted, a new event will be streamed and will be consumed by Card Service and Calculation Service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmgt5b8inos0y0vban8q4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmgt5b8inos0y0vban8q4.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The event consumed by Card Service will actually trigger an update of the record persisted in the first step. The status value will be updated to &lt;strong&gt;IDENTITY_VERIFIED&lt;/strong&gt;. We are notifying the main Service that the identity was verified. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fovmcplkoiargx3or87av.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fovmcplkoiargx3or87av.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The event will also be consumed by Calculation Service. This one will execute some internal logic so that the goal is to calculate the amount Limit for the potential new Credit Card and persist this new data to a new record in the Amount DB.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fss6ij6uugfhu0qsyscoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fss6ij6uugfhu0qsyscoe.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the record is successfully persisted a new event with the amount limit data will be streamed to be consumed by the Card Service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F83nio8pjma142g0kt36i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F83nio8pjma142g0kt36i.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, once the event is consumed by the Card Service we will again update the initial record with its final state. The &lt;strong&gt;amountLimit&lt;/strong&gt; value will be updated and the status will change to &lt;strong&gt;VERIFIED&lt;/strong&gt;. This status value means the new Credit Card Data is ready to be returned to the customer so they can start using their new Digital Credit Card.&lt;/p&gt;
&lt;h3&gt;
  
  
  Implementation details
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr8qsopwbkb1wfn7ee7fx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fr8qsopwbkb1wfn7ee7fx.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let’s imagine how we would implement this in the cloud, more specifically with Azure. We are showing  just a small part of the implementation as we can extrapolate this to the other services.&lt;/p&gt;

&lt;p&gt;As we can see from the diagram above, the services are implemented as Spring boot services. Whenever a new request gets to the Card Service, a new record is persisted in a Cosmos DB Card container. &lt;/p&gt;

&lt;p&gt;The interesting part of this architecture comes when integrating Change Feed. We won’t get into too many details on how it works (the official &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/change-feed-functions" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; is great) but in a nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enabled by default&lt;/li&gt;
&lt;li&gt;It exposes the Cosmos DB logs to the end user so you can consume it and integrate it with other resources to be notified about any new insertion or update.&lt;/li&gt;
&lt;li&gt;Sorted: Comes in the order of modification&lt;/li&gt;
&lt;li&gt;Can be integrated with a number of &lt;a href="https://docs.microsoft.com/en-us/azure/cosmos-db/change-feed-design-patterns" rel="noopener noreferrer"&gt;resources&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The easiest way to consume the change feed is the integration with Azure Functions, which also comes in handy  with our purpose. &lt;/p&gt;

&lt;p&gt;Once a new record in the Card Container is persisted, the Change feed will trigger a new Azure function with an event containing the new record. The azure function will receive this event and will do the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deserialize the content so we get the &lt;strong&gt;customerId&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Find the record associated with the given “customerId” in the Input Container. Actually, the Change Feed event received will only contain the data persisted in the Card Container. This is not enough for the next step which is the Identity Service. We will need identity data that was part of the original request. In this case we are fetching this data by directly reading a given Input container, but it might be something else such as an HTTP request from another Service.&lt;/li&gt;
&lt;li&gt;HTTP request to the Identity Service &lt;/li&gt;
&lt;li&gt;Wait for the Response and depending on the Response Code and Body, stream a new event through Event Hub to be consumed by the Card Service which will transition the Card Container record from &lt;strong&gt;VERIFYING&lt;/strong&gt; to &lt;strong&gt;IDENTITY_VERIFIED&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The implementation of the Azure function that consumes the change feed is really simple. Here is a skeleton of this function implemented in Java.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kn"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.function&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.azure.cosmos.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.azure.cosmos.models.CosmosItemResponse&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.azure.cosmos.models.PartitionKey&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.microsoft.azure.functions.annotation.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.microsoft.azure.functions.*&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;com.model.Input&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;org.json.JSONObject&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;java.util.Collections&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="cm"&gt;/**
 * Azure Function with Cosmo DB Card container Trigger from Change Feed.
 */&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CardChangeFeedTrigger&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;CosmosContainer&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;databaseId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enrollments"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;containerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Input"&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

    &lt;span class="nd"&gt;@FunctionName&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"CardChangeFeedTrigger"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
        &lt;span class="nd"&gt;@CosmosDBTrigger&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"items"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;databaseName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Enrollments"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;collectionName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Card"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;createLeaseCollectionIfNotExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;connectionStringSetting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"AzureCosmosDBConnection"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="nc"&gt;ExecutionContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

        &lt;span class="n"&gt;setupCosmoDB&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;            

            &lt;span class="c1"&gt;// Read customerId from Change Feed.&lt;/span&gt;
            &lt;span class="nc"&gt;JSONObject&lt;/span&gt; &lt;span class="n"&gt;jsonObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JSONObject&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;customerId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="n"&gt;jsonObject&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"customerId"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;


            &lt;span class="c1"&gt;// Read Input from Cosmo Container&lt;/span&gt;
            &lt;span class="nc"&gt;CosmosItemResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;readItem&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PartitionKey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;customerId&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="nc"&gt;Input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
            &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getLogger&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"New item received "&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getItem&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

            &lt;span class="c1"&gt;// Now we do an HTTP CALL to the Identity Service with data customerID and data from Input Model&lt;/span&gt;

            &lt;span class="c1"&gt;// Based on the Answer &lt;/span&gt;
            &lt;span class="c1"&gt;// 1. "IDENTITY_VERIFIED" event back to CardService if HTTP call succeeded.&lt;/span&gt;
            &lt;span class="c1"&gt;// 1. "IDENTITY_FAILED" event back to CardService if HTTP call failed.&lt;/span&gt;
            &lt;span class="c1"&gt;// 2. "IDENTITY_NOT_VERIFIED" event back to CardService if Identity not verified.&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;setupCosmoDB&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;CosmosClient&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;CosmosClientBuilder&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"COSMO_DB_HOST"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"COSMO_DB_MASTER_KEY"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;preferredRegions&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Collections&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;singletonList&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;System&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getenv&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"REGION"&lt;/span&gt;&lt;span class="o"&gt;)))&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;consistencyLevel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConsistencyLevel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EVENTUAL&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;buildClient&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
        &lt;span class="nc"&gt;CosmosDatabase&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getDatabase&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;databaseId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;container&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getContainer&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;containerId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easiest way to implement SAGA&lt;/li&gt;
&lt;li&gt;Each transaction is independent&lt;/li&gt;
&lt;li&gt;It’s ideal when not dealing with many local transactions (e.g. no more than 4) &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It is difficult to track and maintain this logic if several transactions and services are involved. In the implementation example we showed above let’s analyze how this would work:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We introduce a new Azure Function to consume the change feed. In terms of ownership it could be tricky to define who should “own” this new function. Does it fall under the Card Service? Or under the Identity Service?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Also, as we saw before, the event sent through Event Hub needs to be consumed by the Card Service meaning we’ll need to add a new logic in Card Service so it becomes a consumer of this message. Imagine having this same pattern with multiple services, N services would need to send events to Card Service, it would become difficult to maintain at some point.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Orchestration Pattern
&lt;/h2&gt;

&lt;p&gt;The second approach of SAGA comes with an Orchestrator. In this pattern, the coordination of all the transactions is fully abstracted into a separate service, an Orchestrator. We’ll use the same example as the one for Choreography pattern but we are adding a new Service called Verification Service.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation details
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn33dsfir1cf2wmsvbsq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn33dsfir1cf2wmsvbsq8.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This Verification Service will actually internally check if the customer is eligible for a new Card and check for any outstanding loan or any potential red Flag.&lt;/p&gt;

&lt;p&gt;We added this service so we have parallels and sequential operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once a new request is generated it will get to Card Service &lt;/li&gt;
&lt;li&gt;Card Service will trigger the Orchestrator which will be in charge of coordinating the rest of the transactions&lt;/li&gt;
&lt;li&gt;We have 2 verifications that need to happen and they will both be triggered in parallel, the Verification and the Identity Service.&lt;/li&gt;
&lt;li&gt;Once both are successfully completed,  the orchestrator will trigger the Calculation Service to compute the &lt;strong&gt;amountLimit&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We’ll use durable functions to implement the Orchestrator. &lt;/p&gt;

&lt;h3&gt;
  
  
  Durable functions
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-overview?tabs=csharp" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; on Durable functions is very useful, but in a nutshell:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extension of Azure functions&lt;/li&gt;
&lt;li&gt;Serverless State machines - used for Long-running orchestrations&lt;/li&gt;
&lt;li&gt;It simplifies complex transactions and coordination&lt;/li&gt;
&lt;li&gt;It maintains a local state&lt;/li&gt;
&lt;li&gt;It’s code only (No json schemas or config files like other orchestration systems)&lt;/li&gt;
&lt;li&gt;Currently available in &lt;strong&gt;Python, JavaScript and C#&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following image describes the structure of the project to create an orchestrator. We implemented the project in Javascript.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgdzswss18dx5h8f2ggm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcgdzswss18dx5h8f2ggm.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Under the same project (that we usually create with VSCode) we’ll have 3 different kinds of Azure Functions to create a whole Orchestrator workflow. Each function has its own folder.&lt;/p&gt;

&lt;h3&gt;
  
  
  Orchestrator Function
&lt;/h3&gt;

&lt;p&gt;The EnrollmentCreditCardOrchestrator folder will have the code of the orchestrator function itself. As seen it only contains 2 files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;function.json&lt;/li&gt;
&lt;li&gt;index.js&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The json file is a config file and as seen it’s a very small file specifying the function defined in the index.js file is an Orchestration Function (for further details, please check the documentation which is great). &lt;/p&gt;

&lt;p&gt;The Orchestration function looks like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;durable-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;orchestrator&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getInput&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Received New enrollment request. person: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; 
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; || card: &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Verify the request has all the mandatory fields&lt;/span&gt;
    &lt;span class="nf"&gt;verifyRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;verificationTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VerificationActivity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verificationTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;identityTask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IdentityActivity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;identityTask&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Wait for verificationTask and identityTask to finish&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Verification Task &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;verificationTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Identity Task &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;identityTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculationRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;creditData&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;verificationTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;identity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;identityTask&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;calculationCreditCard&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callActivity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;CalculationActivity&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;calculationRequest&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;calculationCreditCard&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;verifyRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A request object is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Gobernment ID is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;firstName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A first name is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A last name is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A type of work is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;workPlace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A work place is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;salary&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A salary is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A Card type is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;card&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brand&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A Cart brand is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The way we call the actual services is through Activities and more precisely through the &lt;strong&gt;context.df.callActitity&lt;/strong&gt; function which is another kind of function we’ll define later on. &lt;/p&gt;

&lt;p&gt;The context object is the one containing the request when triggering the orchestrator.&lt;/p&gt;

&lt;p&gt;“VerificationActivity” and “IdentityActivity” are triggered in parallel, whereas “CalculationActivity” sequentially. How do we do this? &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verification and Identity activities are called without the &lt;strong&gt;yield&lt;/strong&gt; word. This means they run in parallel.&lt;/li&gt;
&lt;li&gt;Line 18 specifies we want to wait for both activities to be completed before moving forward&lt;/li&gt;
&lt;li&gt;Once both successfully return with their respective payload, we actually call the Calculation activity synchronously, we get the result from it and then return the final result &lt;strong&gt;calculationCreditCard&lt;/strong&gt; to the user who triggered the Orchestration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Activity Function
&lt;/h3&gt;

&lt;p&gt;As seen in the project structure screenshot, each activity function will have its own folder. Each folder will have its config file specifying the function in index.js is an activity function. &lt;/p&gt;

&lt;p&gt;The index.js will look something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;identityURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;IDENTITY_SERVICE_URL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CircularJSON&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;circular-json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;identityURL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;body returned...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;CircularJSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Identity Service encountered an error: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this specific case we imagined the services are already implemented somewhere else so the only goal of the activity function would be to use some HTTP library (like axios in this case) to make the HTTP request to them. In the practice if we are dealing with a new brand service you can also implement the actual logic of this service in the Activity Function. &lt;/p&gt;

&lt;p&gt;The activity functions and orchestration functions live in different VMs. &lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP Trigger Function
&lt;/h3&gt;

&lt;p&gt;This is the last kind of function we need, the only purpose of this function is to actually expose the orchestrator as an HTTP endpoint so it can be called from any client easily.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;durable-functions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;instanceId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;startNew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;functionName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Started orchestration with ID = '&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;instanceId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;'.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createCheckStatusResponse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bindingData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;instanceId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a result, when triggering the orchestrator we’ll get a bunch of URLs as a result (Check documentation)&lt;/p&gt;

&lt;p&gt;When calling the &lt;strong&gt;statusQueryGetUri&lt;/strong&gt; we will get the current status of the orchestrator&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdqk1g2zajsh0i9l7spn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhdqk1g2zajsh0i9l7spn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Advantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Easy to maintain the whole flow in a single place&lt;/li&gt;
&lt;li&gt;Avoid cyclic dependencies, again everything happens in a single place.&lt;/li&gt;
&lt;li&gt;If designing a smart orchestrator, the complexity of adding new transactions remains linear.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Disadvantages
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;New Service to maintain: In distributed teams pattern, adding this new service can be tricky to decide which team should own it. It contains logic and domains from all the services.&lt;/li&gt;
&lt;li&gt;It’s also challenging to know a little bit of the logic of all the services, or at the least clearly understanding the return payloads from services and understanding how to react if something fails and how it affects all the services.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
