<?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: berkslv</title>
    <description>The latest articles on DEV Community by berkslv (@berkslv).</description>
    <link>https://dev.to/berkslv</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%2F410215%2F5ed02aae-014a-45a6-aa5a-859a5a78e835.jpeg</url>
      <title>DEV Community: berkslv</title>
      <link>https://dev.to/berkslv</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/berkslv"/>
    <language>en</language>
    <item>
      <title>Bringing GitHub Copilot Agents to Azure DevOps</title>
      <dc:creator>berkslv</dc:creator>
      <pubDate>Thu, 29 Jan 2026 10:44:58 +0000</pubDate>
      <link>https://dev.to/berkslv/bringing-github-copilot-agents-to-azure-devops-3dn3</link>
      <guid>https://dev.to/berkslv/bringing-github-copilot-agents-to-azure-devops-3dn3</guid>
      <description>&lt;p&gt;*This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge*&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;&lt;a href="https://github.com/berkslv/azure-copilot-sdlc" rel="noopener noreferrer"&gt;Azure Copilot SDLC&lt;/a&gt;&lt;/strong&gt;, an open-source CLI tool that bridges the gap between the Azure ecosystem and the new agentic AI capabilities of GitHub.&lt;/p&gt;

&lt;p&gt;GitHub recently introduced AI agents to revolutionize development workflows, but they are currently tightly coupled with GitHub Issues and Projects. If your enterprise relies on &lt;strong&gt;&lt;a href="https://azure.microsoft.com/en-us/products/devops" rel="noopener noreferrer"&gt;Azure DevOps&lt;/a&gt;&lt;/strong&gt; for work item tracking, you are effectively locked out of this revolution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Azure Copilot SDLC&lt;/strong&gt; solves this by leveraging the &lt;strong&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol (MCP)&lt;/a&gt;&lt;/strong&gt;. It connects GitHub Copilot’s AI capabilities directly to your Azure Boards and Repos, allowing you to orchestrate the full software development lifecycle without leaving your terminal—or by automating it entirely through enterprise pipelines.&lt;/p&gt;

&lt;p&gt;The tool automates three critical phases:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Plan:&lt;/strong&gt; Retrieves an Azure Work Item, analyzes repository architecture, and posts a technical implementation plan back to the Work Item comments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Develop:&lt;/strong&gt; Automates the "boring stuff"—branch creation, code implementation, unit test generation, and PR submission.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review:&lt;/strong&gt; Acts as a first-pass reviewer, identifying security vulnerabilities and logic issues before a human reviewer steps in.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Enterprise Workflow: Webhooks &amp;amp; Pipelines
&lt;/h2&gt;

&lt;p&gt;While the CLI is powerful for local development, its true potential in an enterprise setting lies in &lt;strong&gt;automation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Because &lt;code&gt;azure-copilot-sdlc&lt;/code&gt; is a portable CLI, it can be integrated directly into your &lt;strong&gt;&lt;a href="https://azure.microsoft.com/en-us/products/devops/pipelines" rel="noopener noreferrer"&gt;Azure DevOps Pipelines&lt;/a&gt;&lt;/strong&gt;. By configuring &lt;strong&gt;&lt;a href="https://learn.microsoft.com/en-us/azure/devops/service-hooks/services/webhooks" rel="noopener noreferrer"&gt;Azure DevOps Webhooks&lt;/a&gt;&lt;/strong&gt;, you can trigger this AI-powered workflow automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Zero-Touch" Workflow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger:&lt;/strong&gt; A developer moves a Work Item to the "Active" state in Azure Boards.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhook:&lt;/strong&gt; Azure DevOps sends a webhook to a listener (like an Azure Function).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline:&lt;/strong&gt; The listener triggers an Azure DevOps Pipeline containing the &lt;code&gt;azure-copilot-sdlc&lt;/code&gt; executable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; The pipeline runs the &lt;code&gt;plan&lt;/code&gt; and &lt;code&gt;develop&lt;/code&gt; commands. Within minutes, the developer returns to find a technical plan commented on their task and a fresh Pull Request waiting for their review.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Demo / Links
&lt;/h2&gt;

