<?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: Akshay Kumar</title>
    <description>The latest articles on DEV Community by Akshay Kumar (@akshay161099).</description>
    <link>https://dev.to/akshay161099</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%2F842749%2Fa006fac6-1fa5-4a3d-a351-1d5df8ee43c5.jpeg</url>
      <title>DEV Community: Akshay Kumar</title>
      <link>https://dev.to/akshay161099</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/akshay161099"/>
    <language>en</language>
    <item>
      <title>From One Server to Millions: How Scaling Works in System Design</title>
      <dc:creator>Akshay Kumar</dc:creator>
      <pubDate>Thu, 06 Nov 2025 13:14:09 +0000</pubDate>
      <link>https://dev.to/akshay161099/system-design-scaling-36pe</link>
      <guid>https://dev.to/akshay161099/system-design-scaling-36pe</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbst8rmfqoy2px9alkdo4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbst8rmfqoy2px9alkdo4.png" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
What is Scalability?&lt;/p&gt;

&lt;p&gt;Number of requests a system can handle simultaneously. For this we can either add more resources to infrastructure or make our current infrastruction advanced.&lt;/p&gt;

&lt;p&gt;Scaling is basically increasing the capability of our system to handle large number of requests.&lt;/p&gt;

&lt;p&gt;How to scale our system?&lt;/p&gt;

&lt;p&gt;Well, there are two ways a system can be scaled —&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vertical scaling&lt;/li&gt;
&lt;li&gt;Horizontal scaling&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Vertical Scaling —&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In vertical scaling, we make our infrastructure bulky hence making it more capable to handle more requests. This can be done by introducing more CPU, GPU, RAM, Disks etc.&lt;/p&gt;

&lt;p&gt;Vertical scaling must be the first step to scale a system, because it is less expensive than horizontal scaling and its better to utilise the maximum capacity of current infrastructure.&lt;/p&gt;

&lt;p&gt;Vertical scaling is also called Scaling Up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Horizontal Scaling —&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In Horizontal scaling or Scaling out , we add more machines to the current infrastructure. This can be done by adding more servers, databases, load balancers, etc to handle more requests.&lt;br&gt;
Adding a whole new machine is expensive compared to increasing the machine’s capability(Vertical Scaling). So the best way to scale a system is first scaling it vertically and then going to horizontal scaling further.&lt;/p&gt;

&lt;p&gt;In case of horizontal scaling, we need a load balancer to forward the requests to other machines.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vjyq43tzqdfzumk7745.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6vjyq43tzqdfzumk7745.png" alt=" " width="745" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With horizontal scaling we can enable our application to scale infinitely.&lt;/p&gt;

&lt;p&gt;Lets take a scenario where we need to scale our database.&lt;/p&gt;

&lt;p&gt;Scaling our Database —&lt;/p&gt;

&lt;p&gt;Firstly, we vertically scale our database and make it&lt;/p&gt;

&lt;p&gt;Press enter or click to view image in full size&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd2zzsv2il3fgywnwpf5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftd2zzsv2il3fgywnwpf5.jpg" alt=" " width="800" height="360"&gt;&lt;/a&gt;&lt;br&gt;
now, we can create read replicas to handle read requests from users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl81a090rqe6g5cxth4f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkl81a090rqe6g5cxth4f.jpg" alt=" " width="800" height="697"&gt;&lt;/a&gt;&lt;br&gt;
The primary database here can also be called a master db. Its job is to write the updates to the read replicas.&lt;br&gt;
So the read requests can be served by the read replicas, and write requests by the master node. Hence, not overwhelming the master node with read requests.&lt;/p&gt;

