<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Vladimir Vyalov</title>
        <link>https://paragraph.com/@vladimir-vyalov</link>
        <description>Backend developer</description>
        <lastBuildDate>Tue, 08 Sep 2026 23:47:18 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[Microservices Patterns by Chris Richardson Chapter 6 Developing business logic with event sourcing]]></title>
            <link>https://paragraph.com/@vladimir-vyalov/microservices-patterns-by-chris-richardson-chapter-6-developing-business-logic-with-event-sourcing</link>
            <guid>5pSPduzFXLMY0IMzdTTl</guid>
            <pubDate>Tue, 19 Jul 2022 15:32:16 GMT</pubDate>
            <description><![CDATA[Event sourcing is a different way of structuring the business logic and persisting aggregates. It persists an aggregate as a sequence of events. Each event represents a state change of the aggregate. An application recreates the current state of an aggregate by replaying the events. Traditional applications usually use RDB and ORM approach for data persistence. But it has several drawbacks and limitations:Object-Relational impedance mismatch.Lack of aggregate history.Implementing audit loggin...]]></description>
            <content:encoded><![CDATA[<p>Event sourcing is a different way of structuring the business logic and persisting aggregates. It persists an aggregate as a sequence of events. Each event represents a state change of the aggregate. An application recreates the current state of an aggregate by replaying the events.</p><p>Traditional applications usually use RDB and ORM approach for data persistence. But it has several drawbacks and limitations:</p><ul><li><p>Object-Relational impedance mismatch.</p></li><li><p>Lack of aggregate history.</p></li><li><p>Implementing audit logging is tedious and error prone.</p></li><li><p>Event publishing is bolted on to the business logic.</p></li></ul><p>If an application potentially may produce too many state changes of aggregate – than it worth to implement snapshots and replay events only from the last snapshot for getting current state.</p><p>Managing event schema evolution might be challenging due to not all changes of events are backward compatible (renaming, changing type of field, etc.). Upcaster mechanism resolves this challenge. It works similar to schema migrations for SQL databases. It does not change existing events instead updates individual events from an old version to a newer version. As a result, the application code only ever deals with the current event schema.</p><p>Deleting data might be tricky. It&apos;s possible to implement soft delete with deletion flag in database. But due to General Data Protection Regulation, a European data protection and privacy regulation that grants individuals the right to erasure. An application must have the ability to forget a user’s personal information, such as their email address. Encryption is one mechanism you can use to solve this problem. Each user has an encryption key, which is stored in a separate database table. The application uses that encryption key to encrypt any events containing the user’s personal information before storing them in an event store. When a user requests to be erased, the application deletes the encryption key record from the database table. The user’s personal information is effectively deleted, because the events can no longer be decrypted.</p><p>Querying the event store also might be challenging. Consequently, you must implement queries using the CQRS approach described in chapter 7.</p><p>Connect with me on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/vyalovvldmr/">LinkedIn</a></p>]]></content:encoded>
            <author>vladimir-vyalov@newsletter.paragraph.com (Vladimir Vyalov)</author>
        </item>
        <item>
            <title><![CDATA[Microservices Patterns by Chris Richardson Chapter 5 Designing business logic in a microservice architecture]]></title>
            <link>https://paragraph.com/@vladimir-vyalov/microservices-patterns-by-chris-richardson-chapter-5-designing-business-logic-in-a-microservice-architecture</link>
            <guid>uKkd5Bz7Cn9MpXCgPrqJ</guid>
            <pubDate>Tue, 19 Jul 2022 10:12:21 GMT</pubDate>
            <description><![CDATA[In traditional object-oriented design, a domain model is a collection of classes and relationships between classes. The classes are usually organized into packages. But interestingly, the explicit boundaries of each business object are missing from this kind of traditional domain model. This lack of boundaries can sometimes cause problems, especially in microservice architecture.Aggregates have explicit boundariesAn aggregate is a cluster of domain objects within a boundary that can be treate...]]></description>
            <content:encoded><![CDATA[<p>In traditional object-oriented design, a domain model is a collection of classes and relationships between classes. The classes are usually organized into packages. But interestingly, the explicit boundaries of each business object are missing from this kind of traditional domain model. This lack of boundaries can sometimes cause problems, especially in microservice architecture.</p><h2 id="h-aggregates-have-explicit-boundaries" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Aggregates have explicit boundaries</h2><p>An aggregate is a cluster of domain objects within a boundary that can be treated as a unit. It consists of a root entity and possibly one or more other entities and value objects. Many business objects are modeled as aggregates. Aggregates decompose a domain model into chunks, which are individually easier to understand. They also clarify the scope of operations such as load, update, and delete. These operations act on the entire aggregate rather than on parts of it. An aggregate is often loaded in its entirety from the database, thereby avoiding any complications of lazy loading. Deleting an aggregate removes all of its objects from a database. Aggregates must obey is that a transaction can only create or update a single aggregate.</p><h2 id="h-publishing-domain-events" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Publishing domain events</h2><p>In the context of DDD, a domain event is something that has happened to an aggregate. A domain event is a class with a name formed using a past-participle verb. Usually it contains domain object Id also has metadata, such as the event ID, and a timestamp. It might also have the identity of the user who made the change, because that’s useful for auditing. Approach known as event enrichment is for events to contain information that consumers need. It simplifies event consumers because they no longer need to request that data from the service that published the event. Although event enrichment simplifies consumers, the drawback is that it risks making the event classes less stable. An event class potentially needs to change whenever the requirements of its consumers change. This can reduce maintainability because this kind of change can impact multiple parts of the application. Satisfying every consumer can also be a futile effort. Fortunately, in many situations it’s fairly obvious which properties to include in an event.</p><h2 id="h-event-storming" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Event storming</h2><p>Event storming is an event-centric workshop format for understanding a complex domain. It involves gathering domain experts in a room, lots of sticky notes, and a very large surface – a whiteboard or paper roll – to stick the notes on. The result of event storming is an event-centric domain model consisting of aggregates and events.</p><p>Connect with me on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/vyalovvldmr/">LinkedIn</a></p>]]></content:encoded>
            <author>vladimir-vyalov@newsletter.paragraph.com (Vladimir Vyalov)</author>
        </item>
        <item>
            <title><![CDATA[Microservices Patterns by Chris Richardson Chapter 4 Managing transactions with sagas]]></title>
            <link>https://paragraph.com/@vladimir-vyalov/microservices-patterns-by-chris-richardson-chapter-4-managing-transactions-with-sagas</link>
            <guid>EeUwUy9VImbCt223dc1p</guid>
            <pubDate>Sun, 17 Jul 2022 17:51:34 GMT</pubDate>
            <description><![CDATA[My personal short notes after reading the book. In reality, even monolithic applications typically don’t use textbook ACID transactions. For example, many applications use a lower transaction isolation level in order to improve performance. Also, many important business processes, such as transferring money between accounts at different banks, are eventually consistent. The traditional approach to maintaining data consistency across multiple services, databases, or message brokers is to use d...]]></description>
            <content:encoded><![CDATA[<p>My personal short notes after reading the book.</p><p>In reality, even monolithic applications typically don’t use textbook ACID transactions. For example, many applications use a lower transaction isolation level in order to improve performance. Also, many important business processes, such as transferring money between accounts at different banks, are eventually consistent.</p><p>The traditional approach to maintaining data consistency across multiple services, databases, or message brokers is to use distributed transactions. The de facto standard for distributed transaction management is the X/Open Distributed Transaction Processing (DTP) Model (X/Open XA—see <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://en.wikipedia.org/wiki/X/Open_XA">https://en.wikipedia.org/wiki/X/Open_XA</a>).</p><p>XA uses two-phase commit (2PC) to ensure that all participants in a transaction either commit or rollback. An XA-compliant technology stack consists of XA-compliant data- bases and message brokers, database drivers, and messaging APIs, and an interprocess communication mechanism that propagates the XA global transaction ID. Most SQL databases are XA compliant, as are some message brokers.</p><p>Actually that is form of synchronous IPC, which reduces availability. To solve the more complex problem of maintaining data consistency in a microservice architecture, an application must use a different mechanism that builds on the concept of loosely coupled, asynchronous services. This is where sagas come in.</p><h2 id="h-using-the-saga-pattern-to-maintain-data-consistency" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Using the Saga pattern to maintain data consistency</h2><p>Sagas are mechanisms to maintain data consistency in a microservice architecture without having to use distributed transactions. You define a saga for each system command that needs to update data in multiple services. A saga is a sequence of local transactions. Sagas differ from ACID transactions in a couple of important ways, they lack the isolation property of ACID transactions. Also, because each local transaction commits its changes, a saga must be rolled back using compensating transactions.</p><h3 id="h-coordinating-sagas" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Coordinating sagas</h3><ul><li><p>Choreography – distribute the decision making and sequencing among the saga participants. They primarily communicate by exchanging events.</p></li><li><p>Orchestration – centralize a saga’s coordination logic in a saga orchestrator class. A saga orchestrator sends command messages to saga participants telling them which operations to perform.</p></li></ul><p>Choreography might be difficult to understand, there might be cyclical dependencies and risk of tight coupling. It&apos;s often better for more complex sagas use orchestration pattern.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/23ff7a0384f4e24cb91a7a30577c4945dc20c1b33322bfae5721ec77160ed7ea.png" alt="Implementing the createOrder saga using orchestration" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Implementing the createOrder saga using orchestration</figcaption></figure><p>A good way to model a saga orchestrator is as a state machine.</p><h3 id="h-handling-the-lack-of-isolation" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Handling the lack of isolation</h3><p>The lack of isolation can cause the following three anomalies:</p><ul><li><p>Lost updates – one saga overwrites without reading changes made by another saga.</p></li><li><p>Dirty reads – a transaction or a saga reads the updates made by a saga that has not yet completed those updates.</p></li><li><p>Fuzzy/nonrepeatable reads – two different steps of a saga read the same data and get different results because another saga has made updates.</p></li></ul><h3 id="h-countermeasures-for-handling-the-lack-of-isolation" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Countermeasures for handling the lack of isolation</h3><p>The saga transaction model is ACD, and its lack of isolation can result in anomalies that cause applications to misbehave. It’s the responsibility of the developer to write sagas in a way that either prevents the anomalies or minimizes their impact on the business.</p><figure float="none" data-type="figure" class="img-center" style="max-width: null;"><img src="https://storage.googleapis.com/papyrus_images/a9bfb57813a484f33b41c368c9d76b332180184cb6483a569f6cf34154c32735.png" alt="Different types of transactions" blurdataurl="data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACwAAAAAAQABAAACAkQBADs=" nextheight="600" nextwidth="800" class="image-node embed"><figcaption HTMLAttributes="[object Object]" class="">Different types of transactions</figcaption></figure><h4 id="h-countermeasure-semantic-lock" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: Semantic Lock</h4><p>When using the semantic lock countermeasure, a saga’s compensatable transaction sets a flag in any record that it creates or updates. The flag indicates that the record isn’t committed and could potentially change.</p><h4 id="h-countermeasure-commutative-updates" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: Commutative Updates</h4><p>One straightforward countermeasure is to design the update operations to be com- mutative. Operations are commutative if they can be executed in any order. Consider, for example, a scenario where a saga needs to be rolled back after a compensatable transaction has debited (or credited) an account. The compensating transaction can simply credit (or debit) the account to undo the update. There’s no possibility of overwriting updates made by other sagas.</p><h4 id="h-countermeasure-pessimistic-view" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: Pessimistic View</h4><p>It reorders the steps of a saga to minimize business risk due to a dirty read.</p><h4 id="h-countermeasure-reread-value" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: Reread Value</h4><p>A saga that uses this counter- measure rereads a record before updating it, verifies that it’s unchanged, and then updates the record.</p><h4 id="h-countermeasure-version-file" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: Version File</h4><p>The version file countermeasure is so named because it records the operations that are performed on a record so that it can reorder them. It’s a way to turn non-commutative operations into commutative operations.</p><h4 id="h-countermeasure-by-value" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Countermeasure: By Value</h4><p>It’s a strategy for selecting concurrency mechanisms based on business risk. An application that uses this countermeasure uses the properties of each request to decide between using sagas and distributed transactions. It executes low-risk requests using sagas, perhaps applying the countermeasures described in the preceding section. But it executes high-risk requests involving, for example, large amounts of money, using distributed transactions. This strategy enables an application to dynamically make trade-offs about business risk, availability, and scalability.</p><p>Connect with me on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/vyalovvldmr/">LinkedIn</a></p>]]></content:encoded>
            <author>vladimir-vyalov@newsletter.paragraph.com (Vladimir Vyalov)</author>
        </item>
        <item>
            <title><![CDATA[Microservices Patterns by Chris Richardson Chapter 3 Interprocess communication in a microservice architecture]]></title>
            <link>https://paragraph.com/@vladimir-vyalov/microservices-patterns-by-chris-richardson-chapter-3-interprocess-communication-in-a-microservice-architecture</link>
            <guid>Zwk4CKDi6j4E8kaqZmNH</guid>
            <pubDate>Sat, 16 Jul 2022 07:03:32 GMT</pubDate>
            <description><![CDATA[My personal short notes after reading the book.Overview of interprocess communication in a microservice architectureSynchronous request/response-based communicationRESTBinary gRPC or AvroOther JSON/XML RPCAsynchronous, message-based communicationAMQPSTOMPInteraction stylesOne-to-one (Request/response, Asynchronous request/response, One-way notifications)One-to-many (Publish/subscribe, Publish/async responses)API-first design is essential – review the interface definition with the client devel...]]></description>
            <content:encoded><![CDATA[<p>My personal short notes after reading the book.</p><h2 id="h-overview-of-interprocess-communication-in-a-microservice-architecture" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Overview of interprocess communication in a microservice architecture</h2><h3 id="h-synchronous-requestresponse-based-communication" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Synchronous request/response-based communication</h3><ul><li><p>REST</p></li><li><p>Binary gRPC or Avro</p></li><li><p>Other JSON/XML RPC</p></li></ul><h3 id="h-asynchronous-message-based-communication" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Asynchronous, message-based communication</h3><ul><li><p>AMQP</p></li><li><p>STOMP</p></li></ul><h3 id="h-interaction-styles" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Interaction styles</h3><ul><li><p>One-to-one (Request/response, Asynchronous request/response, One-way notifications)</p></li><li><p>One-to-many (Publish/subscribe, Publish/async responses)</p></li></ul><p>API-first design is essential – review the interface definition with the client developers than start implementing.</p><h3 id="h-backward-compatible-api-changes" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Backward compatible API changes</h3><ul><li><p>Adding optional attributes to request</p></li><li><p>Adding attributes to a response</p></li><li><p>Adding new operations Resolve backward incompatible changes with versioning of API and deploying two versions of API at the same time.</p></li></ul><h3 id="h-message-formats" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Message formats</h3><ul><li><p>Text-based</p></li><li><p>Binary</p></li></ul><h2 id="h-using-rest" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Using REST</h2><p>Maturity model for REST by Leonard Richardson:</p><ul><li><p>Level 0: Clients invoke the service by making HTTP POST requests to its sole URL endpoint.</p></li><li><p>Level 1: Service supports the idea of resources. To perform an action on a resource, a client makes a POST request that specifies the action to perform and any parameters.</p></li><li><p>Level 2: Service uses HTTP verbs to perform actions: GET to retrieve, POST to create, and PUT to update. This enables services to use web infrastructure such as caching for GET requests.</p></li><li><p>Level 3: Service is based on the terribly named HATEOAS (Hypertext As The Engine Of Application State) principle. The basic idea is that the representation of a resource returned by a GET request contains links for performing actions on that resource. For example, a client can cancel an order using a link in the representation returned by the GET request that retrieved the order. The benefits of HATEOAS include no longer having to hard-wire URLs into client code.</p></li></ul><h3 id="h-there-are-numerous-benefits-to-using-rest" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">There are numerous benefits to using REST:</h3><ul><li><p>It’s simple and familiar.</p></li><li><p>You can test an HTTP API from within a browser using, for example, the Postman plugin, or from the command line using curl (assuming JSON or some other text format is used).</p></li><li><p>It directly supports request/response style communication.</p></li><li><p>HTTP is, of course, firewall friendly.</p></li><li><p>It doesn’t require an intermediate broker, which simplifies the system’s architecture.</p></li></ul><h3 id="h-there-are-some-drawbacks-to-using-rest" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">There are some drawbacks to using REST:</h3><ul><li><p>It only supports the request/response style of communication.</p></li><li><p>Reduced availability. Because the client and service communicate directly with- out an intermediary to buffer messages, they must both be running for the duration of the exchange.</p></li><li><p>Clients must know the locations (URLs) of the service instances. This is a nontrivial problem in a modern application. Clients must use what is known as a service discovery mechanism to locate service instances.</p></li><li><p>Fetching multiple resources in a single request is challenging.</p></li><li><p>It’s sometimes difficult to map multiple update operations to HTTP verbs.</p></li></ul><h2 id="h-using-grpc" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Using gRPC</h2><h3 id="h-grpc-has-several-benefits" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">gRPC has several benefits:</h3><ul><li><p>It’s straightforward to design an API that has a rich set of update operations.</p></li><li><p>It has an efficient, compact IPC mechanism, especially when exchanging large messages.</p></li><li><p>Bidirectional streaming enables both RPI and messaging styles of communication.</p></li><li><p>It enables interoperability between clients and services written in a wide range of languages.</p></li></ul><h3 id="h-grpc-also-has-several-drawbacks" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">gRPC also has several drawbacks:</h3><ul><li><p>It takes more work for JavaScript clients to consume gRPC-based API than REST/JSON-based APIs.</p></li><li><p>Older firewalls might not support HTTP/2.</p></li></ul><h3 id="h-handling-partial-failure-using-the-circuit-breaker-pattern" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Handling partial failure using the Circuit breaker pattern</h3><p>Whenever one service synchronously invokes another service, it should protect itself using the approach described by Netflix:</p><ul><li><p>Network timeouts – never block indefinitely and always use timeouts when waiting for a response. Using timeouts ensures that resources are never tied up indefinitely.</p></li><li><p>Limiting the number of outstanding requests from a client to a service – impose an upper bound on the number of outstanding requests that a client can make to a particular service. If the limit has been reached, it’s probably pointless to make additional requests, and those attempts should fail immediately.</p></li><li><p>Circuit breaker pattern – track the number of successful and failed requests, and if the error rate exceeds some threshold, trip the circuit breaker so that further attempts fail immediately. A large number of requests failing suggests that the service is unavailable and that sending more requests is pointless. After a timeout period, the client should try again, and, if successful, close the circuit breaker.</p></li></ul><h3 id="h-service-discovery" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Service discovery</h3><ul><li><p>Application level service discovery – requires to be reimplemented in every used language</p></li><li><p>Platform level service discovery – requires all services belong to a platform</p></li></ul><h2 id="h-communicating-using-the-asynchronous-messaging-pattern" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Communicating using the Asynchronous messaging pattern</h2><h3 id="h-implementing-the-interaction-styles-using-messaging" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Implementing the interaction styles using messaging</h3><ul><li><p>Asynchronous request/response</p></li><li><p>One-way notification – using the same as in previous point point-to-point channel without response</p></li><li><p>Publish/subscribe</p></li><li><p>Publish/async responses</p></li></ul><p>Unlike with REST and Open API, there isn’t a widely adopted standard for documenting the channels and the message types. Instead, you need to write an informal document. Generally you need to specify the names of the message channels, the message types that are exchanged over each channel, and their formats</p><h3 id="h-competing-receivers-and-message-ordering" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Competing receivers and message ordering</h3><p>For example, imagine that there are three instances of a service reading from the same point-to-point channel and that a sender publishes <code>orderCreated</code>, <code>orderUpdated</code>, and <code>orderCancelled</code> event messages sequentially. A simplistic messaging implementation could concurrently deliver each message to a different receiver. Because of delays due to network issues or garbage collections, messages might be processed out of order, which would result in strange behaviour. In theory, a service instance might process the <code>orderCancelled</code> message before another service processes the <code>orderCreated</code> message!</p><p>A common solution, used by modern message brokers like Apache Kafka and AWS Kinesis, is to use sharded (partitioned) channels. For example each <code>Order</code> event message has the <code>orderId</code> as its shard key. Each event for a particular order is published to the same shard, which is read by a single consumer instance. As a result, these messages are guaranteed to be processed in order.</p><h3 id="h-handling-duplicate-messages" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Handling duplicate messages</h3><ul><li><p>Write idempotent message handlers.</p></li><li><p>Track messageIds in separate database table and try to insert in the same transaction (or same table for NoSQL).</p></li></ul><h3 id="h-transactional-messaging" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Transactional messaging</h3><ul><li><p>Using a database table as a message queue – insert to this table in the same transaction and make consumer reading this table and publishing to message broker. Works reasonable well at low scale.</p></li><li><p>For large scale better solution is transactional log tailing pattern (Debezium).</p></li></ul><p>Connect with me on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/vyalovvldmr/">LinkedIn</a></p>]]></content:encoded>
            <author>vladimir-vyalov@newsletter.paragraph.com (Vladimir Vyalov)</author>
        </item>
        <item>
            <title><![CDATA[Microservices Patterns by Chris Richardson Chapter 2 Decomposition strategies]]></title>
            <link>https://paragraph.com/@vladimir-vyalov/microservices-patterns-by-chris-richardson-chapter-2-decomposition-strategies</link>
            <guid>pxfuoJheuepf1aUzaxJP</guid>
            <pubDate>Fri, 15 Jul 2022 10:17:50 GMT</pubDate>
            <description><![CDATA[I&apos;ve found the book "Microservices Patterns" by Chris Richardson mind blowing clear, structural and useful. Some notes which I was doing for myself while was reading the book:What is an architecture?The 4+1 View Model of Software ArchitectureLogical view – classes and packagesImplementation view – modules/packagesProcess view – processes at runtime and IPC (interprocess communication)Deployment – how the processes are mapped to machines+1 – that animate views. Each scenario describes how...]]></description>
            <content:encoded><![CDATA[<p>I&apos;ve found the book &quot;Microservices Patterns&quot; by Chris Richardson mind blowing clear, structural and useful.</p><p>Some notes which I was doing for myself while was reading the book:</p><h2 id="h-what-is-an-architecture" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is an architecture?</h2><h3 id="h-the-41-view-model-of-software-architecture" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">The 4+1 View Model of Software Architecture</h3><ul><li><p>Logical view – classes and packages</p></li><li><p>Implementation view – modules/packages</p></li><li><p>Process view – processes at runtime and IPC (interprocess communication)</p></li><li><p>Deployment – how the processes are mapped to machines</p></li><li><p>+1 – that animate views. Each scenario describes how the various architectural components within a particular view collaborate in order to handle a request. A scenario in the logical view, for example, shows how the classes collaborate. Similarly, a scenario in the process view shows how the processes collaborate.</p></li></ul><h3 id="h-why-architecture-matters" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Why Architecture Matters</h3><p>An application has two category of requirements:</p><ul><li><p>Functional requirements – low impact on architecture (you can implement functional requirements with almost every architecture, even with big ball of mud)</p></li><li><p>Quality of service requirements (QoS) – scalability, reliability, maintainability, testability, deployability. Here an architecture is important</p></li></ul><h3 id="h-architectural-styles" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Architectural Styles</h3><h4 id="h-logical-view" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Logical View</h4><ul><li><p>Layered</p></li><li><p>Hexagonal – suitable for microservices</p></li></ul><h4 id="h-implementation-view" class="text-xl font-header !mt-6 !mb-3 first:!mt-0 first:!mb-0">Implementation View</h4><ul><li><p>Monolith</p></li><li><p>Microservices</p></li></ul><h2 id="h-what-is-a-service" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">What is a service?</h2><p>The API of service consists of commands <code>createOrder()</code>, queries <code>findOrderById()</code>, and events <code>OrderCreated</code>. Services have to be loosely coupled by API. Don&apos;t couple services with shared libraries which include business logic. Move it to a separate service instead. Despite of the word &quot;micro&quot; is represented in the naming of architecture size isn&apos;t useful metric. Service should be capable to be developed by a small team.</p><h3 id="h-service-decomposition" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Service Decomposition</h3><p>Patterns for decomposing an application into services:</p><ul><li><p>Decompose by business capability</p></li><li><p>Decompose by subdomain – organizes services around domain-driven design (DDD) subdomains Steps for decomposing an application into services:</p></li></ul><ol><li><p>Creating a high-level domain model</p></li><li><p>Defining system operations</p></li><li><p>Decompose into services by business capability or by subdomain with help of Single Responsibility Principle and Common Closure Principle</p></li><li><p>Assign system operations to services</p></li></ol><h3 id="h-obstacles-to-decomposing-an-application-into-services" class="text-2xl font-header !mt-6 !mb-4 first:!mt-0 first:!mb-0">Obstacles to decomposing an Application into Services</h3><ul><li><p>Network latency</p></li><li><p>Synchronous interprocess communication reduces availability</p></li><li><p>Maintaining Data consistency across services</p></li><li><p>Obtaining a consistence view of the data</p></li><li><p>God classes prevent decomposition</p></li></ul><p>Connect with me on <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.linkedin.com/in/vyalovvldmr/">LinkedIn</a></p>]]></content:encoded>
            <author>vladimir-vyalov@newsletter.paragraph.com (Vladimir Vyalov)</author>
        </item>
    </channel>
</rss>