<?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: Amir Sabahi</title>
    <description>The latest articles on DEV Community by Amir Sabahi (@amirsabahi).</description>
    <link>https://dev.to/amirsabahi</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%2F1220697%2F22becdc2-f5c8-4d37-b7d4-961f8926b290.jpeg</url>
      <title>DEV Community: Amir Sabahi</title>
      <link>https://dev.to/amirsabahi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/amirsabahi"/>
    <language>en</language>
    <item>
      <title>System design sample Task (Real case)</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Sun, 01 Sep 2024 17:11:22 +0000</pubDate>
      <link>https://dev.to/amirsabahi/system-design-sample-task-real-case-3i9c</link>
      <guid>https://dev.to/amirsabahi/system-design-sample-task-real-case-3i9c</guid>
      <description>&lt;p&gt;You are tasked with designing the architecture of a highly scalable and available e-commerce platform. The platform must support 5-8 million users, allow product browsing, and facilitate payments, order management, and user account management.&lt;/p&gt;

&lt;p&gt;Question:&lt;/p&gt;

&lt;p&gt;How would you design the architecture of this system to ensure scalability, high availability, and fault tolerance?&lt;br&gt;
What patterns, principles, or technologies would you use to meet these requirements?&lt;br&gt;
Answer:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;System Design Approach:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Microservices Architecture:&lt;br&gt;
Break down the system into small, decoupled services, each responsible for a specific business capability (e.g., user management, product catalog, order processing, payment handling). This allows independent scaling of services and easier maintenance. Microservices should communicate over lightweight protocols like HTTP/REST or gRPC, or via asynchronous messaging (e.g., Kafka or RabbitMQ).&lt;/p&gt;