&lt;p&gt;If our application is read intensive then this design is fine, if it is write intensive as well, we can create a replica for write db too.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Strategy Design Pattern in Java</title>
      <dc:creator>Akshay Kumar</dc:creator>
      <pubDate>Sat, 11 Oct 2025 09:49:56 +0000</pubDate>
      <link>https://dev.to/akshay161099/strategy-design-pattern-in-java-3402</link>
      <guid>https://dev.to/akshay161099/strategy-design-pattern-in-java-3402</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjdsisyus8hqody4sdi5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjdsisyus8hqody4sdi5.jpg" alt=" " width="560" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Strategy is a behavioral design pattern that turns a set of behaviors into objects and makes them interchangeable inside original context object.&lt;/p&gt;

&lt;p&gt;Lets take an example of payment methods —&lt;br&gt;
Suppose we have to create an application, where a user can pay using either a card or UPI.&lt;/p&gt;

&lt;p&gt;A general code for doing above can be written like below —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (paymentMethod.equals("1")) {
    PayPal p = new PayPal();
    p.pay(amount);
} else if (paymentMethod.equals("2")) {
    CreditCard c = new CreditCard();
    c.pay(amount);
} else if (paymentMethod.equals("3")) {
    GooglePay g = new GooglePay();
    g.pay(amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we have created 3 classes for each payment type. And the above code is being called from a resource layer or business layer.&lt;/p&gt;

&lt;p&gt;Now, if we recall the SOLID principles, we can easily see the violation of Open/Closed principle. Because later if more methods are added, we’ll need to change the code in client class. But if we do following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (paymentMethod.equals("1")) {
    PaymentStrategy p = new PayPal();
    p.pay(amount);
} else if (paymentMethod.equals("2")) {
    PaymentStrategy c = new CreditCard();
    c.pay(amount);
} else if (paymentMethod.equals("3")) {
    PaymentStrategy g = new GooglePay();
    g.pay(amount);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;where PaymentStrategy is an interface and all the strategy classes extend this. Does this solve the problem. Well, not entirely. Because we still have Open/Closed principle being violated due to addition of a new if else clause and imports for that strategy too.&lt;br&gt;
So what would be the right way to do it?&lt;/p&gt;

&lt;p&gt;Lets find out.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PaymentStrategyFactory {
    private static final Map&amp;lt;String, PayStrategy&amp;gt; strategies = Map.of(
        "paypal", new PayByPayPal(),
        "creditcard", new PayByCreditCard(),
        "googlepay", new PayByGooglePay()
    );

    public static PayStrategy getStrategy(String method) {
        return strategies.get(method.toLowerCase());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we have a factory entirely designed to take care of the strategies.&lt;br&gt;
The map is of types String, PayStrategy. And all the strategies implements this interface. So we dont need to define the specific strategy class. Factory would take care of all of them.&lt;/p&gt;

&lt;p&gt;getStrategy() method is used to fetch the instance of the strategy that is called from the client code. So client code would look like following —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PayStrategy strategy = PaymentStrategyFactory.getStrategy(paymentMethod);
strategy.pay();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;here paymentMethod could contain “paypal” or “creditCard” or “googlePay”.&lt;br&gt;
So we don’t need to change anything in client code.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltki7q39e9q340vwt0ic.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fltki7q39e9q340vwt0ic.jpg" alt=" " width="560" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>solidprinciples</category>
      <category>java</category>
    </item>
    <item>
      <title>Why 2-Phase Commit Fails in Microservices — And How the Saga Pattern Saves the Day</title>
      <dc:creator>Akshay Kumar</dc:creator>
      <pubDate>Thu, 31 Jul 2025 13:10:13 +0000</pubDate>
      <link>https://dev.to/akshay161099/why-2-phase-commit-fails-in-microservices-and-how-the-saga-pattern-saves-the-day-3f9p</link>
      <guid>https://dev.to/akshay161099/why-2-phase-commit-fails-in-microservices-and-how-the-saga-pattern-saves-the-day-3f9p</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbq7rmsjg4ypjuhv29o2r.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbq7rmsjg4ypjuhv29o2r.webp" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When talking about microservices, it consists of multiple services communicating with each other giving the application an edge over the monolytic architecture.&lt;/p&gt;

&lt;p&gt;But the biggest problem encountered in a micro-service architecture is how to handle the transaction that spans multiple services.&lt;br&gt;
Hence making data consistency across the service database a big challenge. In a micro-service architecture, every service can have its own database, tech stack and database.&lt;/p&gt;

&lt;p&gt;So when a transaction has to depend on more than one service, data consistency is needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed transactions —&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdb9zr6gi5djupdid0a2.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdb9zr6gi5djupdid0a2.webp" alt=" " width="800" height="76"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above diagram, we have 4 services with their transactions. To ensure a successful order processing service, all four microservices must complete their indivicual transactions. If any transaction fails, all the preceding transaction updates must be rolled back.&lt;/p&gt;

&lt;p&gt;But the distrubuted transactions have following challenges —&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It must maintain ACID : To ensure correctness of a transaction, it must be atomic, consistent, isolated and durable. As in this scenario, the transaction spans multiple services, ensuring ACID is a big challenge.&lt;/li&gt;
&lt;li&gt;Isolation of transactions : If a common object is changed by one service and is read by another service, there is data inconsistency.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To overcome these limitations, 2 Phase-Commit can be used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Two Phase Commit —&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Two-Phase Commit protocol (2PC) is a widely used pattern to implement distributed transactions. We can use this pattern in a microservice architecture to implement distributed transactions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33nets5f71qxftphp0dp.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F33nets5f71qxftphp0dp.webp" alt=" " width="800" height="261"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In two phase commit, there is a central body called coordinator which is connected to the services which is responsible to control the transactions and contains the logic to manage the transactions.&lt;/p&gt;

&lt;p&gt;The two phase commit runs a distributed transaction in two phases —&lt;br&gt;
&lt;strong&gt;Phase 1 **: In this phase, coordinator asks all the nodes whether they are ready to commit the transaction or not.&lt;br&gt;
**Phase 2&lt;/strong&gt; : In this phase, depending on the ack received by the nodes, if all ack are yes, then the coordinator asks all of them to commit. Otherwise, if even one ack is a no, then the coordinator tells all the nodes to roll back their transactions.&lt;/p&gt;

&lt;p&gt;2 PC sounds great. But what is the problem with this design?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Single Point of Failure(SPoF) — If the coordinator is down, the whole system goes down.&lt;/li&gt;
&lt;li&gt;All the services need to wait for the slowest service for confirmation. So, the overall performance of the transaction is bound by the slowest service. 3. Two-phase commit protocol is not supported in NoSQL databases.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;SAGA Architecture Pattern The SAGA pattern provides transaction management using a sequence of local transactions. Each service is considered as a SAGA participant and each participant has its individual transaction. SAGA makes sure that either all the transactions complete successfully or the corresponding compensation transactions are run to undo the work previously completed ie. bascially rolling back the other transactions.&lt;br&gt;
In this pattern, the compensation transactions must me idempotent and retryable.&lt;/p&gt;

&lt;p&gt;The Saga Execution Coordinator (SEC) guarantees these principles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw906i8rzpv9iwx9xddo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faw906i8rzpv9iwx9xddo.webp" alt=" " width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Saga Execution Coordinator is a central component used to implement a SAGA flow. It contains a saga log that captures the sequence of events of a distributed transaction.&lt;br&gt;
In the diagram below, the success scenario is shown for all the transactions completed and the logs captured in the saga log.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi67x1g6970380xt21tje.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi67x1g6970380xt21tje.webp" alt=" " width="800" height="672"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are two approaches to implement SAGA design pattern —&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;SAGA Choreography Pattern&lt;/li&gt;
&lt;li&gt;SAGA Orchestration Pattern&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;SAGA Chorography Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this pattern, each microservice pushes an event to be fetched by the next microservice. Here the microservices should have their individual transactions and be a part of the Saga.&lt;br&gt;
In this pattern, the Saga Execution Coordinator is either embedded within the microservice or can be a standalone component. In the Saga, choreography flow is successful if all the microservices complete their local transaction, and none of the microservices reported any failure.&lt;br&gt;
So, if two services ran successfully and the third failed, the other services listen to the event of failure and roll back their own transactions. Hence eliminating the SPOF.&lt;/p&gt;

&lt;p&gt;The following diagram demonstrates the successful Saga flow for the online order processing application:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5egomhf59f0drgg5zopq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5egomhf59f0drgg5zopq.webp" alt=" " width="800" height="982"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the case of failure, the microservice logs the failure in the log and reports the failure to SEC and its SEC’s responsibility to run the compensating transactions using the logs and keep retrying of it fails.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k7nkjpue48xfoafh3lq.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k7nkjpue48xfoafh3lq.webp" alt=" " width="800" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this example, the Payment microservice reports a failure, and the SEC invokes the compensating transaction to unblock the seat. If the call to the compensating transaction fails, it is the SEC’s responsibility to retry it until it is successfully completed.&lt;br&gt;
Recall that in Saga, a compensating transaction must be idempotent and retryable. The Choreography pattern works for greenfield (from scratch) microservice application development. Also, this pattern is suitable when there are fewer participants in the transaction.&lt;br&gt;
Here are a few frameworks available to implement the choreography pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Axon Saga&lt;/strong&gt; — a lightweight framework and widely used with Spring Boot-based microservices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eclipse MicroProfile LRA&lt;/strong&gt; — implementation of distributed transactions in Saga for HTTP transport based on REST principles&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Eventuate Tram Saga&lt;/strong&gt; — Saga orchestration framework for Spring Boot and Micronaut-based microservices.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;SAGA Orchestration Pattern&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this pattern, a single orchestrator is responsible for managing the overall transaction status. If any of the microservices encounter a failure, the orchestrator is responsible for invoking the necessary compensating transactions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faquuj7f4inlg4qlb2ubo.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faquuj7f4inlg4qlb2ubo.webp" alt=" " width="800" height="539"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Saga orchestration pattern&lt;/strong&gt; is useful for brownfield microservice application development architecture. In other words, this pattern works when we already have a set of microservices and would like to implement the Saga pattern in the application.&lt;br&gt;
We need to define the appropriate compensating transactions to proceed with this pattern. It is different from choreography, as the orchesrator decides every thing and has the control with it. Whereas in choreography, one service has to send event to next, which makes the services in control.&lt;/p&gt;

&lt;p&gt;Here are a few frameworks available to implement the orchestrator pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Camunda&lt;/strong&gt; is a Java-based framework that supports Business Process Model and Notation (BPMN) standard for workflow and process automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Apache Camel&lt;/strong&gt; provides the implementation for Saga Enterprise Integration Pattern (EIP).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this article, we discussed the Saga architecture pattern to implement distributed transactions in a microservice-based application.&lt;br&gt;
We first introduced the challenges of these implementations.&lt;br&gt;
We then explored the two-phase commit protocol, a popular alternative of Saga, and examined its limitation to implement distributed transactions in microservice-based applications.&lt;br&gt;
Lastly, we discussed the Saga architecture pattern, how it works and the two main approaches to implementing the Saga pattern in microservice-based applications.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>microservices</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Spring Security Part 2 : Getting started with jdbc authentication</title>
      <dc:creator>Akshay Kumar</dc:creator>
      <pubDate>Sat, 12 Apr 2025 07:54:24 +0000</pubDate>
      <link>https://dev.to/akshay161099/spring-security-part-2-getting-started-with-jdbc-authentication-2b1g</link>
      <guid>https://dev.to/akshay161099/spring-security-part-2-getting-started-with-jdbc-authentication-2b1g</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuefvcgg2ui0wgcjdxhp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpuefvcgg2ui0wgcjdxhp.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Kudos&lt;/strong&gt; 👏 to reach till here.&lt;br&gt;
In the previous article, we were implementing in-memory authentication in Spring security. But what if we need to connect to a datasource instead of an in-memory.&lt;br&gt;
In this article, we’ll fo throught JDBC authentication.&lt;/p&gt;

&lt;p&gt;Most of the concept is same as before, the only difference is setting up a jdbc authentication in the configure method.&lt;/p&gt;

&lt;p&gt;Below is the code —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Override 
  protected void configure (AuthenticationManagerBuilder auth) {
    auth.jdbcAuthentication();
  }
  @Override
  protected void configure (HttpSecurity http) {
    http.authorizeRequests()
        .antMatchers("/admin").hasRole("ADMIN").
        .antMatchers("/user").hasAnyRole("ADMIN","USER").
        .antMatchers("/**").permitAll().
        .hasAnyRole();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, we need to setup our authentication to tell Spring Security to lookup the user and password in the database. To do so, we need a bean for data source. By default, Spring security provides DataSource class which we can autowire in our project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Autowired
DataSource datasource;
@Override 
  protected void configure (AuthenticationManagerBuilder auth) {
    auth.jdbcAuthentication()
        .dataSource(dataSource);
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But how does the spring knows the configuration of the data source.&lt;br&gt;
We must configure it somewhere or else if we’re using H2 which is in-memory database, then spring by default creates a datasource.&lt;/p&gt;

&lt;p&gt;For now, lets assume we have H2 in our class path.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Autowired
DataSource datasource;
@Override 
  protected void configure (AuthenticationManagerBuilder auth) {
    auth.jdbcAuthentication()
        .dataSource(dataSource);
        .dataSource(dataSource)
        .withDefaultSchema()
        .withUser(
        user.withUserName("user")
            .password("pass")
            .roles("USER")
            .withUserName("admin")
            .password("pass")
            .roles("ADMIN")
        );
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, we’re using a default schema and creating the users.&lt;br&gt;
When a client sends a request along with a password, the authentication configuration creates these 2 users and checks do the user in request matches to these. Hence authenticating the request.&lt;/p&gt;

&lt;p&gt;Now, what if we already have a schema or we don’t want to use the default schema and you don’t want to put user creation logic in the code?&lt;br&gt;
Create your own schema in resources -&amp;gt; schema.sql&lt;/p&gt;

&lt;p&gt;schema.sql :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;create table users(
 username varchar_ignorecase(50) not null primary key,
 password varchar_ignorecase(50) not null,
 enabled boolean not null
);

create table authorities (
 username varchar_ignorecase(50) not null,
 authority varchar_ignorecase(50) not null,
 constraint fk_authorities_users foreign key(username) references users(username)
);
create unique index ix_auth_username on authorities (username,authority);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;data.sql :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INSERT INTO users (username, password, enabled) VALUES 
('user', 'pass', true),
('admin', 'pass', true);

INSERT INTO authorities (username, authority) VALUES 
('user', 'ROLE_USER'),
('admin', 'ROLE_ADMIN');
Important notes:
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The password should ideally be encoded (BCrypt is recommended) rather than stored in plain text like this&lt;br&gt;
Spring Security expects the authorities/roles to be prefixed with “ROLE_” by default&lt;br&gt;
The enabled column must be set to true for the users to be able to authenticate&lt;br&gt;
Below is the complete code for configuration class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
  @Autowired
  DataSource dataSource;

  @Override 
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.jdbcAuthentication()
        .dataSource(dataSource)
        .passwordEncoder(passwordEncoder());
  }

  @Override
    protected void configure (HttpSecurity http) {
      http.authorizeRequests()
        .antMatchers("/admin").hasRole("ADMIN").
        .antMatchers("/user").hasAnyRole("ADMIN","USER").
        .antMatchers("/**").permitAll().
        .hasAnyRole();
  }

  @Bean
  public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you autowire DataSource and use it in auth.jdbcAuthentication(), Spring Security automatically uses this DataSource to query the database for user authentication.&lt;/p&gt;

&lt;p&gt;By default, it looks for tables: users (with username, password, enabled columns) , authorities (with username, authority columns)&lt;/p&gt;

&lt;p&gt;If your schema is different, you can customize the queries.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth.jdbcAuthentication()
        .dataSource(dataSource)
        .usersByUsernameQuery("Select username, password, enables"
        + "from custom_users where username = ?")
        .authoritiesByUsernameQuery("Select username, authority "
        + "from authorities where username = ?");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’re using MySQL, you need to define the DataSource in application.properties:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spring.datasource.url=jdbc:mysql://localhost:3306/spring_security_db
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great 👏&lt;/p&gt;

&lt;p&gt;You’ve now got a good idea about spring security and jdbc authentication.&lt;/p&gt;

&lt;p&gt;Next, let’s dive deep into JWT and implementing it using Spring security.&lt;br&gt;
Thanks for reading.&lt;/p&gt;

</description>
      <category>security</category>
      <category>springboot</category>
      <category>spring</category>
      <category>java</category>
    </item>
    <item>
      <title>Secure Your APIs and Web Apps using Spring Security</title>
      <dc:creator>Akshay Kumar</dc:creator>
      <pubDate>Wed, 09 Apr 2025 14:19:20 +0000</pubDate>
      <link>https://dev.to/akshay161099/secure-your-apis-and-web-apps-using-spring-security-1976</link>
      <guid>https://dev.to/akshay161099/secure-your-apis-and-web-apps-using-spring-security-1976</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbil9c8xkzh56lw7pp5hc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbil9c8xkzh56lw7pp5hc.png" alt=" " width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security&lt;/strong&gt;. Yeah, we know, it can feel like a chore. Especially when you’re just trying to build something awesome. But trust me, skipping security is like leaving your front door wide open. That’s where Spring Security comes in — it’s your trusty sidekick for locking things down in your Spring apps. Think of it as the bouncer for your code, making sure only the right people get in.&lt;/p&gt;

&lt;p&gt;Before diving into the main part, first lets understand the difference between two widely used and similar meaning(not exaclty) words —&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Authentication&lt;/strong&gt; and &lt;strong&gt;Authorization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;They both are related to security. Well thats true. But how does both differ from one another.&lt;br&gt;
Simply put, &lt;strong&gt;Authentication&lt;/strong&gt; means &lt;strong&gt;WHO ARE YOU?&lt;/strong&gt;&lt;br&gt;
and &lt;strong&gt;Authorization&lt;/strong&gt; means &lt;strong&gt;WHAT DO YOU WANT TO ACCESS?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not same right?&lt;/p&gt;

&lt;p&gt;When we talk about authentication, we mainly mean that the person is who he is saying he is. First authentication needs to happen. In the web applications, the login pages authenticate the user if he/she is the owner of that account or not. For authentication we may need a username and a password to prove our identity.&lt;/p&gt;

&lt;p&gt;When the authentication is done, the user enters the web application. But he/she may not have access to all the features. Here comes authorization. Authorization let us know what accesses and rights the user has.&lt;br&gt;
For example, if admin is logged in, he/she has access to more number of features than a user.&lt;/p&gt;

&lt;p&gt;Now, lets talk about Principal&lt;/p&gt;

&lt;p&gt;In Spring security, a user sends a request along with credentials to the server. After the user is authenticated, the returned response contains an Object of Principal which has the details of currently logged in user.&lt;/p&gt;

&lt;p&gt;In Spring boot, add the following dependency to use Spring Security :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`&amp;lt;!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security --&amp;gt;
&amp;lt;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;org.springframework.boot&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;spring-boot-starter-security&amp;lt;/artifactId&amp;gt;
    &amp;lt;version&amp;gt;3.4.4&amp;lt;/version&amp;gt;
&amp;lt;/dependency&amp;gt;`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, as the dependency is added, do we need to configure something to use Spring security?&lt;br&gt;
NO&lt;/p&gt;

&lt;p&gt;After adding the dependency, just try hitting an API and you’ll get Unauthorized.&lt;/p&gt;

&lt;p&gt;Spring by default uses Spring security if it is added in the pom file.&lt;/p&gt;

&lt;p&gt;Spring Security Default behaviour —&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adds mandatory authentication for all URLs&lt;/li&gt;
&lt;li&gt;Adds login form(try opening the localhost url in browser)&lt;/li&gt;
&lt;li&gt;Handles login error&lt;/li&gt;
&lt;li&gt;Creates a user and a password by default.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Above, the user and password are generated by Spring security. You can find the password in the console logs when you start the application and the user is “user” by default.&lt;/p&gt;

&lt;p&gt;Lets now talk about configuring authentication.&lt;br&gt;
Step 1 : Get hold of AuthenticationManagerBuilder&lt;br&gt;
Step 2 : Set the configuration on it.&lt;/p&gt;

&lt;p&gt;What kind of authentication you want? eg. in-memory, etc.&lt;br&gt;
Set the user and password&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`@EnableWebSecurity
public class myClass extends WebSecurityConfigurerAdapter {
  @Override
  configure(AuthenticationManagerBuilder auth) {
    auth.inMemoryAuthentication()
    .withUser("user1")
    .withPassword("password")
    .roles("USER");
  }
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AuthenticatonManager has a method called authenticate() and we use AuthenticationManagerBuilder to access it. Override the configure method which takes AuthenticationManagerBuilder object and then set what kind of authentication you want, set the username and passwords and define the role for that user.&lt;br&gt;
Now, the above code is not correct because the password is in plain text.&lt;/p&gt;

&lt;p&gt;Never store password as plain text.&lt;/p&gt;

&lt;p&gt;Always deal with hashed password by encoding it.&lt;br&gt;
How to set a password encoder?&lt;br&gt;
Just expose an &lt;a class="mentioned-user" href="https://dev.to/bean"&gt;@bean&lt;/a&gt; of type PasswordEncoder because spring security keeps looking for all the beans available to find a password encoder.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@Bean&lt;br&gt;
public PasswordEncoder getEncodedPassword() {&lt;br&gt;
  return new BCryptPasswordEncoder();&lt;br&gt;
}&lt;/code&gt;&lt;br&gt;
Now for configuring authorization, we can ovverride same method configure() but with different parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`@EnableWebSecurity
public class myClass extends WebSecurityConfigurerAdapter {
  @Override
  configure(HttpSecurity http) {
    http.authorizeRequests()
    .antMatchers("/**")
    .hasRole("USER");
  }
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above code uses configure method along with HttpSecurity object, which authorizes all the requests given using antMatchers.&lt;br&gt;
Above code, will authorize all the APIs for role USER which means all the APIs are accessible only by USER role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`@EnableWebSecurity
public class myClass extends WebSecurityConfigurerAdapter {
  @Override
  configure(HttpSecurity http) {
    http.authorizeRequests()
    .antMatchers("/**")
    .hasAnyRole();
  }
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Above code lets any role access the APIs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`@EnableWebSecurity
public class myClass extends WebSecurityConfigurerAdapter {
  @Override
  configure(HttpSecurity http) {
    http.authorizeRequests()
    .antMatchers("/admin").hasRole("ADMIN").
    .antMatchers("/user").hasAnyRole("ADMIN","USER").
    .antMatchers("/**").permitAll().
    .hasAnyRole();
  }
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, the API with /admin can only be accessed by users with ADMIN role, /user can be accessed by users with roles ADMIN and USER and all the other APIs can be accessed by every user.&lt;/p&gt;

&lt;p&gt;Note the above sequence, if we put “antMatchers(“/**”).permitAll()” at the top, that would make all APIs accessible to every user, so here the sequence matters.&lt;/p&gt;

</description>
      <category>springsecurity</category>
      <category>springboot</category>
      <category>webdev</category>
      <category>java</category>
    </item>
  </channel>
</rss>