&lt;p&gt;You can find the full source code, build scripts, and documentation here:&lt;br&gt;
👉 &lt;strong&gt;&lt;a href="https://github.com/berkslv/azure-copilot-sdlc" rel="noopener noreferrer"&gt;Azure Copilot SDLC Repository&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Phase 1: Planning
&lt;/h3&gt;

&lt;p&gt;The agent reads requirements from Azure, scans the codebase, and generates a plan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run azure-copilot-sdlc plan 1247

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Result: Detailed technical plan posted to the Azure DevOps Work Item.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 2: Development
&lt;/h3&gt;

&lt;p&gt;The Developer agent takes the plan and implements the code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run azure-copilot-sdlc develop 1247

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Result: Feature branch created, code written, and PR submitted with links back to the work item.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Phase 3: Review
&lt;/h3&gt;

&lt;p&gt;The Reviewer agent scans the PR for compliance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;uv run azure-copilot-sdlc review 1247

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Result: Flagged issues and auto-fix suggestions provided in the terminal or PR comments.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;Building a tool that wraps &lt;strong&gt;&lt;a href="https://www.google.com/search?q=https://docs.github.com/en/copilot/github-copilot-in-the-cli" rel="noopener noreferrer"&gt;GitHub Copilot CLI&lt;/a&gt;&lt;/strong&gt; while using it was a meta experience.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Accelerating Boilerplate with Typer&lt;/strong&gt;&lt;br&gt;
I used &lt;strong&gt;&lt;a href="https://typer.tiangolo.com/" rel="noopener noreferrer"&gt;Typer&lt;/a&gt;&lt;/strong&gt; for the CLI. Copilot CLI was fantastic at scaffolding the command structure. I simply asked: &lt;em&gt;"Create a Typer command for 'plan' that takes a work item ID,"&lt;/em&gt; and it generated clean, type-hinted Python code instantly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Complexity Abstraction with MCP&lt;/strong&gt;&lt;br&gt;
Integrating the Model Context Protocol involves complex configuration between Node.js servers and a Python client. Copilot CLI helped me debug the JSON configuration and managed the environment variables required for the subprocesses.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Focusing on Architecture over Syntax&lt;/strong&gt;&lt;br&gt;
Because Copilot CLI handled the implementation details of the Git operations (using &lt;strong&gt;&lt;a href="https://gitpython.readthedocs.io/" rel="noopener noreferrer"&gt;GitPython&lt;/a&gt;&lt;/strong&gt;) and API calls, I was able to focus on the higher-level logic: how to effectively pass context between the "Planner" and "Developer" agents to maintain a consistent state across the SDLC.&lt;/p&gt;

&lt;p&gt;The CLI didn't just write code; it acted as a pair programmer that understood my project's goals, allowing me to build a multi-agent enterprise workflow in record time.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>Event-Driven Architecture: Do you need other service’s data in microservice architecture</title>
      <dc:creator>berkslv</dc:creator>
      <pubDate>Sat, 07 Sep 2024 14:18:25 +0000</pubDate>
      <link>https://dev.to/berkslv/event-driven-architecture-do-you-need-other-services-data-in-microservice-architecture-55ap</link>
      <guid>https://dev.to/berkslv/event-driven-architecture-do-you-need-other-services-data-in-microservice-architecture-55ap</guid>
      <description>&lt;p&gt;In applications developed with microservice architecture, domains are generally tried to be strictly separated from each other. In the example we will examine, all logic and data related to the product are located in the product service, while the organization service that manages the sales consultants who can create orders with this product also hosts its own logic and data.&lt;/p&gt;