&lt;p&gt;Load Balancing and Auto-Scaling:&lt;br&gt;
Deploy load balancers (e.g., AWS Elastic Load Balancer or NGINX) to distribute incoming traffic across multiple instances of each service. Implement auto-scaling policies (e.g., using Kubernetes or cloud providers' auto-scaling features) to dynamically adjust the number of instances based on load.&lt;/p&gt;

&lt;p&gt;Database Sharding and Replication:&lt;br&gt;
Use a combination of horizontal sharding and replication to ensure the database can scale with the number of users and transactions. For example, relational databases like MySQL or PostgreSQL can be horizontally partitioned, while NoSQL databases like MongoDB or DynamoDB can provide automatic scaling and replication.&lt;/p&gt;

&lt;p&gt;Caching:&lt;br&gt;
To reduce the load on the database and improve performance, use caching strategies. For example, implement a caching layer (e.g., Redis or Memcached) for frequently accessed data such as product details, user sessions, and inventory information.&lt;/p&gt;

&lt;p&gt;Content Delivery Network (CDN):&lt;br&gt;
Use a CDN (e.g., Cloudflare, AWS CloudFront) to serve static assets like images, CSS, and JavaScript, reducing latency for users across different regions and offloading traffic from the origin servers.&lt;/p&gt;

&lt;p&gt;Event-Driven Architecture:&lt;br&gt;
For processing asynchronous tasks (e.g., sending confirmation emails, updating inventory, or managing background jobs), use an event-driven architecture. Implement message queues (e.g., Apache Kafka or RabbitMQ) to handle events such as order creation or payment success, ensuring that these tasks are processed reliably even if some services experience downtime.&lt;/p&gt;

&lt;p&gt;Database Choice:&lt;/p&gt;

&lt;p&gt;Use a relational database (e.g., PostgreSQL or MySQL) for structured data like orders, user profiles, and transactional data.&lt;br&gt;
Use a NoSQL database (e.g., DynamoDB or MongoDB) for unstructured or semi-structured data, such as user reviews, session storage, or product metadata.&lt;br&gt;
Service Discovery and API Gateway:&lt;br&gt;
Use service discovery (e.g., Consul, Eureka) and an API Gateway (e.g., AWS API Gateway, Kong) to manage inter-service communication. The API Gateway can also handle cross-cutting concerns like authentication, authorization, rate limiting, and monitoring.&lt;/p&gt;

&lt;p&gt;High Availability and Fault Tolerance:&lt;br&gt;
Deploy services across multiple availability zones and/or regions to ensure high availability. Implement circuit breakers and retries (e.g., using Hystrix or Resilience4j) to handle failures gracefully. Use distributed tracing and logging (e.g., ELK stack, Prometheus, or Grafana) to monitor system health and troubleshoot issues.&lt;/p&gt;

&lt;p&gt;Security:&lt;br&gt;
Implement strong security practices including TLS encryption, JWT-based authentication for API calls, and role-based access control (RBAC) for user and admin access. For sensitive operations like payments, integrate with trusted third-party providers (e.g., Stripe, PayPal) and ensure that sensitive data like credit card information is handled securely (e.g., using tokenization).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Patterns, Principles, and Technologies:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Design Patterns:&lt;/p&gt;

&lt;p&gt;Service Mesh: To manage microservices communication, traffic policies, and security between services (e.g., Istio, Linkerd).&lt;br&gt;
Database Sharding and Partitioning: Split large datasets into smaller chunks for performance and scalability.&lt;br&gt;
Event Sourcing &amp;amp; CQRS (Command Query Responsibility Segregation): For separation of read and write operations to handle complex transactional workflows.&lt;br&gt;
Saga Pattern: For managing distributed transactions across multiple microservices without locking resources.&lt;br&gt;
Principles:&lt;/p&gt;

&lt;p&gt;Separation of Concerns: Keep different system functionalities modular and decoupled to ensure flexibility in scaling and maintainability.&lt;br&gt;
Fail-Fast: Design the system to quickly detect and handle failures to prevent cascading failures across the system.&lt;br&gt;
Graceful Degradation: Ensure the system continues to operate in a reduced capacity during partial failures (e.g., show cached product data when the main database is down).&lt;br&gt;
Technologies:&lt;/p&gt;

&lt;p&gt;Infrastructure: Kubernetes for container orchestration, AWS, Azure or GCP for cloud hosting, and Terraform for infrastructure as code.&lt;br&gt;
Databases: PostgreSQL or MariaDB for relational data, MongoDB for NoSQL, Redis for caching.&lt;br&gt;
CI/CD Pipeline: Jenkins or GitLab CI for automated builds, testing, and deployments.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>interview</category>
    </item>
    <item>
      <title>Part 8: Types of Coupling in Microservice Architecture</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Fri, 26 Apr 2024 08:09:25 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part-8-types-of-coupling-in-microservice-architecture-4o9a</link>
      <guid>https://dev.to/amirsabahi/part-8-types-of-coupling-in-microservice-architecture-4o9a</guid>
      <description>&lt;p&gt;Up to here, we covered the main characteristics of microservices. Short development time, cohesion, and coupling. Coupling and cohesion are strongly related and, at some level at least, are arguably the same in that both concepts describe the relationship between things. Cohesion applies to the relationship between things inside a boundary (a microservice in our context), whereas coupling describes the relationship between things across a boundary. &lt;/p&gt;

&lt;p&gt;We want to reduce coupling because it is bad. Now let's focus on coupling and see some of the available types of coupling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Domain coupling
&lt;/h2&gt;

&lt;p&gt;Domain coupling describes a situation in which one microservice needs to interact with another microservice because the first microservice needs to make use of the functionality that the other microservice provides. An example would be order processing communicates with payment and warehouse. So there is a coupling between order processing and payment and warehouse. As a general rule, domain coupling is considered to be a loose form of coupling, although even here we can hit problems. A microservice that needs to talk to lots of downstream microservices might point to a situation in which too much logic has been centralized. Domain coupling can also become problematic as more complex sets of data are sent between services—this can often point to the more problematic forms of coupling we’ll explore shortly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Temporal Coupling
&lt;/h2&gt;

&lt;p&gt;Temporal coupling refers to a situation in which one microservice needs another microservice to do something at the same time for the operation to complete. Order Processor is making a synchronous HTTP call to the Warehouse service, The Warehouse needs to be up and available at the same time the call is made. If the warehouse service is down, then the operation fails. One of the ways to avoid temporal coupling is to use some form of asynchronous communication, such as a message broker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pass-Through Coupling
&lt;/h2&gt;

&lt;p&gt;Pass-through coupling describes a situation in which one microservice passes data to another microservice purely because the data is needed by some other microservice further downstream. An example would be as follows: we have an Order Processor, which is sending a request to Warehouse to prepare an order for dispatch. As part of the request payload, we send along a Shipping Manifest. This Shipping Manifest contains not only the address of the customer but also the shipping type. The Warehouse just passes this manifest on to the downstream Shipping microservice.&lt;br&gt;
A big problem is that a change to the required data downstream can cause a more significant upstream change.&lt;br&gt;
To solve that we can directly talk to the downstream and bypass the intermediary. For example order processing talks directly to shipping micorservice. This creates more complexity since we should be sure that both warehouse and shipping do their job completely. This makes order processing heavier with more complex logic. &lt;br&gt;
Another way is to fix this issue would be to prepare shipping manifest inside the warehouse microservice. This way, order processing does not need to know if there's a change in shipping. Warehouse will handle this change. &lt;br&gt;
While this will help protect the Warehouse microservice from some changes to Shipping, there are some things that would still require all parties to change. Let’s consider the idea that we want to start shipping internationally. As part of this, the Shipping service needs a Customs Declaration to be included in the Shipping Manifest. If this is an optional parameter, then we could deploy a new version of the Shipping microservice without issue. If this is a required parameter, however, then Warehouse would need to create one. It might be able to do this with existing information that it has (or is given), or it might require that additional information be passed to it by the Order Processor.&lt;br&gt;
Although in this case we haven’t eliminated the need for changes to be made across all three microservices, we have been given much more power over when and how these changes could be made. If we had the tight (pass-through) coupling of the initial example, adding this new Customs Declaration might require a lockstep rollout of all three microservices. At least by hiding this detail we could much more easily phase deployment.&lt;br&gt;
One final way would be to send data from order processing to shipping via the warehouse, without the need for data processing by the warehouse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Coupling
&lt;/h2&gt;

&lt;p&gt;When we have two microservices using the same database, filesystem, or memory we have a common coupling. The main issue with common coupling is that changes to the structure of the data can impact multiple microservices at once.&lt;br&gt;
For example, imagine our order processing and warehouse use the same database for countries. Any backward incompatible change in the database causes issues and both microservices should change.&lt;br&gt;
Now imagine both order processing and warehouse updating the order status. If there is a finite state machine to manage states then how we should be sure that both microservices work as intended? A possible solution would be to manage the status with another microservice, which we can call order. Warehouse or Order Processor can send status update requests to the Order service. Here, the Order microservice is the source of truth for any given order. it is the job of the Order service to manage the acceptable state transitions associated with an order aggregate. As such, if the Order service received a request from Order Processor to move a status straight from PLACED to COMPLETED, it is free to reject that request if that is an invalid change. Multiple microservices making use of the same filesystem or database could overload that shared resource, potentially causing significant problems if the shared resource becomes slow or even entirely unavailable. A shared database is especially prone to this problem, as multiple consumers can run arbitrary queries against the database itself, which in turn can have wildly different performance characteristics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Content Coupling
&lt;/h2&gt;

&lt;p&gt;an external service accessing another microservice’s database and changing it directly. The differences between content coupling and common coupling are subtle. In both cases, two or more microservices are reading and writing to the same set of data. With common coupling, you understand that you are making use of a shared, external dependency. You know it’s not under your control. With content coupling, the lines of ownership become less clear, and it becomes more difficult for developers to change a system. For example, order processing uses orders to manage states, meanwhile, the warehouse manages states directly in the database. In such a case we should hope that warehouse logic and order logic behave in the same way. One possible solution is that make the warehouse use the order microservice. In short, avoid content coupling.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>microservices</category>
      <category>softwareengineering</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Part 7: Modeling Microservice</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Thu, 25 Apr 2024 14:25:31 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part-7-modeling-microservice-5351</link>
      <guid>https://dev.to/amirsabahi/part-7-modeling-microservice-5351</guid>
      <description>&lt;p&gt;In this post, we briefly talk about modeling microservices. microservices are just another form of modular decomposition one that has network-based interaction between the models and all the associated challenges that brings. Now let us delve into three concepts we talked about in previous posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Information Hiding
&lt;/h2&gt;

&lt;p&gt;Information hiding describes a desire to hide as many details as possible behind a module boundary.&lt;br&gt;
With information hiding we achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improved development time by allowing modules to be developed independently, we can allow for more work to be done in parallel and reduce the impact of adding more developers to a project.&lt;/li&gt;
&lt;li&gt;Comprehensibility
Each module can be looked at in isolation and understood in isolation. That makes the system easy to understand.&lt;/li&gt;
&lt;li&gt;Flexibility by being able to change modules independently and mix them to create new functionality.
To achieve the above characteristics, it lot depends on how the module boundaries are formed. Information hiding was a key technique to help get the most out of modular architectures, and with a modern eye, the same applies to microservices too.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cohesion
&lt;/h2&gt;

&lt;p&gt;The code that changes together, stays together. we’re optimizing our microservice architecture around the ease of making changes in business functionality—so we want the functionality grouped in such a way that we can make changes in as few places as possible. We want related behavior to sit together. If the related functionality is spread across the system, we say that cohesion is weak—whereas for our microservice architectures, we’re aiming for strong cohesion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Coupling
&lt;/h2&gt;

&lt;p&gt;The whole point of a microservice is being able to make a change to one service and deploy it without needing to change any other part of the system. This is really quite important. A loosely coupled service knows as little as it needs to about the services with which it collaborates. &lt;/p&gt;

&lt;p&gt;In the next post, we will talk deeply about coupling.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>softwareengineering</category>
      <category>learning</category>
    </item>
    <item>
      <title>Part6: Should we use Microservice</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Sun, 11 Feb 2024 14:43:50 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part6-should-we-use-microservice-24g8</link>
      <guid>https://dev.to/amirsabahi/part6-should-we-use-microservice-24g8</guid>
      <description>&lt;p&gt;As discussed in a previous post (&lt;a href="https://dev.to/amirsabahi/part-5-microservice-pain-points-2309"&gt;Part 5&lt;/a&gt;), we need to be more considerate when choosing microservice architecture. Issues like complexity, involvement of different technologies, monitoring, and scaling should be taken into account when we choose this architecture. In many cases monolith or gradual shift would be a better option. &lt;/p&gt;

&lt;p&gt;Now let's see what may make us go for or avoid microservice architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Whom microservice may not work for
&lt;/h2&gt;

&lt;p&gt;Products with many changes and in their early days. For instance startups. At first, it is tempting to go for microservice. What if our startup becomes so successful that we need to scale? But with change in the business domain and without a solid product market fit we can not go for microservice. Also, we have smaller teams, small budgets, and a short amount of time. Microservice brings complexity and a new set of works and we do not want it in a startup early on.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;When working with smaller teams with just a handful of developers, I’m very hesitant to suggest microservices for this reason.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we need to eliminate the microservice tax. That is the amount of time required for small teams to maintain and monitor the services.&lt;/p&gt;

&lt;p&gt;Another place where microservice can be avoided is when the software is developed for different customers. After all, microservice brings complexity to deployment. Your customer does not know about pods and Kubernetes at all. It will be a shock to them!&lt;/p&gt;

&lt;h2&gt;
  
  
  Where microservice may work well
&lt;/h2&gt;

&lt;p&gt;Microservice works best when we want to get our architecture and organizational boundaries right and allow teams and developers to work independently. Also, we want to avoid delivery contention.&lt;/p&gt;

&lt;p&gt;Softwares like Saas benefit from microservice architecture. You can release changes to the services independently and also scale up and down as demand changes.&lt;/p&gt;

&lt;p&gt;Microservice is technology agnostic. That means you can easily match your services with cloud providers' services.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Microservices also present clear benefits for organizations looking to provide services to their customers over a variety of new channels. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This helps an organization to provide different customer experiences over different channels.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>Part 5: Microservice Pain Points</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Wed, 31 Jan 2024 07:41:53 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part-5-microservice-pain-points-2309</link>
      <guid>https://dev.to/amirsabahi/part-5-microservice-pain-points-2309</guid>
      <description>&lt;p&gt;In the last post we saw the &lt;a href="https://dev.to/amirsabahi/part-4-advantages-of-microservice-architecture-5ecf"&gt;Advantages of Microservice Architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there are good things about microservice, there are bad things about it as well.&lt;br&gt;
Let's cover some of the summary of what Sam says in the book Building Microservice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Developer Experience
&lt;/h2&gt;

&lt;p&gt;As the number of services increases, the developer experience may be impacted, especially with resource-intensive runtimes like the JVM, limiting the number of microservices that can run on a single developer machine. Running a large system locally becomes challenging, leading to discussions on how to handle this limitation. Extreme solutions like "developing in the cloud" can be considered but may negatively affect feedback cycles. Alternatively, limiting the scope of the system a developer works on could be a more practical approach.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technology overload
&lt;/h2&gt;

&lt;p&gt;You don't need a Kubernetes cluster with just 3 services! Having lots of different technologies for microservices can be overwhelming. Some companies get excited and introduce a ton of new, alien tech when they switch to microservices. But you don't have to use every option available. It's important to balance the benefits of different technologies with the complexity they bring.&lt;/p&gt;

&lt;p&gt;The takeaway here is when you start with microservices, you'll face challenges like handling data consistency and dealing with delays. Trying to understand these challenges while also learning a bunch of new technologies can be tough. It's important to focus on gradually increasing complexity and only introducing new tech when you really need it. This helps manage the complexity and gives you time to learn better ways of doing things that might come up later. &lt;/p&gt;

&lt;h2&gt;
  
  
  Cost
&lt;/h2&gt;

&lt;p&gt;Switching to microservices might initially cost more for a few reasons. First, you'll likely need to run more things—more processes, computers, network, storage, and supporting software, leading to additional costs. Second, any change in a team or organization slows things down temporarily because it takes time to learn and adapt.&lt;/p&gt;

&lt;p&gt;If your main goal is to cut costs, microservices might not be the best choice. Microservices are more beneficial for making money by reaching more customers or developing more features at the same time. So, are microservices a way to increase profits? Maybe. Are they a way to reduce costs? Not really.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reporting
&lt;/h2&gt;

&lt;p&gt;In a monolithic system, analyzing data together is easy with a single database and a fixed schema for reports. In a microservice setup, where the schema is broken into isolated parts, reporting across all data becomes more challenging. Modern reporting methods like real-time streaming can adapt to microservices but may need new technology. Another option is publishing microservice data into central reporting databases or data lakes for reporting purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring and Troubleshooting
&lt;/h2&gt;

&lt;p&gt;Monitoring and troubleshooting in a standard monolithic application is simpler with fewer machines and a binary failure mode. In a microservice setup, understanding the impact of a single service instance going down can be challenging. While in a monolithic system, 100% CPU usage for a long time signals a big problem, it's less clear in a microservice architecture with numerous processes. &lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;In a single-process monolithic system, information stays within the process. In microservices, data moves between services over networks, making it vulnerable. Securing data in transit and protecting microservice endpoints from unauthorized access is crucial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;When testing software, there's a trade-off between the breadth of functionality covered and the challenges of setup and maintenance. End-to-end tests, which cover a lot of functionality, are powerful but can be difficult to manage. In microservice architecture, these tests become even more complex, spanning multiple processes and requiring extensive setup. As your microservices grow, the returns on investing in end-to-end testing diminish, leading to the exploration of alternative testing approaches like contract-driven testing, testing in production, and progressive delivery techniques. Later you can use parallel run or canary release methods.&lt;/p&gt;

&lt;p&gt;What is canary release: &lt;br&gt;
A canary release is a deployment strategy where a new version of the software is gradually rolled out to a small subset of users or servers before being made available to the entire user base. This approach allows for testing the new release in a real-world environment with reduced risk, as any issues or bugs can be identified and addressed before a full-scale release.&lt;/p&gt;

&lt;h2&gt;
  
  
  Latency
&lt;/h2&gt;

&lt;p&gt;In a microservice setup, tasks that used to be handled locally on one computer might now be spread across different microservices. This involves sending information over networks, making the system slower. Measuring the impact on speed during the design or coding phase is tricky, so it's essential to make changes gradually and measure their effects. You need to know how much latency is acceptable in your services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data consistency
&lt;/h2&gt;

&lt;p&gt;Moving from a single-database monolithic system to a distributed setup with different databases managed by various processes poses challenges in ensuring data consistency. Unlike the past reliance on database transactions, maintaining similar safety in a distributed system is complex, and distributed transactions often prove problematic. Concepts like sagas are important to use. Gradual decomposition of your application allows you to assess the impact of architectural changes in a more controlled manner.&lt;/p&gt;

&lt;p&gt;What is Saga&lt;br&gt;
A saga is a design pattern for managing a long-running and complex transaction that involves multiple steps or services. Instead of relying on traditional distributed transactions, which can be challenging to implement and scale, a saga breaks down the transaction into a series of smaller, more manageable steps.&lt;/p&gt;

&lt;p&gt;Each step in the saga corresponds to a specific action or operation, and the overall saga is coordinated to ensure that all steps either succeed or fail together. If a failure occurs at any step, compensating transactions are used to undo the completed steps and maintain a consistent state.&lt;/p&gt;

&lt;p&gt;Sagas helps address the challenges of distributed transactions by providing a more scalable and flexible approach to managing transactions across multiple services in a distributed system.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>learning</category>
    </item>
    <item>
      <title>Part 4: Advantages of Microservice Architecture</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Fri, 26 Jan 2024 14:24:28 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part-4-advantages-of-microservice-architecture-5ecf</link>
      <guid>https://dev.to/amirsabahi/part-4-advantages-of-microservice-architecture-5ecf</guid>
      <description>&lt;p&gt;Now that we know more about monolith and microservice and we understood more about the characteristics of microservice let's see the advantages associated with it.&lt;/p&gt;

&lt;p&gt;If you have not read the previous parts here is the table of contents to go back and read more about microservice fundamentals.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/amirsabahi/microservice-desing-fundamentals-2i54"&gt;Part1: Microservice Desing: Fundamentals&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/amirsabahi/microservice-desing-the-monolith-part-2-j9l"&gt;Part2: Microservice Desing: The Monolith&lt;br&gt;
&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/amirsabahi/part-3-key-technologies-in-adopting-microservice-architecture-3med"&gt;Part 3: Key technologies in adopting Microservice architecture&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Microservices have many benefits of distributed systems however with the use of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Information hiding&lt;/li&gt;
&lt;li&gt;Domain-driven design&lt;/li&gt;
&lt;li&gt;distributed systems
we have more benefits than any distributed system architecture. &lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Technology Heterogeneity&lt;br&gt;
Microservice brings a versatile approach to technology, allowing different services to use diverse technologies suitable for their specific needs. So you can pick different technologies and even data storage for each service. For example, for a social media service, you can use a graph database and a RDBMS for other services. In addition to that, microservice offers adaptability. You can opt for different programming languages or frameworks on one service without breaking the whole system. This capability is not available in the case of monolith design. Of course, this comes with some challenges. That is why many companies put some constraints on technology choices. However, information hiding makes it possible to change part of the system without affecting other parts of the system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Robustness&lt;br&gt;
Imagine parts of your system can fail, but if this failure does not spread, you can contain the issue, and the rest of the system keeps working. This is called the bulkhead concept. With microservice failure of one service may not affect the whole system.  This is what we do not have in the case of the monolith. If something goes wrong in the monolith, the whole system will be down. Even though we can use replication to eliminate the risk to some degree. Embracing this concept means we need to know what causes failures in distributed systems. Without knowing this or neglecting it, we have a less robust system after migration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scaling&lt;br&gt;
In monolith systems, we need to scale everything all together. You can not scale a subsystem alone. Microservice offers a solution by allowing us to scale specific services as needed. This enables efficient scaling of the system. For example, Gilt online retailer faced scalability issues with monolith setup. They did transition to microservice and now run over 450 services on multiple machines. With on-demand provisioning systems like AWS, microservices enable cost-effective scaling, aligning architectural choices with immediate cost savings. Microservices provide an adaptable approach to scaling applications, offering targeted scalability and improved resource utilization. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ease of Deployment&lt;br&gt;
In a monolithic application, a small code change requires deploying the entire system, leading to infrequent, high-risk releases due to accumulated changes. Microservices, however, enable independent deployment of individual services, allowing faster and safer releases with quick issue isolation. This approach, favored by companies like Amazon and Netflix, aims to streamline software delivery by minimizing obstacles and accelerating the introduction of new functionality to customers.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;5- Organizational Alignment&lt;br&gt;
Microservices address challenges linked to large, distributed teams and codebases by promoting smaller teams and codebases, enhancing productivity. This architecture enables better alignment between organizational structure and codebase, facilitating adjustments in service ownership as the organization evolves, and ensuring a sustained harmony between architecture and organization.&lt;/p&gt;

&lt;p&gt;6- Composable&lt;br&gt;
Microservices enhance composability by offering reusable functionality in diverse ways for different purposes. In addition, microservices enable the opening up of system seams, allowing external parties to address them, and facilitating adaptable application development based on changing circumstances. In contrast, monolithic applications with coarse-grained seams lack such flexibility and require more disruptive changes.&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Part 3: Key technologies in adopting Microservice architecture</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Wed, 24 Jan 2024 10:12:05 +0000</pubDate>
      <link>https://dev.to/amirsabahi/part-3-key-technologies-in-adopting-microservice-architecture-3med</link>
      <guid>https://dev.to/amirsabahi/part-3-key-technologies-in-adopting-microservice-architecture-3med</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/amirsabahi/microservice-desing-the-monolith-part-2-j9l"&gt;last post, we talked about Monolith architecture (Part 2)&lt;/a&gt;. Now we want to talk about technologies that enable microservice briefly.&lt;/p&gt;

&lt;p&gt;In adopting microservices, a cautious and gradual approach to incorporating new technologies is advised. The initial focus should be on identifying issues stemming from the evolving distributed system and then exploring technologies that can effectively address those challenges. This process demands a comprehensive understanding of the supporting technologies, eroding traditional distinctions between logical and physical architecture.&lt;/p&gt;

&lt;p&gt;Key technologies that play a crucial role in successful microservices implementation include &lt;strong&gt;log aggregation&lt;/strong&gt; and &lt;strong&gt;distributed tracing&lt;/strong&gt;. Log aggregation systems, such as Humio or services offered by public cloud vendors, facilitate centralized log analysis, enhancing troubleshooting and monitoring capabilities. Distributed tracing tools like Jaeger are instrumental in navigating the complexities of a growing system, allowing for efficient exploration and problem-solving across multiple services.&lt;/p&gt;

&lt;p&gt;Containers, particularly managed by orchestration platforms like Kubernetes, provide essential benefits in terms of isolated execution environments. They ensure that issues in one microservice instance do not impact others, allowing for faster spin-up times and cost-effective resource utilization. Apache Kafka emerges as a pivotal choice for streaming data in microservices, offering features like message permanence, compaction, and scalability to handle large volumes of messages.&lt;/p&gt;

&lt;p&gt;Public cloud providers, including Google Cloud, Microsoft Azure, and Amazon Web Services (AWS), offer an extensive array of managed services and deployment options. Leveraging these services becomes increasingly beneficial as the complexity of the microservices architecture grows. Notably, serverless offerings, falling under the umbrella of public cloud services, present an attractive proposition. These products abstract the underlying infrastructure, allowing developers to work at a higher level of abstraction. Function as a Service (FaaS) platforms, a subset of serverless, simplify deployment by handling code instances on demand, eliminating the need to worry about server provisioning.&lt;/p&gt;

&lt;p&gt;This comprehensive suite of technologies forms the backbone of a successful microservices architecture. Carefully integrating these technologies ensures a robust and scalable microservices ecosystem, enabling organizations to navigate the intricacies of distributed systems effectively. We will talk more about these topics in subsequent posts.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>learning</category>
    </item>
    <item>
      <title>Part2: Microservice Desing: The Monolith</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Sat, 20 Jan 2024 09:08:15 +0000</pubDate>
      <link>https://dev.to/amirsabahi/microservice-desing-the-monolith-part-2-j9l</link>
      <guid>https://dev.to/amirsabahi/microservice-desing-the-monolith-part-2-j9l</guid>
      <description>&lt;p&gt;In the &lt;a href="https://dev.to/amirsabahi/microservice-desing-fundamentals-2i54"&gt;first part&lt;/a&gt;, we talked about microservice and its implications on the business domain. When we talk about Microservice, inevitably we must mention the term monolith. This post is about the monolith and its types. Should we start with a monolith or go for microservice right away? In my experience, working in different startups I would go with monolith if I want to deliver a fast MVP. But let's talk about it deeper to better understand the concept.&lt;/p&gt;

&lt;p&gt;The Monolith is a system that is deployed all together. It is the opposite of microservice independent deployment principle. So If you have microservices that you must deploy all together, you have a monolith. Now let's visit different types of monolith.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Single-Process Monolith
&lt;/h2&gt;

&lt;p&gt;The most common type of monolith is a single-process monolith. It is a code that is deployed as a single process. The main characteristic is that they use a single database to read and write. This architecture makes sense for smaller organizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Modular Monolith
&lt;/h2&gt;

&lt;p&gt;When a single-process has separate modules. we call it a modular monolith. It can use a single database. The main problem is that the database lacks decomposition. But to make modules independent we can decompose the database the same as modules. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shopify is a great example of an organization that has used this technique as an alternative to microservice decompo‐ sition, and it seems to work really well for that company.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Distributed Monolith
&lt;/h2&gt;

&lt;p&gt;A distributed monolith is a system composed of multiple services, but unlike true service-oriented architecture (SOA), it necessitates deploying the entire system as a single unit. Despite technically fitting the SOA definition, distributed monoliths often fall short of delivering the advantages promised by SOA. In practical terms, they inherit the drawbacks of both distributed systems and single-process monoliths without fully embracing the benefits of either. Distributed monoliths commonly arise due to insufficient emphasis on principles like information hiding and business functionality cohesion where seemingly local changes have far-reaching effects, breaking other components of the system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Disadvantage of Monolith
&lt;/h2&gt;

&lt;p&gt;1- Single database: Using a single database, especially in a single process monolith.&lt;br&gt;
2- deployment of a large system altogether: This makes the deployment a tedious and error-prone task.&lt;br&gt;
3- Difficult testing: It can be a hard and time-consuming task to test when one part of the application changes.&lt;br&gt;
4- Delivery contention: Multiple teams work on single code and this creates a delivery contention.&lt;br&gt;
5- Large systems can not be scaled in monolith easily&lt;/p&gt;

&lt;h2&gt;
  
  
  Advantages of Monolith
&lt;/h2&gt;

&lt;p&gt;Monoliths, including single-process or modular monoliths, offer a range of advantages, simplifying deployment topology and mitigating challenges linked with distributed systems. They provide streamlined developer workflows and simplify activities like monitoring and troubleshooting. Additionally, code reuse within a monolith is straightforward, eliminating the complexities of deciding how to share code in a distributed system. Monolith should not be considered as legacy system and it is a valid choice for many scenarios.&lt;/p&gt;

&lt;p&gt;In the next post, we talk about the advantages of microservice.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/amirsabahi/microservice-desing-fundamentals-2i54"&gt;Read previous post: the fundamentals here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>learning</category>
    </item>
    <item>
      <title>Part1: Microservice Desing: Fundamentals</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Thu, 18 Jan 2024 14:30:02 +0000</pubDate>
      <link>https://dev.to/amirsabahi/microservice-desing-fundamentals-2i54</link>
      <guid>https://dev.to/amirsabahi/microservice-desing-fundamentals-2i54</guid>
      <description>&lt;p&gt;Software engineering is about creating services and infrastructure to serve the needs of a group of people. We create services and we solve business problems through software engineering. As software engineers designing systems and architecture of software are the main part of our job. It is not just about coding but how we will put a system together so that we can maintain and scale it further. Now imagine we want to break the system into smaller services. So a single monolith service breaks down into small services We call it a microservice.&lt;/p&gt;

&lt;p&gt;Since many mainstream software companies use this architecture I decided to create a series of posts about microservices and mainly I refer to the book Building Microservices by Sam Newman. I follow the book mainly because it gives a nice round map. And also we add some more information to it.&lt;/p&gt;

&lt;p&gt;Let's begin by understanding the fundamentals of microservice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is mircoservice?
&lt;/h2&gt;

&lt;p&gt;A microservice is a small, independently deployable, and scalable software component that encapsulates a specific business capability. Microservice is molded around the business domain. It operates as a modular unit within a larger system, communicating with other microservices through well-defined interfaces (say APIs) over a network. Microservices are designed to be flexible, allowing developers to work on, deploy, and update them independently, contributing to a software system's overall agility and scalability. Being independent is a key. &lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Imagine a Marketing SaaS (Software as a Service) platform that traditionally handles various marketing domains within a monolithic structure. In a microservices architecture, these functions can be separated into individual microservices, each responsible for a specific aspect of marketing(or business domains):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Campaign Management Microservice:
Manages the creation, scheduling, and monitoring of marketing campaigns.
Exposes APIs for creating new campaigns and retrieving campaign analytics.&lt;/li&gt;
&lt;li&gt;Email Marketing Microservice:
Handles the email marketing component of the platform.
Manages subscriber lists, sends out emails, and tracks email engagement metrics.&lt;/li&gt;
&lt;li&gt;Analytics Microservice:
Collects and analyzes data related to user interactions with marketing content.
Provides insights into the effectiveness of campaigns.
User Authentication Microservice:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each microservice is treated as a black box. We can say it is a service-oriented architecture. Each service exposes APIs and other services that use the functionality of the service. &lt;/p&gt;

&lt;p&gt;One important aspect is that internal implementation from the technology to where data is stored is hidden from the outside world. &lt;strong&gt;That means each microservice (in most cases) will have its own database.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;another important aspect is that microservice uses information hiding. It means It exposes as little as possible via the external interface and keeps the much of information inside. This gives each service the power of controlling on what can be changed and what can not be modified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is Microservice a service-oriented architecture?
&lt;/h2&gt;

&lt;p&gt;Microservice is a specific approach for SOA in the same way that Extreme Programming (XP) or Scrum is a specific approach for Agile software development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key concepts of microservice
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Independent deployability&lt;br&gt;
Make changes to one microservice and deploy it into production without having to deploy anything else. It is the key point.&lt;br&gt;
So we should make microservices loosely coupled. That means Minimal dependencies, independent operation, and ease of modification between system components. That is why sharing the database is not a good idea at all.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Shaped around a business domain&lt;br&gt;
Techniques like domain-driven design help structure code to mirror the real-world domain. In microservice architectures, the same idea is applied to define service boundaries around business domains.&lt;br&gt;
This makes it easier to roll out new functionality and allows flexible recombination of microservices for delivering new features.&lt;br&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%2Fmve8qkp8aegcwik8ic2h.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%2Fmve8qkp8aegcwik8ic2h.png" alt="Image description" width="475" height="326"&gt;&lt;/a&gt;&lt;br&gt;
Implementing features requiring changes in multiple microservices is costly.&lt;br&gt;
Our goal should be minimizing cross-service changes to streamline development efforts.&lt;br&gt;
Layered architectures, such as three-tiered structures, often have each layer representing a service boundary.&lt;br&gt;
Changes in functionality often span multiple layers, complicating the development process. For example, a change in backend needs a change in fronend too.&lt;br&gt;
Efficiency in making changes is slowed, especially in highly layered architectures.&lt;br&gt;
Microservices prioritize arranging services as end-to-end slices of business functionality.&lt;br&gt;
Aims to make changes to business functionality more efficient by avoiding technical functionality layers.&lt;br&gt;
Emphasis on high cohesion of business functionality over high cohesion of technical functionality in a microservices architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Owning their own state&lt;br&gt;
The challenge often faced in adopting microservices lies in the notion that shared databases should be avoided. Instead of one microservice accessing the data of another through a shared database, microservices should directly request the needed information. This approach allows microservices to independently determine what is shared and what remains hidden. To achieve true independent deployability, minimizing backward-incompatible changes is crucial. Analogous to encapsulation in object-oriented programming, hiding internal state in microservices contributes to information hiding. This encapsulation of data, including user interface, business logic, and underlying databases, promotes high cohesion of business functionality and reduces coupling, aligning to make changes to business-related functionality more efficient.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Size&lt;br&gt;
Chris Richardson, the author of Microservice Patterns (Manning Publications), once said—that the goal of microservices is to have “as small an interface as possible.” That aligns with the concept of information hiding again, but it does represent an attempt to find meaning in the term “microservices” that wasn’t there initially. So we need to keep the size as small and as meaningful as possible and expose the data necessary to keep the cohesion of the microservices. After all, size is not that important.&lt;br&gt;
The two most important things here are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many microservices can we handle? If you want to move to microservice and keep the complexity arising, manageable, migrate to microservice incrementally. &lt;/li&gt;
&lt;li&gt;How do you define microservice boundaries to get the most out of them, without everything becoming a coupled mess?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Alignment of Architecture and business
&lt;/h2&gt;

&lt;p&gt;MusicCorp (a real company with an imaginary name), an online CD-selling ecommerce company, currently operates with a traditional three-tiered architecture, consisting of a web-based UI, a monolithic backend for business logic, and a traditional database. The architecture aligns with how teams were traditionally organized based on core competencies, resulting in high cohesion of related technology but low cohesion of business functionality. However, as expectations around software development have changed, the company aims to transition into a more agile and efficient model.&lt;/p&gt;

&lt;p&gt;The three-tiered architecture is optimized around familiarity and how teams were historically organized. Conway's law, which states that system designs mirror communication structures within organizations, is evident in this architecture. To adapt to changing forces and align with current practices, the company explores an alternative microservices architecture organized along vertical business lines. This approach involves dedicated teams responsible for end-to-end changes in specific business functionalities, enhancing the cohesion of business functionality rather than technology. The introduction of stream-aligned teams, as described in the book Team Topologies, becomes a key concept, emphasizing teams' empowerment to deliver customer value independently. This shift towards microservices and stream-aligned teams aims to facilitate quicker, safer, and more aligned development and organizational structures.&lt;/p&gt;

&lt;p&gt;In the next post, we will talk more about monolith and microservice fundamentals. &lt;/p&gt;

&lt;p&gt;Stay Tuned!&lt;/p&gt;

&lt;p&gt;Photo by Omar Flores on Unsplash&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>architecture</category>
      <category>learning</category>
    </item>
    <item>
      <title>Architecture design: Crypto Exchange example</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Sun, 07 Jan 2024 07:31:06 +0000</pubDate>
      <link>https://dev.to/amirsabahi/architecture-design-crypto-exchange-example-20ce</link>
      <guid>https://dev.to/amirsabahi/architecture-design-crypto-exchange-example-20ce</guid>
      <description>&lt;p&gt;Designing systems is fun. That is why I decided to design a system for an imaginary crypto exchange called BitEx.&lt;br&gt;
Let's take a look at the architecture. For that, we start with explaining the microservice. My language of choice is C# and Typescirpt but it does not matter much.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Microservices Architecture:&lt;br&gt;
User Service:&lt;br&gt;
Implementation: Develop using a framework like Django(Python), .Net(C#) or Spring (Java).&lt;br&gt;
Functionality:&lt;br&gt;
User registration, authentication, and authorization.&lt;br&gt;
User profile management.&lt;br&gt;
Order Service:&lt;br&gt;
Implementation: Utilize a technology stack such as Node.js with Express or Django (Python).&lt;br&gt;
Functionality:&lt;br&gt;
Order creation, modification, and cancellation.&lt;br&gt;
Validation of order parameters.&lt;br&gt;
Market Service:&lt;br&gt;
Implementation: Use a language like Go, C#, or Java with Spring Boot.&lt;br&gt;
Functionality:&lt;br&gt;
Real-time market data retrieval.&lt;br&gt;
Trading pair information.&lt;br&gt;
Execution Service:&lt;br&gt;
Implementation: Develop using a language suitable for low-latency processing (e.g., Go).&lt;br&gt;
Functionality:&lt;br&gt;
Execution of matched orders.&lt;br&gt;
Account balance updates.&lt;br&gt;
Notification Service:&lt;br&gt;
Implementation: Choose a lightweight framework like Django (Python) or Express (Node.js).&lt;br&gt;
Functionality:&lt;br&gt;
Publishing order status changes.&lt;br&gt;
Real-time notifications to users.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Message Queue (Kafka):&lt;br&gt;
Implementation:&lt;br&gt;
Set up Kafka clusters using Apache Kafka or use a managed service like Azure Event Hubs.&lt;br&gt;
Create Kafka topics for User Events, Order Events, and Market Events.&lt;br&gt;
Use Kafka producers and consumers in microservices to publish and subscribe to events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Database Management:&lt;br&gt;
MySQL Database:&lt;br&gt;
Implementation: Set up MySQL instances or use Azure Database for MySQL.&lt;br&gt;
Functionality:&lt;br&gt;
Store user account information.&lt;br&gt;
Persist order details.&lt;br&gt;
Support transactions for atomic operations.&lt;br&gt;
Redis:&lt;br&gt;
Implementation: Deploy Redis instances or use Azure Cache for Redis.&lt;br&gt;
Functionality:&lt;br&gt;
Caching user sessions for quick authentication.&lt;br&gt;
Pub/Sub for real-time communication.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker Containers and Kubernetes:&lt;br&gt;
Implementation:&lt;br&gt;
Containerize microservices using Docker.&lt;br&gt;
Use Kubernetes for container orchestration, managing deployments, and scaling.&lt;br&gt;
Implement Kubernetes ConfigMaps and Secrets for configuration management.&lt;br&gt;
Functionality:&lt;br&gt;
Efficient scaling with Kubernetes Horizontal Pod Autoscaler.&lt;br&gt;
Rolling updates and rollback capabilities.&lt;br&gt;
Load balancing across microservice instances.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Load Balancing:&lt;br&gt;
Implementation:&lt;br&gt;
Utilize Azure Load Balancer to distribute traffic.&lt;br&gt;
Configure load balancing rules for each microservice.&lt;br&gt;
Functionality:&lt;br&gt;
Evenly distribute incoming requests to maintain high availability.&lt;br&gt;
Handle automatic failover in case of node failures.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security (Azure):&lt;br&gt;
Azure Active Directory (AAD):&lt;br&gt;
Implementation: Integrate microservices with AAD for user authentication.&lt;br&gt;
Functionality:&lt;br&gt;
Secure user authentication and authorization.&lt;br&gt;
Azure Key Vault:&lt;br&gt;
Implementation: Use Azure Key Vault for managing secrets and sensitive information.&lt;br&gt;
Functionality:&lt;br&gt;
Secure storage of API keys, passwords, and encryption keys.&lt;br&gt;
Azure Security Center:&lt;br&gt;
Implementation: Enable Azure Security Center for threat detection.&lt;br&gt;
Functionality:&lt;br&gt;
Continuous monitoring and threat detection.&lt;br&gt;
Automated responses to security incidents.&lt;br&gt;
Azure Network Security Groups (NSG):&lt;br&gt;
Implementation: Configure NSGs to control traffic between microservices.&lt;br&gt;
Functionality:&lt;br&gt;
Control inbound and outbound traffic to enhance security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Monitoring and Logging:&lt;br&gt;
Azure Monitor:&lt;br&gt;
Implementation: Integrate microservices with Azure Monitor.&lt;br&gt;
Functionality:&lt;br&gt;
Real-time monitoring of application performance and availability.&lt;br&gt;
Set up alerts for critical events.&lt;br&gt;
Application Insights:&lt;br&gt;
Implementation: Add Application Insights for detailed performance monitoring.&lt;br&gt;
Functionality:&lt;br&gt;
Code-level insights and diagnostics.&lt;br&gt;
Tracing requests across microservices.&lt;br&gt;
Azure Log Analytics:&lt;br&gt;
Implementation: Configure microservices to send logs to Azure Log Analytics.&lt;br&gt;
Functionality:&lt;br&gt;
Centralized logging for easy troubleshooting.&lt;br&gt;
Custom queries and analysis of log data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scalability:&lt;br&gt;
Azure Kubernetes Service (AKS):&lt;br&gt;
Implementation: Use AKS for managed Kubernetes clusters.&lt;br&gt;
Functionality:&lt;br&gt;
Automatic scaling based on resource usage.&lt;br&gt;
Efficient resource utilization and cost management.&lt;br&gt;
Azure Container Registry (ACR):&lt;br&gt;
Implementation: Store Docker container images in ACR(Azure Container Registry).&lt;br&gt;
Functionality:&lt;br&gt;
Secure and managed storage of container images.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fault Tolerance:&lt;br&gt;
Azure Availability Zones:&lt;br&gt;
Implementation: Deploy microservices across Azure Availability Zones.&lt;br&gt;
Functionality:&lt;br&gt;
High availability and redundancy.&lt;br&gt;
Minimize downtime in case of failures.&lt;br&gt;
Azure Backup:&lt;br&gt;
Implementation: Set up Azure Backup for regular backups of databases.&lt;br&gt;
Functionality:&lt;br&gt;
Data recovery in case of accidental deletions or data corruption.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Testing:&lt;br&gt;
Implementation:&lt;br&gt;
Utilize testing frameworks for unit testing (e.g., JUnit, pytest).&lt;br&gt;
Set up automated integration tests and stress tests.&lt;br&gt;
Functionality:&lt;br&gt;
Ensure the reliability and correctness of microservices.&lt;br&gt;
Identify and fix performance bottlenecks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Compliance:&lt;br&gt;
Implementation:&lt;br&gt;
Regularly audit and update security configurations to comply with industry standards.&lt;br&gt;
Collaborate with legal and compliance teams to address regulatory requirements.&lt;br&gt;
Functionality:&lt;br&gt;
Periodic security and compliance audits are a must. Especially having regular security checks using bounty programs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now let's estimate the system capacity.&lt;/p&gt;

&lt;p&gt;Estimating User Handling Capacity:&lt;br&gt;
User Service:&lt;br&gt;
Suppose the User Service can handle 500 user registrations/authentication requests per second.&lt;br&gt;
Therefore, it can handle 500×60=30,000 user-related transactions per minute.&lt;br&gt;
Order Service:&lt;/p&gt;

&lt;p&gt;Assume the Order Service can process 1,000 order-related transactions per second.&lt;br&gt;
This results in &lt;br&gt;
1,000×60=60,000 order-related transactions per minute.&lt;br&gt;
Market Service:&lt;/p&gt;

&lt;p&gt;Assume the Market Service can provide market data for 800 requests per second.&lt;br&gt;
Thus, it can handle 800×60=48,000 market-related transactions per minute.&lt;br&gt;
Execution Service:&lt;/p&gt;

&lt;p&gt;Suppose the Execution Service can execute 700 matched orders per second.&lt;br&gt;
This translates to 700×60=42,000 matched order transactions per minute.&lt;/p&gt;

&lt;p&gt;Notification Service:&lt;br&gt;
Assume the Notification Service can handle 600 notification events per second.&lt;br&gt;
Consequently, it can handle 600×60=36,000 notification events per minute.&lt;br&gt;
Total User Handling Capacity:&lt;br&gt;
The overall user handling capacity of the system per minute is the minimum of the capacities of the individual services since the system is only as fast as its slowest component.&lt;/p&gt;

&lt;p&gt;Finally the total capacity would be the minimum ofcapacities of the system which is 30,000&lt;/p&gt;

&lt;p&gt;Total Capacity=min(30,000,60,000,48,000,42,000,36,000)&lt;/p&gt;

&lt;p&gt;In this example, the total user handling capacity per minute is 30,000 transactions. This estimation helps understand the system's potential load and can guide decisions related to scaling, optimization, and capacity planning. For example we can see that our registration and authorization service capacity is 30,000. So we need to plan if we are going to have a heavy marketing campaign.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>softwareengineering</category>
      <category>webdev</category>
      <category>learning</category>
    </item>
    <item>
      <title>Technical Debt: the remedy</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Wed, 27 Dec 2023 13:09:48 +0000</pubDate>
      <link>https://dev.to/amirsabahi/technical-debt-the-remedy-4fkf</link>
      <guid>https://dev.to/amirsabahi/technical-debt-the-remedy-4fkf</guid>
      <description>&lt;p&gt;Technical debt is inevitable. We always have it around. Yet, we can keep it as low as possible especially when we work in startups or projects with tight schedules. After all, technical debt has a direct impact on the business goals and performance. Special we would expect fast delivery in major products with high competition or in startups with delimited resources. It is so common to neglect technical debt. As if it was not there at all. However, we know that we will reach the point which we have to pay back. Do not get me wrong here. Having a technical debt isn't bad. The issue here is not looking at it the right way. In fact, ignoring it.&lt;/p&gt;

&lt;p&gt;Here I introduce some of my observations and personal experience on dealing with technical debt. I do not want this blog to be long. Rather I want to graze over the topic.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Understand the debt you need to pay back&lt;br&gt;
Not every issue, bug, or improvement should be and can be handled. Instead, try to prioritize them around business needs, the impact they make, and the amount of work they need. For example, changing a message broker in the system is a technical debt. However, we can ask if we can delay it for a month, three months, or even six months. The main concern is to see debt and decide when and how to address it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understand the business domain:&lt;br&gt;
As technical people, sometimes we forget why we are creating software or pieces of functionality. This can lead to two things. One is the stream of tasks and requests from the other teams, and the second is the contrary. Working on a component for a long time and keeping everyone waiting. By understanding the business you can negotiate with managers and feature-hungry domains within the organization&lt;br&gt;
For example in a trading system, the client asks for a feature for buying options. Without knowing about the business and its criticality you can not decide whether to keep it for the future or deliver it very fast.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Categorize the debt and decide which one is a do-or-die&lt;br&gt;
I use the Reforg blog as a reference to types of debt, however, you can modify them any way you want.&lt;br&gt;
The 6 key types of technical debt that teams encounter are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stability debt&lt;/li&gt;
&lt;li&gt;Security debt&lt;/li&gt;
&lt;li&gt;Maintenance debt&lt;/li&gt;
&lt;li&gt;Developer efficiency debt&lt;/li&gt;
&lt;li&gt;Technical product debt&lt;/li&gt;
&lt;li&gt;Decision debt
Now based on the categories mentioned decide if the technical debt is a priority or not. For example, you know there is governance regulation imposed regarding the security. So If you have to fix a security or you have to work on database stability, for example, you need to do the security patch first. It sounds no-brainer, nonetheless, in a day-to-day job if do not have a clear categorization, you or your managers may miss the debt. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Zoom out and focus on software architecture early on&lt;br&gt;
A good architecture can reduce many stability, maintenance, deployability, and flexibility issues. As a result, you may face nominal debts. For example, changing from cloud to in-house servers can be costly. So we can work more on such decisions. We must keep in mind that, we may start simple and later expand the work as per our need. For example, there is nothing wrong if we do not start with domain domain-driven design or CQRS pattern. But it is important to know 6 months or one year from now what we should expect. If you are planning to move into microservice, you must plan early. Even a mature startup company may overhaul its architecture to answer new business challenges. This kind of technical debt is always present itself while your system grows. The important point is how prepared we will be to tackle the challenge.  &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Setup a Continuous Integration and Testing&lt;br&gt;
When it comes to handling technical debt, continuous integration and testing are like superheroes for developers. They act as a shield against accumulating technical issues. Imagine automated testing as your trusty sidekick in CI/CD pipeline—detecting and fixing problems early on and ensuring new changes blend seamlessly with existing code. This dynamic duo not only prevents the growth of technical debt but also boosts the overall stability and reliability of our software. By giving importance to continuous integration and testing, teams can create a culture of quality assurance, keeping projects on track and avoiding long-term headaches.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I hope you take some points from my experience. Curious to know your thoughts. Please comment below on what you think about the technical dept.&lt;/p&gt;

</description>
      <category>softwareengineering</category>
      <category>agile</category>
    </item>
    <item>
      <title>Learn from Source: Master Testing in Django</title>
      <dc:creator>Amir Sabahi</dc:creator>
      <pubDate>Tue, 26 Dec 2023 14:06:43 +0000</pubDate>
      <link>https://dev.to/amirsabahi/learn-from-source-master-testing-in-django-16gn</link>
      <guid>https://dev.to/amirsabahi/learn-from-source-master-testing-in-django-16gn</guid>
      <description>&lt;p&gt;Testing is a fundamental part of the development. We test to find bugs, and one of the places we often need testing is database queries. While working and learning from the Django core repository, I encountered different unit test cases. They test raw queries. In this blog post, we will delve into two specific Django test methods that highlight some interesting unit tests: passing optional query parameters and understanding the lazy nature of raw queries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Optional Query Parameters Test:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Understanding the Test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's first revisit the test_params Django test method, which is designed to evaluate the handling of optional query parameters. The test focuses on passing parameters to a raw SQL query and performing assertions to validate the correctness of the results.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wIjVaT7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uewzi3mdzo63buwgs30e.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wIjVaT7l--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uewzi3mdzo63buwgs30e.jpeg" alt="Image description" width="800" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's break down the assertions to understand them better:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertProcessed(Author, results, [author]):&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This assertion ensures that the raw SQL query results (results) have been processed correctly for the Author model.&lt;br&gt;
The Author model and the expected list of authors ([author]) are passed as arguments.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertNoAnnotations(results):&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This assertion verifies that there are no annotations present in the raw SQL query results. Annotations in Django are additional metadata associated with query results. For example number of entries.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertEqual(len(results), 1):&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This assertion checks that the length of the results list is equal to 1. It ensures that the raw SQL query returns exactly one result, as expected.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertIsInstance(repr(qset), str):&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
This assertion confirms that the representation of the query set (qset) is an instance of a string (str). This is a useful check to ensure that the query set can be represented as a string.&lt;/p&gt;

&lt;p&gt;Attention to use of repr built-in function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;repr(object)&lt;br&gt;
Return a string containing a printable representation of an object.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Lazy Raw Queries Test:
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Introducing the Test:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In addition to testing optional query parameters, Django developers must be aware of the lazy nature of raw queries. The test_raw_query_lazy method explores this characteristic, emphasizing that raw queries are not executed until they are iterated over. the last line is the key to understanding this code. Take a look at the code below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tWwxYF_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbjb7v7pzw77cv0wcss7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tWwxYF_A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fbjb7v7pzw77cv0wcss7.jpeg" alt="Image description" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Breaking Down the Test Steps and Assertions:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;q = Author.objects.raw("SELECT * FROM raw_query_author"):&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This line defines a raw SQL query using Author.objects.raw(). Importantly, the query is not executed at this stage.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertIsNone(q.query.cursor):&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This assertion checks that the raw SQL query has not been executed initially. It does so by verifying that the cursor attribute of the query is None.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;list(q):&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This line triggers the execution of the raw SQL query by iterating over it using the list() function. This is the point at which the lazy execution occurs.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;self.assertIsNotNone(q.query.cursor):&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
After iterating over the query, this assertion confirms that the raw SQL query has been executed. It does so by checking that the cursor attribute of the query is now not None.&lt;/p&gt;

&lt;p&gt;Very interesting setup here. We see how we create a raw query execute it and check it with the last assertion. Look at the &lt;code&gt;list()&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;The main goal of this post was to make you familiar with testing and how the Django test can be written.&lt;/p&gt;

&lt;p&gt;Comment your thoughts below. Until next time.&lt;/p&gt;

&lt;p&gt;To read more about the list: check out this part of the &lt;a href="https://docs.djangoproject.com/en/5.0/ref/models/querysets/#when-querysets-are-evaluated"&gt;documentation&lt;/a&gt;. &lt;/p&gt;

</description>
      <category>django</category>
      <category>unittest</category>
      <category>python</category>
    </item>
  </channel>
</rss>