&lt;p&gt;However, the &lt;code&gt;createUnit()&lt;/code&gt; request we will make to create a sales consultant in the organization service will need the data of the product service for validation reasons. Shouldn't the unit be given the permission to create a product that doesn't exist? In this case, the organization service will need the data of the product service, which is not in its domain and is not under its responsibility.&lt;/p&gt;

&lt;p&gt;We can access this data either synchronously or asynchronously. First, we’ll look at accessing it synchronously and the problems we may encounter, then we’ll address the potential issues with using the asynchronous method. Let’s begin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synchronous communication
&lt;/h2&gt;

&lt;p&gt;With the request we will send to our organization service via REST, we will trigger the &lt;code&gt;createUnit()&lt;/code&gt; method and create a unit. However, since this service will need product data for validation purposes, it will need to retrieve this data synchronously through an HTTP REST &lt;code&gt;getProduct()&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;During runtime, for the &lt;code&gt;createUnit()&lt;/code&gt; method to be processed, both the organization service and the product service need to be up and accessible, and there must be no issues with the network connection between them. If the product service is not operational, the organization service will also not function. Even when both services are up and accessible, if the product service is slow, the synchronous request flow will be blocked, causing the organization service to slow down as well. To overcome this issue, the organization service will need to scale during periods of high demand. However, since the product service has a runtime dependency, it will also need to be scaled in the same way to handle the large number of requests coming from the organization. If we apply this practice to all services, all services will need to scale together. As a result, the organization service will be highly dependent on the product service, and they will have to continue operating together rather than independently. If all the services in our microservice architecture become dependent on each other in this way, the inaccessibility of a single service could lead to all other services becoming inaccessible as well.&lt;/p&gt;

&lt;p&gt;During design time, if a change is made to the &lt;code&gt;getProduct()&lt;/code&gt; API in the product service, the developers of the organization service would also need to update their HTTP client integrations accordingly. This change would likely require modifying the organization service's codebase as well.&lt;/p&gt;

&lt;p&gt;In conclusion, since coupling will occur both at runtime and design time, the two services will be tightly coupled, leading to what Jonathan Tower calls a &lt;a href="https://www.youtube.com/watch?v=p2GlRToY5HI&amp;amp;t=1203s" rel="noopener noreferrer"&gt;distributed monolith&lt;/a&gt;. Any change in one service will directly affect the other, making it difficult to quickly respond to constantly changing business requirements. Any improvements made to the &lt;code&gt;getProduct()&lt;/code&gt; method in the product service would also need to be implemented by the other services that consume it. After completing these updates, all services connected synchronously must be accessible for end-users to use the application.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l1qgsyr8p7plo66duhl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0l1qgsyr8p7plo66duhl.png" alt="Synchronous communication" width="800" height="648"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a scenario where we want to guarantee an SLA to our customer, if we optimistically offer a 99.5% uptime guarantee for both the product and organization services, we are accepting that there could be up to 43 hours of downtime annually. In a scenario where the product and organization services are dependent on each other during runtime, using the calculation $0.995 * 0.995 = 0.990$, the dependency created by synchronous communication results in our services offering twice the downtime guarantee, potentially leading to 87 hours of downtime annually.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Product&lt;/th&gt;
&lt;th&gt;Organization&lt;/th&gt;
&lt;th&gt;Product &amp;amp; Organization&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uptime percentage&lt;/td&gt;
&lt;td&gt;99.5&lt;/td&gt;
&lt;td&gt;99.5&lt;/td&gt;
&lt;td&gt;99.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month&lt;/td&gt;
&lt;td&gt;716&lt;/td&gt;
&lt;td&gt;716&lt;/td&gt;
&lt;td&gt;712&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downtime in month&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Year&lt;/td&gt;
&lt;td&gt;8716&lt;/td&gt;
&lt;td&gt;8716&lt;/td&gt;
&lt;td&gt;8672&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Downtime in year&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;43&lt;/td&gt;
&lt;td&gt;87&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;So, how do we avoid this method, which can cause so many headaches? Let's look at another solution for communication between services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Asynchronous communication
&lt;/h2&gt;

&lt;p&gt;If we don’t want to choose synchronous communication, which increases inter-service dependency in every possible direction, we can proceed with the alternative: asynchronous communication. By reversing the arrows with this method, the product service publishes a domain event called &lt;code&gt;ProductCreatedEvent&lt;/code&gt; whenever there is an update in the product table. All services listening to this event update their own local &lt;code&gt;products&lt;/code&gt; tables.&lt;/p&gt;

&lt;p&gt;When the organization service needs product data, it reads from its own &lt;code&gt;products&lt;/code&gt; table. This table is unaffected by the organization's workflows and is only read from. This way, in the &lt;code&gt;createUnit()&lt;/code&gt; method, we query the product data from the same database where we save the unit data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdixewpsxz2gr1nrhc2so.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdixewpsxz2gr1nrhc2so.png" alt="Asynchronous communication" width="800" height="618"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this method, we access the product data from the organization's database in the &lt;code&gt;createUnit()&lt;/code&gt; flow, eliminating runtime dependency on the product service.&lt;/p&gt;

&lt;p&gt;By eliminating runtime dependency, we stop making synchronous queries to the product service’s &lt;code&gt;getProduct()&lt;/code&gt; endpoint. At design time, the dependency we faced while developing is also removed. After making a change in the &lt;code&gt;getProduct()&lt;/code&gt; method of the product service, the team managing the organization service no longer needs to make any changes.&lt;/p&gt;

&lt;p&gt;During design time, we only have an asynchronous dependency, and we only need to make changes when necessary. If a new column is added to the product domain model, it can be added directly to the event as a new field. If a column is removed from the product table, it can be sent with default values without being removed from the event type and marked as obsolete. Services can respond to these added or removed columns as needed or continue without making any changes.&lt;/p&gt;

&lt;p&gt;The product service does not need to care about who is processing the published event. Anyone who needs this data can consume the event, maintain their own copy of the product data, and carry on their work without having to synchronize communication with the product service. This leads to more scalable and accessible applications since they can now operate independently without depending on other services.&lt;/p&gt;

&lt;p&gt;If we worry that our tables will mix domains, we can keep tables from different domains in a separate database schema as shown in the example below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukhlgszf99co8oeo892e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fukhlgszf99co8oeo892e.png" alt="Asynchronous communication 2" width="800" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Eventual consistency
&lt;/h2&gt;

&lt;p&gt;The biggest issue that may arise from this method is eventual consistency. The update of the relevant table in the organization service may not reflect at the exact same moment a product is added to the product service. Depending on the availability of the message broker, there could be a delay of a few milliseconds or seconds.&lt;/p&gt;

&lt;p&gt;We can also explain this situation with CAP theory. If we keep the Partition tolerance leg, which is one of the 3 legs of CAP theory, constant, one of the Consistency and Availability legs will increase while the other will decrease. Therefore, we will not be able to provide these three options at the same time. Here, we need to decide according to the workflow we are working with.&lt;/p&gt;

&lt;p&gt;For example, in an e-commerce system, the "add to cart" feature might need to be highly available. If the "add to cart" feature isn’t working, receiving an error message like “please try again later” might cause customers to switch to a competitor's site. However, if we see 2 instead of 1 of the same item in our cart, we can simply adjust our cart and continue the payment process.&lt;/p&gt;

&lt;p&gt;However, the same approach may not work for hotel reservations. In contrast to the cart example, consistency is probably more critical. Returning an error message like "please try again later" is much more logical than renting out the same room to multiple customers.&lt;/p&gt;

&lt;p&gt;In conclusion, synchronous communication is suitable for workflows that need immediate consistency, while asynchronous communication is better for workflows that require high availability. Typically, in microservice architecture, high availability is preferred, as synchronous communication tightly couples all services together.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8q1y4uz6bu6ahn3xuae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx8q1y4uz6bu6ahn3xuae.png" alt="High availability vs Immediate consistency" width="800" height="290"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge cases in asynchronous communication
&lt;/h2&gt;

&lt;p&gt;If you have decided to proceed with event-driven architecture in the communication between your services, you will need to do something to ensure data consistency in the system. If a create request comes to one of our services and we publish CreatedEvent, we first update the database and then publish the event, if the transaction we execute in the database results in an error, and we publish the event without following it, or if the transaction we execute in the database results in success but the event bus cannot be accessed afterwards, the data that is distributed in our applications may fall into an inconsistent state. In order to prevent this situation, while the product service updates the product data in its own database, it also adds the relevant event to the outbox table in the same database, and then a different thread continuously scans this table and publishes the new events. Since the record we make to the database will be processed atomically, it is guaranteed that the event data will be created in the outbox table while the product data is being created. However, in an application that works as multiple instances, situations such as an event reading from the same outbox table twice and publishing it twice may be encountered. In this case, the idempotency problem already arises.&lt;/p&gt;

&lt;p&gt;If the result of a method being called once is the same as the result of multiple calls, then this is an idempotent method. In order to prevent an event from being processed multiple times due to different reasons and thus disrupting data consistency in the system, we will need to save the unique message id values ​​of the events to the database after they are consumed, and continue processing if the message id value is not in the database when a new event is to be consumed. Chris Richardson (microservices.io) also touches on this issue in his article Pattern: &lt;a href="https://microservices.io/patterns/communication-style/idempotent-consumer.html" rel="noopener noreferrer"&gt;Idempotent Consumer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa4l38294zdf3und71hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwa4l38294zdf3und71hc.png" alt="Without Outbox &amp;amp; Idempotency" width="800" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt24bzt5fxd2gkz5l3iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frt24bzt5fxd2gkz5l3iy.png" alt="Outbox &amp;amp; Idempotency" width="800" height="759"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a result, as with most solutions to problems in the field of Computer Science, we do not have a silver bullet. After considering the advantages and disadvantages of both methods in detail and in the domain we are working in, we can continue with the method we want. However, my suggestion would be to eliminate the dependency between services by using asynchronous communication whenever possible.&lt;/p&gt;

&lt;p&gt;You can access the .NET project I developed to simulate situations that may occur while working with asynchronous and synchronous data communication from the github repo below. In the example, the infrastructure provided by MassTransit was used for the outbox structure, and no special development was made for this feature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/berkslv/lecture-fetch-other-service-data-with-event-driven-architecture" rel="noopener noreferrer"&gt;GitHub - berkslv/lecture-fetch-other-service-data-with-event-driven-architecture&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=p2GlRToY5HI&amp;amp;t=1203s" rel="noopener noreferrer"&gt;Don’t Build a Distributed Monolith - Jonathan "J." Tower - NDC London 2023&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=STKCRSUsyP0" rel="noopener noreferrer"&gt;The Many Meanings of Event-Driven Architecture • Martin Fowler • GOTO 2017&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=AEbJgpamZ4w&amp;amp;t=898s" rel="noopener noreferrer"&gt;Solving distributed data problems in a microservice architecture | Microservices.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=rZxIzrjvSGg&amp;amp;t=716s" rel="noopener noreferrer"&gt;You Keep Using That Word • Sam Newman • GOTO 2023&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://microservices.io/patterns/communication-style/idempotent-consumer.html" rel="noopener noreferrer"&gt;Microservices Pattern: Pattern: Idempotent Consumer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactivemanifesto.org/en" rel="noopener noreferrer"&gt;The Reactive Manifesto&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Thank you for reading! 🎉 In order not to miss my research in the field of software development, you can follow me at &lt;a href="https://x.com/berkslv" rel="noopener noreferrer"&gt;@berkslv&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>eventdriven</category>
      <category>masstransit</category>
    </item>
  </channel>
</rss>
