<?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: Gokul G.K.</title>
    <description>The latest articles on DEV Community by Gokul G.K. (@gokul_gk).</description>
    <link>https://dev.to/gokul_gk</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%2F880492%2Fedd6030a-cde7-4960-9e77-bbf297f47710.jpeg</url>
      <title>DEV Community: Gokul G.K.</title>
      <link>https://dev.to/gokul_gk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gokul_gk"/>
    <language>en</language>
    <item>
      <title>Design pattern visualization: Structural Design Patterns</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Sun, 15 Mar 2026 16:09:32 +0000</pubDate>
      <link>https://dev.to/gokul_gk/design-pattern-visualization-structural-design-patterns-1863</link>
      <guid>https://dev.to/gokul_gk/design-pattern-visualization-structural-design-patterns-1863</guid>
      <description>&lt;p&gt;Refactoring &lt;a href="https://refactoring.guru/design-patterns/structural-patterns" rel="noopener noreferrer"&gt;Guru&lt;/a&gt; already has the best blog to learn Design patterns. Here I am just trying to give a brief about each design.&lt;/p&gt;

&lt;p&gt;Design patterns are solutions to recurring problems and design paradigms.&lt;/p&gt;

&lt;p&gt;Structural design patterns describe how to combine objects and classes into larger structures while maintaining flexibility and efficiency.&lt;/p&gt;

&lt;p&gt;You can get the Java code &lt;a href="https://github.com/GKcodebase/Design/blob/main/DesignPattern/src/main/java/StructuralDesignPattern/Readme.md" rel="noopener noreferrer"&gt;here&lt;/a&gt; or some detailed &lt;a href="https://github.com/GKcodebase/Design/tree/main/DesignPatternsDetailedImplementation" rel="noopener noreferrer"&gt;examples&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let's dive into each one.......&lt;/p&gt;

&lt;h3&gt;
  
  
  Adapter
&lt;/h3&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%2F7aqtcutpdmv8vy6dk06k.gif" 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%2F7aqtcutpdmv8vy6dk06k.gif" alt="Adapter Gif" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An adapter is a design pattern that allows objects with incompatible interfaces to work together effectively.&lt;/p&gt;

&lt;p&gt;Rather than a rail-to-car adaptor (which sounds like AI-generated, which it isn't), a universal power adaptor is the best real-world example.&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%2Ft0ax5hh9vo8cp6tmn3xj.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%2Ft0ax5hh9vo8cp6tmn3xj.webp" alt="Universal power adapter" width="618" height="621"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fbl92ydk9vxu2p1eifhkv.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%2Fbl92ydk9vxu2p1eifhkv.png" alt="Adapter class Diagram" width="791" height="708"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Adapter pattern acts as a bridge between two incompatible interfaces. Just like a physical travel adapter allows a European plug to work in a US wall outlet, the software Adapter allows classes with mismatched interfaces to work together smoothly.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The class that wants to interact with a system using a specific, expected interface (the Target).&lt;/li&gt;
&lt;li&gt;Target: The interface or abstract class that the Client understands and expects to work with. It defines the standard &lt;code&gt;request()&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;Adaptee: The existing, already-built class that contains the functionality the Client needs, but it has an incompatible interface (like &lt;code&gt;specificRequest()&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Adapter: The bridge class. It implements the Target interface so the Client can use it, but under the hood, it holds a reference to the Adaptee and translates the &lt;code&gt;request()&lt;/code&gt; method into the &lt;code&gt;specificRequest()&lt;/code&gt; method the Adaptee understands.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Bridge
&lt;/h3&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%2Fwxid7elu127ebma5za8q.gif" 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%2Fwxid7elu127ebma5za8q.gif" alt="Bridge Gif" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A bridge is a design pattern that allows separating a large class or a set of related classes into two distinct hierarchies: abstraction and implementation, which can be developed independently.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fkvy84n6h4ogrxoi0zadm.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%2Fkvy84n6h4ogrxoi0zadm.png" alt="Bridge class diagram" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Bridge pattern separates a class's interface (its abstraction) from its implementation, allowing both to be modified independently without breaking client code. This is particularly useful for preventing a "Cartesian product" explosion of classes (for example, instead of creating &lt;code&gt;RedCircle&lt;/code&gt;, &lt;code&gt;BlueCircle&lt;/code&gt;, &lt;code&gt;RedSquare&lt;/code&gt;, and &lt;code&gt;BlueSquare&lt;/code&gt;, create a Shape abstraction that holds a bridge to a Color implementor).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that uses the system. It only interacts with the Abstraction and doesn't need to know anything about the underlying implementations.&lt;/li&gt;
&lt;li&gt;Abstraction: The high-level control layer. It defines the basic interface for the client and maintains a reference to an &lt;code&gt;Implementor&lt;/code&gt; object. It delegates the actual work to this implementor.&lt;/li&gt;
&lt;li&gt;RefinedAbstraction: A specific variant or extension of the &lt;code&gt;Abstraction&lt;/code&gt;. It implements the specific behaviors of the high-level entity (e.g., a &lt;code&gt;Circle&lt;/code&gt; or &lt;code&gt;Square&lt;/code&gt; class extending a general Shape class).&lt;/li&gt;
&lt;li&gt;Implementor: The interface for all implementation classes. It doesn't have to match the Abstraction's interface at all; typically, the &lt;code&gt;Implementor&lt;/code&gt; provides primitive operations, while the &lt;code&gt;Abstraction&lt;/code&gt; defines higher-level operations based on those primitives.&lt;/li&gt;
&lt;li&gt;ConcreteImplementor (A/B): The specific, concrete classes that carry out the actual work (e.g., the &lt;code&gt;Red&lt;/code&gt; or &lt;code&gt;Blue&lt;/code&gt; color classes).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Composite
&lt;/h3&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%2Ftv17fsbwl8epknalr76w.gif" 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%2Ftv17fsbwl8epknalr76w.gif" alt="Composite Gif" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Composite is a structural design pattern that allows you to combine objects into tree structures and treat them as individual entities.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fr89cdopzzg5ypdpdakjg.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%2Fr89cdopzzg5ypdpdakjg.png" alt="Composite Class diagram" width="664" height="576"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Composite pattern is used to represent part-whole hierarchies as tree structures. Its primary superpower is that it allows the client code to treat individual objects (leaves) and compositions of objects (branches/nodes) in the exact same way. Think of a file system: a folder (Composite) and a file (Leaf) can both be moved, deleted, or renamed (Component operations), even though a folder contains other files and folders.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that interacts with the objects in the tree structure. It uses the &lt;code&gt;Component&lt;/code&gt; interface, meaning it doesn't need to check whether it's dealing with a single object or a complex group.&lt;/li&gt;
&lt;li&gt;Component: The base interface or abstract class for all objects in the composition. It defines common operations (such as &lt;code&gt;operation()&lt;/code&gt;) and usually includes methods for adding, removing, or accessing child components.&lt;/li&gt;
&lt;li&gt;Leaf: The basic, building-block object that has no children. It implements the &lt;code&gt;Component&lt;/code&gt; interface and defines the behavior of the &lt;code&gt;operation()&lt;/code&gt; method. In a file system, this is the individual file.&lt;/li&gt;
&lt;li&gt;Composite: The complex object that contains child components (which can be Leaves or other Composites). It implements the &lt;code&gt;Component&lt;/code&gt; interface. When &lt;code&gt;operation()&lt;/code&gt; is called on a Composite, it typically iterates over its children and delegates the work to them.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Decorator
&lt;/h3&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%2Ffrsuwu31ev00dmxe4qnh.gif" 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%2Ffrsuwu31ev00dmxe4qnh.gif" alt="Decorator Gif" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A decorator is a design pattern that allows you to attach new behaviors to objects by placing them inside special wrapper objects that include those behaviors.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fuakv2jdg4fqu4ble2g23.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%2Fuakv2jdg4fqu4ble2g23.png" alt="Decorator class diagram" width="800" height="677"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Decorator pattern allows you to attach new behaviors or responsibilities to an object dynamically at runtime, without altering its structure or relying on massive subclassing. Think of it like ordering a plain coffee and then adding "decorations" like milk, sugar, and caramel—each addition wraps the original object and adds its own flavor, but it is still fundamentally a coffee.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that interacts with objects through the standard &lt;code&gt;Component&lt;/code&gt; interface. It doesn't need to know whether it is working with a plain &lt;code&gt;ConcreteComponent&lt;/code&gt; or one wrapped in multiple decorators.&lt;/li&gt;
&lt;li&gt;Component: The common interface or abstract class for both the core objects and the decorators. It defines the standard methods (like &lt;code&gt;operation()&lt;/code&gt;) that can be used or overridden.&lt;/li&gt;
&lt;li&gt;ConcreteComponent: The base, standalone object to which new behaviors can be added. It implements the basic behavior defined in the &lt;code&gt;Component&lt;/code&gt; interface (e.g., the plain black coffee).&lt;/li&gt;
&lt;li&gt;Decorator: An abstract class that implements the &lt;code&gt;Component&lt;/code&gt; interface and simultaneously contains a reference (or wrapper) to a Component object. Its primary job is to delegate all requests to the wrapped component by default.&lt;/li&gt;
&lt;li&gt;ConcreteDecorator (A/B): The classes that extend the base &lt;code&gt;Decorator&lt;/code&gt; to add new, specific behaviors or state. They override the &lt;code&gt;operation()&lt;/code&gt; method to execute their custom code either before or after delegating the rest of the work to the wrapped &lt;code&gt;component&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Facade
&lt;/h3&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%2F7s2avq2e2bmdhruahksd.gif" 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%2F7s2avq2e2bmdhruahksd.gif" alt="Facade Gif" width="600" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A facade is a design pattern that provides a simplified interface to complex libraries, frameworks, or classes.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fn04ib4gpkdzzsixc1llj.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%2Fn04ib4gpkdzzsixc1llj.png" alt="Facade class diagram" width="800" height="725"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Facade pattern provides a simplified, unified interface to a complex set of underlying subsystems. Think of it like a smart home hub: instead of having to manually turn on the lights, roll down the blinds, and turn on the TV with three different remotes, the hub gives you a single "Movie Mode" button (the Facade) that handles all the complex underlying interactions for you.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that needs to interact with the complex subsystem. Instead of managing dozens of individual subsystem classes, it simply calls the easy-to-use methods provided by the &lt;code&gt;Facade&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Facade: The "front-facing" class that provides the simplified interface. It knows exactly which subsystem classes are responsible for a request and delegates the client's command to the appropriate places in the correct order.&lt;/li&gt;
&lt;li&gt;Subsystem Classes (A/B/C): The complex, underlying classes that do the actual, heavy-lifting work. They handle the specific tasks assigned by the &lt;code&gt;Facade&lt;/code&gt;. Importantly, these classes operate independently and have no knowledge that the &lt;code&gt;Facade&lt;/code&gt; exists—they don't hold references back to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Flyweight
&lt;/h3&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%2Ffo96nh5ormn02lm67vgl.gif" 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%2Ffo96nh5ormn02lm67vgl.gif" alt="Flyweight Gif" width="720" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A flyweight is a design pattern that allows you to fit more objects into available RAM by sharing common parts of their state among multiple objects rather than storing all data in each one.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fzwpnb96i327xf4gzslvl.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%2Fzwpnb96i327xf4gzslvl.png" alt="Flyweight class diagram" width="800" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Flyweight pattern is all about memory optimization. It allows you to fit more objects into the available RAM by sharing common parts of state across multiple objects, rather than keeping all the data in each individual object. Think of a word processor: instead of creating a brand new object for every single letter "e" in a document (which would eat up memory), the system creates exactly one "e" object that holds the font shape (the shared, unchanging data). The exact coordinates on the page where that "e" appears (the unique, changing data) are passed in from the outside.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that uses the flyweights. It calculates or stores the "extrinsic" state (the unique context, like the coordinates of a letter on a page) and passes it to the flyweight's methods when needed.&lt;/li&gt;
&lt;li&gt;FlyweightFactory: A manager class that creates and maintains a pool of flyweight objects. When a client requests a flyweight, the factory checks if one already exists. If it does, it returns the existing instance; if not, it creates a new one, adds it to the pool, and returns it.&lt;/li&gt;
&lt;li&gt;Flyweight: The interface or abstract class that defines how flyweights can receive and act on extrinsic state passed in by the client.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;ConcreteFlyweight: The object that implements the &lt;code&gt;Flyweight&lt;/code&gt; interface and stores the "intrinsic" state. This state must be immutable (unchanging) and shared across all contexts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;UnsharedConcreteFlyweight: The pattern allows for flyweights that aren't actually shared. Sometimes you have an object that implements the &lt;code&gt;Flyweight&lt;/code&gt; interface so it can be treated uniformly by the client, but it maintains all of its own state internally rather than sharing it.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Proxy
&lt;/h3&gt;

&lt;p&gt;A proxy is a design pattern that allows you to create a substitute or placeholder for another object. It manages access to the original object, enabling you to perform an operation before or after the request is sent to it.&lt;/p&gt;

&lt;h4&gt;
  
  
  Class Diagram
&lt;/h4&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%2Fwj885y11vj7uic0un8hz.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%2Fwj885y11vj7uic0un8hz.png" alt="Proxy class diagram" width="800" height="1109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Proxy pattern provides a surrogate or placeholder for another object, allowing it to control access to that object. While it looks structurally very similar to the Decorator or Adapter patterns, its intent is different: an Adapter changes the interface, a Decorator adds behavior, but a Proxy controls access. Think of a company credit card: it acts as a proxy for the company's bank account. Both the card and the account share the same "payment" interface, but the card controls access, perhaps imposing limits or logging transactions before interacting with the actual funds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client: The code that needs to use the real object. Because it interacts strictly with the Subject interface, it doesn't know (and doesn't need to know) whether it is talking to the RealSubject or the &lt;code&gt;Proxy&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Subject: The common interface shared by both the &lt;code&gt;RealSubject&lt;/code&gt; and the &lt;code&gt;Proxy&lt;/code&gt;. This ensures the proxy can be used interchangeably anywhere the real object is expected.&lt;/li&gt;
&lt;li&gt;RealSubject: The actual, underlying object that contains the real business logic or heavy resource. It actually handles the work when the &lt;code&gt;proxy&lt;/code&gt; finally passes the request along.&lt;/li&gt;
&lt;li&gt;Proxy: The middleman. It implements the Subject interface and holds a reference to the &lt;code&gt;RealSubject&lt;/code&gt;. When the client makes a request, the &lt;code&gt;proxy&lt;/code&gt; intercepts it. It might check access permissions, log the request, handle lazy loading (delaying the creation of a heavy' RealSubject' until it is absolutely needed), and ultimately delegate the work to the &lt;code&gt;RealSubject&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Structural Design Patterns: Real-World &amp;amp; Technical Examples
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Design Pattern&lt;/th&gt;
&lt;th&gt;What it does (The "TL;DR")&lt;/th&gt;
&lt;th&gt;Real-World Analogy&lt;/th&gt;
&lt;th&gt;Technical Application&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Adapter&lt;/td&gt;
&lt;td&gt;Acts as a bridge between two incompatible interfaces, allowing them to work together.&lt;/td&gt;
&lt;td&gt;A travel plug adapter that allows a US laptop charger to fit into a European wall outlet.&lt;/td&gt;
&lt;td&gt;Wrapping a legacy XML-based billing API so it can be used by a modern JSON-based microservice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bridge&lt;/td&gt;
&lt;td&gt;Separates an abstraction (interface) from its implementation, allowing the two to vary independently.&lt;/td&gt;
&lt;td&gt;A universal remote (abstraction) that can be paired with different TV brands (implementations).&lt;/td&gt;
&lt;td&gt;A UI framework where a Button abstraction delegates its rendering to underlying OS-specific (Windows/macOS) implementations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Composite&lt;/td&gt;
&lt;td&gt;Composes objects into tree structures to represent part-whole hierarchies, treating individual objects and groups uniformly.&lt;/td&gt;
&lt;td&gt;A shipping box that contains individual products as well as smaller boxes, which in turn contain more products.&lt;/td&gt;
&lt;td&gt;A file system where both Directory and File share a common interface for operations like getSize() or delete().&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decorator&lt;/td&gt;
&lt;td&gt;Dynamically attaches new responsibilities or behaviors to an object without altering its underlying structure.&lt;/td&gt;
&lt;td&gt;Ordering a basic coffee and adding "decorators" like milk, caramel syrup, and whipped cream.&lt;/td&gt;
&lt;td&gt;Wrapping a base FileDataReader with a CompressionDecorator and an EncryptionDecorator before saving to a database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Facade&lt;/td&gt;
&lt;td&gt;Provides a simplified, higher-level interface to a complex subsystem of classes.&lt;/td&gt;
&lt;td&gt;A smart home hub's "Movie Mode" button automatically dims lights, closes blinds, and turns on the TV.&lt;/td&gt;
&lt;td&gt;A simple VideoConverter class that hides the complex interactions of underlying audio/video codec libraries and buffer management.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flyweight&lt;/td&gt;
&lt;td&gt;Minimizes memory usage by sharing as much data as possible with similar objects, rather than keeping all data in each object.&lt;/td&gt;
&lt;td&gt;Using a single master blueprint to build a massive neighborhood of structurally identical houses.&lt;/td&gt;
&lt;td&gt;A text editor that loads a single instance of a character glyph (like the letter "e") into memory and reuses it, only passing its unique X/Y coordinates on the screen.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Proxy&lt;/td&gt;
&lt;td&gt;Provides a surrogate or placeholder to control access to the original object.&lt;/td&gt;
&lt;td&gt;A credit card acting as a proxy for your bank account—it controls access to your funds and enforces limits.&lt;/td&gt;
&lt;td&gt;A LazyImageLoader that displays a lightweight placeholder icon on a webpage until the user scrolls down, at which point it loads the heavy, high-res image.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Design pattern visualization: Creational Design Patterns</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Wed, 18 Feb 2026 02:33:06 +0000</pubDate>
      <link>https://dev.to/gokul_gk/design-pattern-visualization-creational-design-patterns-29gj</link>
      <guid>https://dev.to/gokul_gk/design-pattern-visualization-creational-design-patterns-29gj</guid>
      <description>&lt;p&gt;&lt;em&gt;Refactoring &lt;a href="https://refactoring.guru/design-patterns" rel="noopener noreferrer"&gt;Guru&lt;/a&gt; already has the best blog to learn Design patterns. Here I am just trying to give a brief about each design.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Design patterns are solutions to recurring problems and design paradigms.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Creational design patterns provide various mechanisms for object creation, increasing flexibility and the reuse of existing code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We have around 5 patterns. You can get the Java code &lt;a href="https://github.com/GKcodebase/Design/tree/main/DesignPatternsDetailedImplementation/src/main/java/CreationalDesignPattern" rel="noopener noreferrer"&gt;here&lt;/a&gt;, &lt;code&gt;hope it works, built a couple of years back&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's dive into each one.......&lt;/p&gt;

&lt;h3&gt;
  
  
  Factory Method
&lt;/h3&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%2Fvnmhk6tfnh476yvj3c79.gif" 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%2Fvnmhk6tfnh476yvj3c79.gif" alt="Factory Method" width="700" height="394"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Factory Method is a design pattern that provides an interface for creating objects in a superclass while allowing subclasses to modify the types of objects that are created.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a pizza shop where you can order different &lt;code&gt;types&lt;/code&gt; of pizza, but the creation process (baking, adding toppings) is handled by specific pizza factories(&lt;code&gt;which I am not sure&lt;/code&gt;) for each type.&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%2Ff62r2utbxc6rmunt2ypd.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%2Ff62r2utbxc6rmunt2ypd.png" alt="Pizza shop" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another example that makes sense is different types of factories for other kinds of cars. &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%2Fdqhy2gtt4za0bjtvn9ek.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%2Fdqhy2gtt4za0bjtvn9ek.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's see a class diagram for the Factory class.&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%2Fqu6famulvgsubhpw1lct.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%2Fqu6famulvgsubhpw1lct.png" alt="Factory class diagram" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick Explanation of the Diagram
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Product (Interface)&lt;/strong&gt;: Defines the interface of objects that the factory method creates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteProduct&lt;/strong&gt;: The actual implementation of the Product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Creator (Abstract Class)&lt;/strong&gt;: Declares the factory method (&lt;code&gt;createProduct&lt;/code&gt;). It can also contain core business logic that relies on the Product objects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ConcreteCreator&lt;/strong&gt;: Overrides the factory method to return an instance of a ConcreteProduct.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Abstract Factory Method
&lt;/h3&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%2Ftael7kzaoc2ruz0e9rn6.gif" 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%2Ftael7kzaoc2ruz0e9rn6.gif" alt="Abstract Factory" width="600" height="337"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Abstract Factory is a design pattern that enables the creation of families of related objects without specifying their concrete classes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Abstract Factory is a &lt;code&gt;factory of factories&lt;/code&gt;, where you build a factory class from Abstract Factory, which in turn builds the type of class you need.&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%2Fydy3nhc3cnw4zpdhvvcw.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%2Fydy3nhc3cnw4zpdhvvcw.png" alt="Factory of Factory" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's check out the Abstract Factory class diagram. You can clearly see the difference between the factory class and why the abstract factory pattern is &lt;code&gt;Factory of Factories&lt;/code&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%2Fmn3wis9eamns0gsojd0b.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%2Fmn3wis9eamns0gsojd0b.png" alt="Abstract Factory class diagram" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick Explanation of the Diagram
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Abstract Factory (Interface)&lt;/strong&gt;: Declares a set of methods for creating each of the abstract products (e.g., &lt;code&gt;createProductA&lt;/code&gt;, &lt;code&gt;createProductB&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Factory&lt;/strong&gt;: Implements the creation methods to produce a specific flavor or family of products (e.g., &lt;code&gt;ConcreteFactory1&lt;/code&gt; only creates &lt;code&gt;ProductA1&lt;/code&gt; and &lt;code&gt;ProductB1&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Abstract Product (Interface)&lt;/strong&gt;: Defines the interface for a type of product (e.g., &lt;code&gt;ProductA&lt;/code&gt;), ensuring all variations of that product are compatible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Product&lt;/strong&gt;: The specific implementation of a product type, created by the corresponding concrete factory to ensure they match other products in the same family.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Singleton
&lt;/h3&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%2Fr618sryhmbsb7md7c3do.gif" 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%2Fr618sryhmbsb7md7c3do.gif" alt="Singleton" width="600" height="337"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Singleton is a design pattern that guarantees a class has only one instance while providing a global access point to this instance.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a single barista/coffee machine, the &lt;code&gt;single instance&lt;/code&gt;, that makes all kinds of coffee.&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%2Fgx970qc05wqkjx6x19fk.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%2Fgx970qc05wqkjx6x19fk.png" alt="Singleton Baristan" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A Singleton class will have a single instance.&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%2Fjmjkn9srxado1ld9npyf.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%2Fjmjkn9srxado1ld9npyf.png" alt="Singleton class diagram" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick Explanation of the Diagram
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Singleton Class&lt;/strong&gt;: The single class responsible for creating and managing its own unique instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;instance (Private Static Variable)&lt;/strong&gt;: A static member that holds the only instance of the class. The &lt;code&gt;$&lt;/code&gt; symbol (or the underline in standard UML) denotes a static member.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Singleton() (Private Constructor)&lt;/strong&gt;: A constructor with private visibility that prevents other objects from using the &lt;code&gt;new&lt;/code&gt; operator with this class.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;getInstance() (Public Static Method)&lt;/strong&gt;: The global access point. When called, it checks if the &lt;code&gt;instance&lt;/code&gt; is null; if so, it creates one. It then returns that same instance to every caller.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Prototype
&lt;/h3&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%2F8oyw217i8q59f5cvegcv.gif" 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%2F8oyw217i8q59f5cvegcv.gif" alt="Prototype" width="700" height="394"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Prototype is a creational design pattern that allows you to copy existing objects without making your code dependent on their classes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider a &lt;code&gt;cloning&lt;/code&gt; Machine, which is a good example of a prototype.&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%2Fq6045wrka8taq5xhakva.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%2Fq6045wrka8taq5xhakva.png" alt="Cloning Machine" width="800" height="800"&gt;&lt;/a&gt;&lt;br&gt;
Let's check the UML Diagram.&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%2F49gfiu0wwjbutivc1hzz.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%2F49gfiu0wwjbutivc1hzz.png" alt="Clonning Diagram" width="614" height="664"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick Explanation of the Diagram
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prototype (Interface)&lt;/strong&gt;: Declares the interface for cloning itself, usually consisting of a single &lt;code&gt;clone&lt;/code&gt; method.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Prototype&lt;/strong&gt;: Implements the cloning operation by copying its own data into a new object instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client&lt;/strong&gt;: Creates new objects by asking an existing prototype instance to clone itself instead of instantiating a class from scratch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Builder
&lt;/h3&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%2Fcvn8bubvlk8lyral8yu8.gif" 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%2Fcvn8bubvlk8lyral8yu8.gif" alt="Builder Pattern" width="700" height="394"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;The Builder design pattern allows you to construct complex objects step by step. This pattern enables the production of different types and representations of an object using the same construction code.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You travelled to 2050. Now you get a burger-building machine kiosk, which builds it step by step.&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%2Fl1l0s4vh0mpyuwmg03go.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%2Fl1l0s4vh0mpyuwmg03go.png" alt="Burger Builder" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visualization for Builder.&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%2Fq7j7zaobpvgz9rnfobpm.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%2Fq7j7zaobpvgz9rnfobpm.png" alt="Builder class diagram" width="322" height="1246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Explanation of the Diagram
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Director&lt;/strong&gt;: Defines the order in which to execute the building steps. It works with a builder object to create a specific product configuration (e.g., a "Vegan Burger" vs. a "Double Cheeseburger").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Builder (Interface)&lt;/strong&gt;: Declares all possible steps required to build a product. These steps are common to all types of builders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Concrete Builder&lt;/strong&gt;: Provides a specific implementation of the building steps. It is responsible for creating and assembling the parts of the complex object and returning the final product.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Product:&lt;/strong&gt; The resulting complex object. Unlike other creational patterns, different builders can produce products that do not follow a common interface (e.g., a "House" product vs. a "Manual" product).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Creational Design Patterns Overview
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Design Pattern&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Other Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Factory Method&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Subclasses decide object type&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;PizzaStore&lt;/code&gt; with regional pizza creators (&lt;code&gt;NYPizzaStore&lt;/code&gt;, &lt;code&gt;ChicagoPizzaStore&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Abstract Factory&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Creates related object families&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;GUIFactory&lt;/code&gt; for Windows/Mac button + checkbox pairs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Singleton&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;One instance, global access&lt;/td&gt;
&lt;td&gt;Single &lt;code&gt;Logger&lt;/code&gt; or &lt;code&gt;DatabaseConnectionPool&lt;/code&gt; across app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prototype&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Clone objects without class dependency&lt;/td&gt;
&lt;td&gt;Duplicate &lt;code&gt;Circle&lt;/code&gt;/&lt;code&gt;Rectangle&lt;/code&gt; shapes via &lt;code&gt;clone()&lt;/code&gt; method&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Builder&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Step-by-step complex object construction&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;HouseBuilder&lt;/code&gt; for &lt;code&gt;WoodenHouse&lt;/code&gt; or &lt;code&gt;StoneHouse&lt;/code&gt; variants&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>architecture</category>
      <category>design</category>
      <category>java</category>
      <category>oop</category>
    </item>
    <item>
      <title>API designs for microservice comparison.</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Thu, 05 Feb 2026 22:17:24 +0000</pubDate>
      <link>https://dev.to/gokul_gk/api-designs-for-microservice-comparison-39o4</link>
      <guid>https://dev.to/gokul_gk/api-designs-for-microservice-comparison-39o4</guid>
      <description>&lt;p&gt;I have created a separate blog for &lt;a href="https://dev.to/gokul_gk/getting-started-with-the-rest-api-in-spring-boot-2cek"&gt;REST&lt;/a&gt;, &lt;a href="https://dev.to/gokul_gk/graphql-for-beginners-389p"&gt;GraphQL&lt;/a&gt;, and &lt;a href="https://dev.to/gokul_gk/implementing-grpc-4llc"&gt;gRPC&lt;/a&gt;.&lt;br&gt;
The codebase for Imaginary Aquarium retail, implemented across all three APIs, can be found &lt;a href="https://github.com/GKcodebase/API_Architecture" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I tried to include images and tables for comparison.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. High-Level Architectural Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Aspect&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;REST&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Core Style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Resource-oriented&lt;/td&gt;
&lt;td&gt;Query language with a schema&lt;/td&gt;
&lt;td&gt;Remote Procedure Calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Transport&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP/1.1 (mostly)&lt;/td&gt;
&lt;td&gt;HTTP/1.1 or HTTP/2&lt;/td&gt;
&lt;td&gt;HTTP/2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JSON (XML optional)&lt;/td&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;td&gt;Protocol Buffers (binary)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Endpoints&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Multiple URL endpoints&lt;/td&gt;
&lt;td&gt;Single endpoint (&lt;code&gt;/graphql&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Method names within services&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typing/Schema&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Weak typing&lt;/td&gt;
&lt;td&gt;Strongly typed schema&lt;/td&gt;
&lt;td&gt;Strongly typed via &lt;code&gt;.proto&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tooling &amp;amp; Ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Very mature&lt;/td&gt;
&lt;td&gt;Growing fast&lt;/td&gt;
&lt;td&gt;Strong, but narrower scope&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Typical Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Public APIs, simple CRUD&lt;/td&gt;
&lt;td&gt;Flexible client-driven data needs&lt;/td&gt;
&lt;td&gt;High-performance microservices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  2. Performance &amp;amp; Efficiency
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Metric&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;REST&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Variable (depends on query complexity)&lt;/td&gt;
&lt;td&gt;Very low&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Throughput&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Moderate&lt;/td&gt;
&lt;td&gt;Depends (higher with precise queries)&lt;/td&gt;
&lt;td&gt;Highest&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Payload Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JSON (often larger)&lt;/td&gt;
&lt;td&gt;Depends on query&lt;/td&gt;
&lt;td&gt;Small (binary)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Over-fetching Risk&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;High&lt;/td&gt;
&lt;td&gt;Minimal (client defines data)&lt;/td&gt;
&lt;td&gt;Low (compact payloads)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streaming Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP streaming possible&lt;/td&gt;
&lt;td&gt;Subscriptions (via WebSockets)&lt;/td&gt;
&lt;td&gt;Built-in streaming&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  3. Developer Experience &amp;amp; Tooling
&lt;/h2&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%2F0hf9z7s7kojesodafhwa.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%2F0hf9z7s7kojesodafhwa.png" alt="Developer Experience &amp;amp; Tooling" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Security &amp;amp; Caching
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Security &amp;amp; Caching&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;REST&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;OAuth2, JWT, API keys&lt;/td&gt;
&lt;td&gt;JWT tokens, directive-based auth&lt;/td&gt;
&lt;td&gt;TLS/mTLS, ALTS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authorization&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Role-based&lt;/td&gt;
&lt;td&gt;Field-level controls possible&lt;/td&gt;
&lt;td&gt;Interceptor-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Native HTTP caching&lt;/td&gt;
&lt;td&gt;Custom strategies required&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Common Risks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard HTTP threats&lt;/td&gt;
&lt;td&gt;Query complexity &amp;amp; DoS&lt;/td&gt;
&lt;td&gt;Binary payload complexity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  5. Versioning &amp;amp; Evolution
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Versioning Strategy&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;REST&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;gRPC&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Versioning&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;URL/version headers&lt;/td&gt;
&lt;td&gt;Schema evolution &amp;amp; deprecation&lt;/td&gt;
&lt;td&gt;Proto backward-compatible changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Breaking Changes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Explicit version bump&lt;/td&gt;
&lt;td&gt;Avoid by deprecation&lt;/td&gt;
&lt;td&gt;Avoid by compat proto rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Schema Contract&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;td&gt;Defined via GraphQL schema&lt;/td&gt;
&lt;td&gt;Defined via &lt;code&gt;.proto&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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%2Fyp4t44r4uk4eog0j0cit.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%2Fyp4t44r4uk4eog0j0cit.png" alt="PROS and CONS" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>microservices</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Implementing gRPC.</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Thu, 05 Feb 2026 22:06:46 +0000</pubDate>
      <link>https://dev.to/gokul_gk/implementing-grpc-4llc</link>
      <guid>https://dev.to/gokul_gk/implementing-grpc-4llc</guid>
      <description>&lt;p&gt;gRPC is a framework developed by Google that provides an efficient, language-independent mechanism for making Remote Procedure Calls (RPCs). Its primary use case is to enhance the performance of these remote calls while maintaining compatibility across different programming languages. Remote procedure calls are crucial in microservices and distributed environments, where large volumes of data are transferred between services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core Principle
&lt;/h2&gt;

&lt;p&gt;gRPC is built on several core principles that contribute to its performance and capabilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Protocol Buffers&lt;/strong&gt;: gRPC employs Protocol Buffers for serialization, allowing efficient binary encoding of data. This reduces message size and minimizes the parsing and serialization overhead, resulting in faster communication.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strongly-typed contracts&lt;/strong&gt;: gRPC APIs rely on strongly-typed contracts defined with Protocol Buffers that specify the services, methods, and data types available. This establishes a straightforward, consistent interface between the client and the server, minimizing the risk of errors and misunderstandings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bi-directional streaming&lt;/strong&gt;: gRPC facilitates bi-directional streaming, allowing clients and servers to exchange messages simultaneously. This feature enhances communication efficiency, particularly for large or real-time data transfers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language-agnostic:&lt;/strong&gt; gRPC is intended to be language-agnostic, offering official support for various programming languages such as C++, Java, Python, and Go. This flexibility allows developers to select the most appropriate language for their project without facing compatibility issues.&lt;/li&gt;
&lt;/ol&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%2F58eomwnl6acmfzlmmz52.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%2F58eomwnl6acmfzlmmz52.png" alt="gRPC Core Concept" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-performance applications&lt;/li&gt;
&lt;li&gt;Microservices architecture&lt;/li&gt;
&lt;li&gt;Applications that require high scalability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;gRPC is an excellent choice for performance-centric, scalable APIs in distributed systems, microservices, and real-time applications. It supports multiple languages and platforms with efficient binary data. It's ding. It's ideal for teams experienced in low-level programming and network communication, enabling fast, reliable APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC vs REST API: Comparison Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;gRPC&lt;/th&gt;
&lt;th&gt;REST&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Protocol&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HTTP/2&lt;/td&gt;
&lt;td&gt;HTTP/1.1 (or HTTP/2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Message Format&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Protocol Buffers (Binary)&lt;/td&gt;
&lt;td&gt;JSON, XML (Text)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;⚡ Faster (binary serialization)&lt;/td&gt;
&lt;td&gt;Slower (text parsing)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Payload Size&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Smaller (~3-10x)&lt;/td&gt;
&lt;td&gt;Larger&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Latency&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Bandwidth Usage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower&lt;/td&gt;
&lt;td&gt;Higher&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Code Generation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Automatic (from .proto files)&lt;/td&gt;
&lt;td&gt;Manual or template-based&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Browser Support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Limited (gRPC-Web required)&lt;/td&gt;
&lt;td&gt;Native support&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;RPC (function calls)&lt;/td&gt;
&lt;td&gt;Resource-oriented (URIs)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;URL Routing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Service.Method&lt;/td&gt;
&lt;td&gt;RESTful paths (/resource/id)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HTTP Methods&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Uses POST for all&lt;/td&gt;
&lt;td&gt;GET, POST, PUT, DELETE, PATCH&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Caching&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Difficult (custom logic)&lt;/td&gt;
&lt;td&gt;Built-in (HTTP caching)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Streaming&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Bidirectional streaming&lt;/td&gt;
&lt;td&gt;Request-response only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Connection&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Persistent (multiplexed)&lt;/td&gt;
&lt;td&gt;Per-request&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Learning Curve&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Steeper&lt;/td&gt;
&lt;td&gt;Easier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Ecosystem&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Growing&lt;/td&gt;
&lt;td&gt;Mature &amp;amp; established&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Documentation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Code-generated (proto)&lt;/td&gt;
&lt;td&gt;Manual documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Debugging&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Harder (binary format)&lt;/td&gt;
&lt;td&gt;Easier (JSON readable)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mobile Friendly&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;td&gt;Very good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;IoT/Edge Computing&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Good&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Real-time Features&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Excellent (streaming)&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Interceptors/Middleware&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in&lt;/td&gt;
&lt;td&gt;Manual implementation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standardized (gRPC codes)&lt;/td&gt;
&lt;td&gt;HTTP status codes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Authentication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;JWT, OAuth, Certificates&lt;/td&gt;
&lt;td&gt;OAuth, API Keys, JWT&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Microservices, Real-time, Mobile&lt;/td&gt;
&lt;td&gt;Public APIs, Web services&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Java Implementation
&lt;/h2&gt;

&lt;p&gt;Clone this Git &lt;a href="https://github.com/GKcodebase/API_Architecture/tree/main/gRPC" rel="noopener noreferrer"&gt;repo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run these commands to build and run the applications&lt;br&gt;
&lt;code&gt;mvn clean install&lt;/code&gt;&lt;br&gt;
&lt;code&gt;mvn spring-boot:run&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Expected outcome&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🐠 ==========================================
🐠 AquaWorld Pet Store gRPC API
🐠 ==========================================
🐠 gRPC Server started on port 9090
🐠 Test with grpcurl: grpcurl -plaintext localhost:9090 list
🐠 ==========================================
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Test Application&lt;/strong&gt;&lt;br&gt;
install grpcurl&lt;br&gt;
&lt;em&gt;grpcurl - Command-line tool for testing gRPC APIs&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# macOS
brew install grpcurl

# Linux (requires Go)
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected Result&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;com.aquaworld.grpc.auth.AuthService
com.aquaworld.grpc.order.OrderService
com.aquaworld.grpc.payment.PaymentService
com.aquaworld.grpc.product.ProductService
grpc.reflection.v1.ServerReflection
grpc.reflection.v1alpha.ServerReflection
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Follow the ReadMe file to test the remaining functionalities.&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%2Fxg14vl1jgcqvihw7jacy.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%2Fxg14vl1jgcqvihw7jacy.png" alt="gRPC Application" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  gRPC Design and Best Practices
&lt;/h2&gt;

&lt;h3&gt;
  
  
  API Versioning in gRPC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Versioning via Proto Packages&lt;/strong&gt; 
The recommended approach is to version your API using the package name in your .proto files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field Numbers Are Sacred&lt;/strong&gt;
In Protocol Buffers, field numbers must never be reused.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Don't Delete&lt;/strong&gt;
Instead of removing fields, mark them as deprecated.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Error Handling in gRPC
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use gRPC Status Codes Correctly&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;OK&lt;/code&gt; – Success&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;INVALID_ARGUMENT&lt;/code&gt; – Client sent invalid data&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NOT_FOUND&lt;/code&gt;– Resource does not exist&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ALREADY_EXISTS&lt;/code&gt; – Duplicate resource&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PERMISSION_DENIED&lt;/code&gt; – Authorization failure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;UNAVAILABLE – Service&lt;/code&gt; temporarily unavailable
Avoid returning UNKNOWN or INTERNAL for client-side errors.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Rich Error Details via Trailers&lt;/strong&gt;
gRPC offers rich error metadata, enabling clients to handle failures programmatically through structured error details in trailers.&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deadlines, Timeouts, Retries, and Load Balancing
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Always Set Deadlines&lt;/strong&gt;
A gRPC deadline defines how long a client is willing to wait for a response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Retries Must Be Intentional&lt;/strong&gt;
Retries can improve resilience—but only when used carefully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing Considerations&lt;/strong&gt;
HTTP2'sssHTTP/2'ss long-lived connections, which change how load balancing works.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose gRPC if you need:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; High performance and low latency&lt;/li&gt;
&lt;li&gt; Efficient mobile/IoT communication&lt;/li&gt;
&lt;li&gt; Real-time bidirectional streaming&lt;/li&gt;
&lt;li&gt; Microservices architecture&lt;/li&gt;
&lt;li&gt; Internal APIs between services&lt;/li&gt;
&lt;li&gt; Minimal bandwidth usage&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>microservices</category>
      <category>performance</category>
    </item>
    <item>
      <title>GraphQL for Beginners</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Tue, 27 Jan 2026 19:45:46 +0000</pubDate>
      <link>https://dev.to/gokul_gk/graphql-for-beginners-389p</link>
      <guid>https://dev.to/gokul_gk/graphql-for-beginners-389p</guid>
      <description>&lt;h2&gt;
  
  
  Why GraphQL Emerged: Solving the Pain Points of REST APIs
&lt;/h2&gt;

&lt;p&gt;APIs are the backbone of how applications communicate and exchange data. REST has been the go-to architectural style for building APIs (at least for me). It's straightforward, relying on standard HTTP methods, with endpoints structured around resources (e.g., &lt;code&gt;/users/123&lt;/code&gt; to fetch a specific user). As applications grew more complex, think mobile apps, single-page web apps, and microservices, REST started showing its limitations. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Over-Fetching and Under-Fetching Problems in REST
&lt;/h3&gt;

&lt;p&gt;One of the biggest headaches with REST is overfetching and underfetching of data.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Overfetching happens when an API endpoint returns more data than the client actually needs.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Imagine a social media app that displays only a user's name and profile picture could use a REST endpoint like &lt;code&gt;/users/123&lt;/code&gt; to return only the relevant data. Returning the entire user object, including unnecessary details, wastes bandwidth and slows performance, especially on mobile devices.&lt;br&gt;
On the other side, &lt;strong&gt;&lt;em&gt;underfetching occurs when a single endpoint doesn't provide enough data, requiring the client to make multiple API calls&lt;/em&gt;.&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%2F9kpm5ky5bg0ukn0t2ry7.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%2F9kpm5ky5bg0ukn0t2ry7.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GraphQL flips this script by empowering clients to specify precisely which data they need in a single request. Instead of rigid endpoints, clients send a query that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;query {
  products {
    id
    name
    category
    price
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server responds with that exact structure, reducing network overhead, minimizing round-trip times, and speeding up development by preventing frontend teams from being blocked by backend changes.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Strongly Typed&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Complete type system defined in schema&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Declarative&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client specifies what data is needed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Single Endpoint&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;All requests go to &lt;code&gt;/graphql&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Efficient&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No over-fetching or under-fetching&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Self-Documenting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Schema is the API documentation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Developer-Friendly&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Built-in playground (GraphiQL)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  GraphQL as a Query Language and Schema-Based Runtime
&lt;/h3&gt;

&lt;p&gt;GraphQL is both a query language for your data and a runtime that executes queries based on a defined schema, which describes available data types, their relationships, and how to query them. It's usually written in Schema Definition Language (SDL), like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type User {
  id: ID!
  name: String!
  posts: [Post!]!
}
type Post {
  title: String!
  content: String
}
type Query {
  user(id: ID!): User
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This schema is accessed through a single HTTP endpoint (usually &lt;code&gt;/graphql&lt;/code&gt;), unlike REST's multiple URLs. Clients POST their queries to this endpoint, which validates them against the schema for type safety and rejects invalid requests. While transport-agnostic, it typically uses HTTP for easy integration with existing systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Core GraphQL Concepts: Building Blocks for Powerful APIs
&lt;/h2&gt;

&lt;h4&gt;
  
  
  The Schema: Types, Queries, Mutations, and Strong Typing.
&lt;/h4&gt;

&lt;p&gt;The schema is the foundation of any GraphQL API. It's a blueprint that defines:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Types: These describe your data models.&lt;/strong&gt; Scalar types (e.g., String, Int, Boolean) are built-in, while object types (like User or Post) are custom. You can define enums, interfaces, unions, and input types for added complexity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Queries: The entry points for reading data.&lt;/strong&gt; Think of them as read-only operations. The Query type in the schema lists available queries, like &lt;code&gt;user(id: ID!)&lt;/code&gt;, which returns a User object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutations: For writing data, such as creating, updating, or deleting.&lt;/strong&gt; Similar to queries but side-effecting.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;GraphQL enforces &lt;strong&gt;strong typing for every field, allowing runtime checks against defined types.&lt;/strong&gt; This catches errors early, avoiding issues like receiving a string instead of a number. In contrast, REST often uses loosely typed JSON, which can lead to fragile client code.&lt;/p&gt;

&lt;h4&gt;
  
  
  Operations: Queries, Mutations, and Subscriptions
&lt;/h4&gt;

&lt;p&gt;GraphQL supports three main operation types:&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%2Fzlrsfkguetpiy12uoq5f.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%2Fzlrsfkguetpiy12uoq5f.png" alt="GraphQL Concepts" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Queries: For fetching data.&lt;/strong&gt; They're idempotent (safe to retry) and can include arguments, fragments (reusable query parts), and variables for dynamic inputs. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutations: For modifying data.&lt;/strong&gt; They follow the same structure as queries but signal changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptions: For real-time updates.&lt;/strong&gt; Unlike queries and mutations (which are request-response), subscriptions use WebSockets to push data from server to client when events occur, like new messages in a chat app. A subscription might be &lt;code&gt;subscription { newMessage(chatId: ID!): Message }&lt;/code&gt;, keeping the client in sync without polling.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Resolvers: The Data-Fetching Glue
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Behind every field in a query or mutation is a resolver, a function that knows how to fetch or compute the data for that field&lt;/strong&gt;. Resolvers are like mini-handlers, executed in a tree-like fashion as the query resolves from root to leaves.&lt;br&gt;
In GraphQL, the root resolver fetches a user, while child resolvers retrieve related posts. This modular design allows data to be pulled from various sources, unlike REST controllers, which handle entire responses at once, leading to monolithic code. Resolvers enhance separation of concerns, enabling independent optimization and security for each field. &lt;/p&gt;
&lt;h3&gt;
  
  
  Java Code Example.
&lt;/h3&gt;

&lt;p&gt;Let's convert the &lt;a href="https://dev.to/gokul_gk/getting-started-with-the-rest-api-in-spring-boot-2cek"&gt;REST example&lt;/a&gt; for project Aquaworld to GraphQL.&lt;/p&gt;
&lt;h4&gt;
  
  
  REST vs GraphQL
&lt;/h4&gt;
&lt;h5&gt;
  
  
  AquaWorld Endpoint Comparison
&lt;/h5&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operation&lt;/th&gt;
&lt;th&gt;REST&lt;/th&gt;
&lt;th&gt;GraphQL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Get all products&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /api/v1/products&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query { products { ... } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Get single product&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /api/v1/products/2001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query { product(id: 2001) { ... } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Create order&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;POST /api/v1/orders&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mutation { createOrder(input: {...}) { ... } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Get order with items&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;2 requests&lt;/td&gt;
&lt;td&gt;1 request with nested data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Filter by name&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GET /api/v1/products/search?name=...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;query { searchProducts(name: "...") { ... } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h5&gt;
  
  
  Data Fetching Comparison
&lt;/h5&gt;

&lt;p&gt;&lt;strong&gt;REST&lt;/strong&gt;: Fixed response structure (over-fetching)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;/api/v&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;/products/&lt;/span&gt;&lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Red Guppy Male"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"category"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"guppies"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;5.99&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"imageUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-15"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GraphQL&lt;/strong&gt;: Client specifies needed fields&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;stock&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Returns ONLY: name, price, stock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Quick Start Guide
&lt;/h4&gt;

&lt;p&gt;Pull code from the API Architecture &lt;a href="https://github.com/GKcodebase/API_Architecture" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# 1. Navigate to the project.
cd /Users/gokulg.k/Documents/GitHub/API_Architecture/GraphQL/aquaworld-graphql-api

# 2. Build
mvn clean install

# 3. Run
mvn spring-boot:run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check out the complete &lt;a href="https://github.com/GKcodebase/API_Architecture/blob/main/GraphQL/DOCUMENTATION_INDEX.md" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for building the project from scratch, the API schema, the Visual Guide, and more.&lt;/p&gt;

&lt;h4&gt;
  
  
  GraphQL Endpoint
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query &amp;amp; Mutation&lt;/strong&gt;: &lt;code&gt;http://localhost:8080/aquaworld/graphql&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Interactive Playground&lt;/strong&gt;: &lt;code&gt;http://localhost:8080/aquaworld/graphiql&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Make Use of the GraphQL playground to test all queries.&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%2F3v4d4pyn654vx0x1nxje.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%2F3v4d4pyn654vx0x1nxje.png" alt="GraphQL playground" width="800" height="400"&gt;&lt;/a&gt;&lt;br&gt;
&lt;code&gt;Note: All the magic happens inside the resolver with the help of some annotations.&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  GraphQL Annotations in Spring Boot (&lt;code&gt;spring-graphql&lt;/code&gt;)
&lt;/h4&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;th&gt;Description / When to Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@Controller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Marks the class as a GraphQL controller (same annotation as in Spring MVC/REST, but used here for GraphQL resolvers)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@QueryMapping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maps the method to a field in the root &lt;code&gt;Query&lt;/code&gt; type — used for top-level read/fetch operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@MutationMapping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maps the method to a field in the root &lt;code&gt;Mutation&lt;/code&gt; type — used for top-level create/update/delete operations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@SubscriptionMapping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maps the method to a field in the root &lt;code&gt;Subscription&lt;/code&gt; type — used for real-time updates (WebSocket-based)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@SchemaMapping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Most flexible mapping — connects the method to &lt;strong&gt;any&lt;/strong&gt; field in the schema (root-level or nested object fields)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@BatchMapping&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Batch-loads related data for multiple parent objects at once — prevents N+1 query problem in lists/relationships&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@Argument&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Explicitly binds a GraphQL argument to a method parameter (optional when parameter name matches the argument name)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  GraphQL Design and Best Practices: Building APIs That Age Gracefully
&lt;/h2&gt;

&lt;p&gt;GraphQL’s flexibility is powerful, but without discipline, it can lead to bloated schemas, performance nightmares, and maintenance headaches. The following best practices help create client-centric, stable, and performant GraphQL APIs that evolve smoothly over time.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the Schema Client-Centric and Stable – Evolve by Addition, Not Replacement
&lt;code&gt;One of GraphQL’s biggest promises is that clients dictate the shape of the data, not the server.&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Design from the UI/use-case perspective&lt;/li&gt;
&lt;li&gt;Avoid breaking changes at all costs&lt;/li&gt;
&lt;li&gt;Evolve by addition instead of versioning the whole API&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Use Pagination Patterns (Connections / Cursors) to Avoid Huge Responses
GraphQL makes it dangerously easy to write queries that return thousands of items (e.g., products { id name price }). Without limits, this kills performance and can even DDoS your own server.
&lt;code&gt;Best practice: Always paginate lists using the Relay-style Connections pattern.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Handle Errors Gracefully Using the &lt;code&gt;errors&lt;/code&gt; Field + Custom Extensions
Unlike REST (where HTTP status + body tells the story), GraphQL always returns 200 OK if the query is syntactically valid—even if business logic fails. All errors live in the top-level errors array.
&lt;code&gt;Best practice: Structured, machine-readable errors.&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&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%2F5w64joci0tq9m1qk5bgq.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%2F5w64joci0tq9m1qk5bgq.png" alt="Best Practices in GraphQL" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>api</category>
      <category>architecture</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Getting started with the REST API in Spring Boot.</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Tue, 20 Jan 2026 07:02:59 +0000</pubDate>
      <link>https://dev.to/gokul_gk/getting-started-with-the-rest-api-in-spring-boot-2cek</link>
      <guid>https://dev.to/gokul_gk/getting-started-with-the-rest-api-in-spring-boot-2cek</guid>
      <description>&lt;h2&gt;
  
  
  What is REST?
&lt;/h2&gt;

&lt;p&gt;Representational state transfer (&lt;a href="https://www.woodruff.dev/category/blog/http-rest/" rel="noopener noreferrer"&gt;REST&lt;/a&gt;) or RESTful web services is a way to provide interoperability between computer systems on the Internet. &lt;br&gt;
It is an architectural style for building distributed systems (defined by Roy Fielding in 2000), with six main constraints:&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%2Fohryfp6zt4dyb20fg7h9.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%2Fohryfp6zt4dyb20fg7h9.png" alt="REST Constraints" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Uniform Interface&lt;/strong&gt; - Keeping Things Consistent

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Resource identification&lt;/em&gt; through URIs (e.g.,/users/123, /orders)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Manipulation of resources&lt;/em&gt; through representations (usually JSON     today)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Self-descriptive messages&lt;/em&gt; (HTTP headers tell you content-type, status, caching rules…)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;HATEOAS&lt;/em&gt; (Hypermedia as the Engine of Application State — optional, rarely used in practice)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client–Server&lt;/strong&gt; - Separation of Responsibilities&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stateless communication&lt;/strong&gt; - Every Request Stands Alone&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cacheable&lt;/strong&gt; - Speeding Things Up&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Layered system&lt;/strong&gt; - Scalability &amp;amp; Security&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code on demand&lt;/strong&gt; - allows the server to send executable code(I have never used)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://github.com/GKcodebase/API_Architecture/tree/main/REST" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is a sample retail pet store project in SpringBoot, an imaginary pet store that currently sells pet fish, &lt;strong&gt;Aqua World&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Core REST Concepts
&lt;/h2&gt;
&lt;h4&gt;
  
  
  1. Resources and URIs (Uniform Resource Identifier)
&lt;/h4&gt;

&lt;p&gt;In REST, everything is a resource — think of it as a noun (something that can be created, read, updated, deleted).&lt;br&gt;
Example URI in AquaWorld App:&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%2F2qr1p5ald8z7cdbpsejl.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%2F2qr1p5ald8z7cdbpsejl.png" alt="Order Endpoints" width="800" height="385"&gt;&lt;/a&gt;&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%2Fwtbop5hj577lsh41uy9b.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%2Fwtbop5hj577lsh41uy9b.png" alt="Authentication Endpoints" width="800" height="465"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  2. HTTP Methods &amp;amp; Status Codes
&lt;/h4&gt;

&lt;p&gt;REST uses standard HTTP methods to express what we want to do with a resource.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Idempotent?&lt;/th&gt;
&lt;th&gt;Common Status Codes&lt;/th&gt;
&lt;th&gt;Typical Use Case&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GET&lt;/td&gt;
&lt;td&gt;Retrieve resource(s)&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;td&gt;Read data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HEAD&lt;/td&gt;
&lt;td&gt;Same as GET but no body&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;td&gt;Check existence/metadata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;POST&lt;/td&gt;
&lt;td&gt;Create new resource&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;201 Created&lt;/td&gt;
&lt;td&gt;Create user, submit form, place order&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PUT&lt;/td&gt;
&lt;td&gt;Replace entire resource&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;td&gt;Update/replace whole user profile&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PATCH&lt;/td&gt;
&lt;td&gt;Partially update resource&lt;/td&gt;
&lt;td&gt;Usually&lt;/td&gt;
&lt;td&gt;200 OK&lt;/td&gt;
&lt;td&gt;Change only email or status&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DELETE&lt;/td&gt;
&lt;td&gt;Remove resource&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;204 No Content&lt;/td&gt;
&lt;td&gt;Delete user or order&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h5&gt;
  
  
  Note:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safe methods&lt;/strong&gt;: GET, HEAD — can be called any number of times without changing server state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Idempotent methods&lt;/strong&gt;: GET, HEAD, PUT, DELETE — repeating the same request multiple times has the same effect as doing it once&lt;/li&gt;
&lt;li&gt;&lt;code&gt;POST is neither safe nor (strictly) idempotent — that's why it's used for creation&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;
  
  
  Common status codes everyone should know:
&lt;/h5&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;200 OK&lt;/em&gt; → success (with body)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;201 Created&lt;/em&gt; → resource created successfully&lt;/li&gt;
&lt;li&gt;204 No Content → success, but no response body (common for DELETE/PUT)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;400 Bad Request&lt;/em&gt; → client sent invalid data&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;401 Unauthorized&lt;/em&gt; → authentication required&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;403 Forbidden&lt;/em&gt; → authenticated but not allowed&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;404 Not Found&lt;/em&gt; → resource doesn't exist&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;409 Conflict&lt;/em&gt; → resource conflict
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;500 Internal Server Error&lt;/em&gt; → something broke on the server side&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;503 Service Unavailable&lt;/em&gt; → service temporarily down&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  3. Representations &amp;amp; Content Negotiation
&lt;/h4&gt;

&lt;p&gt;A resource can be represented in different formats.&lt;br&gt;
Most common today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;JSON → application/json (the default in 2025–2026)
XML  → application/xml (still used in enterprise, SOAP legacy)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Content Negotiation&lt;/em&gt; — how client and server agree on format:&lt;br&gt;
Client tells server what it accepts via Accept header:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Accept: application/json, application/xml;q=0.9, */*;q=0.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Server responds with Content-Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Content-Type: application/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F73id0mvfj4r96b5ljjzn.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%2F73id0mvfj4r96b5ljjzn.png" alt="Core REST" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Java Example
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Steps to create a sample project:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;1. Create a Spring Boot project&lt;/strong&gt;&lt;br&gt;
Use Spring initializer to create a sample project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://start.spring.io/" rel="noopener noreferrer"&gt;https://start.spring.io/&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project: Maven
Language: Java
Spring Boot: 3.3.x (Latest)
Java: 21
Dependencies:
  - Spring Web (spring-boot-starter-web)
  - Lombok (optional, for reducing boilerplate)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Maven Dependencies (pom.xml)&lt;/strong&gt;&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;dependencies&amp;gt;
    &amp;lt;!-- Spring Web for REST APIs --&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-web&amp;lt;/artifactId&amp;gt;
    &amp;lt;/dependency&amp;gt;
    &amp;lt;!-- Lombok for @Data annotation (optional) --&amp;gt;
    &amp;lt;dependency&amp;gt;
        &amp;lt;groupId&amp;gt;org.projectlombok&amp;lt;/groupId&amp;gt;
        &amp;lt;artifactId&amp;gt;lombok&amp;lt;/artifactId&amp;gt;
        &amp;lt;optional&amp;gt;true&amp;lt;/optional&amp;gt;
    &amp;lt;/dependency&amp;gt;
&amp;lt;/dependencies&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Application Properties&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pring.application.name=book-api
server.port=8080
server.servlet.context-path=/api
# Logging
logging.level.root=INFO
logging.level.com.example=DEBUG
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Building controller&lt;/strong&gt;&lt;br&gt;
The Controller handles HTTP requests and returns responses.&lt;br&gt;
In Spring Boot, we use annotations to build REST APIs. Some commonly needed Annotations:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Annotation&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;@RestController&lt;/td&gt;
&lt;td&gt;Marks the class as a REST API controller and returns JSON responses&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@RequestMapping("/books")&lt;/td&gt;
&lt;td&gt;Base path for all endpoints in this controller&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@GetMapping&lt;/td&gt;
&lt;td&gt;Maps HTTP GET requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@PostMapping&lt;/td&gt;
&lt;td&gt;Maps HTTP POST requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@PutMapping&lt;/td&gt;
&lt;td&gt;Maps HTTP PUT requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@DeleteMapping&lt;/td&gt;
&lt;td&gt;Maps HTTP DELETE requests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@PathVariable&lt;/td&gt;
&lt;td&gt;Extracts values from the URL path (e.g., {id})&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;@RequestBody&lt;/td&gt;
&lt;td&gt;Binds JSON request body to a Java object&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Project Aquaworld&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can clone the Aqua World project and follow the steps to run the application.&lt;br&gt;
Use IntelliJ IDEA or your favourite IDE to run the application.&lt;br&gt;
Or run these commands in the terminal&lt;br&gt;
&lt;code&gt;mvn clean install&lt;/code&gt;&lt;br&gt;
&lt;code&gt;mvn start&lt;/code&gt;&lt;br&gt;
Check out Swagger UI to run all the endpoints.&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%2Fisl9bpsd8q6dwlv8sk0l.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%2Fisl9bpsd8q6dwlv8sk0l.png" alt="Swagger" width="800" height="501"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  REST Design Tips
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Noun-based URIs, plural collections, predictable patterns&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always use nouns for resources (not verbs):&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Good: /users, /orders/123&lt;/code&gt;&lt;br&gt;
&lt;code&gt;Bad: /getUser, /createOrder&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Use plural for collections: /users, /products (not /user or /usersList)&lt;br&gt;
Keep patterns predictable &amp;amp; consistent:&lt;br&gt;
&lt;code&gt;/resource → collection&lt;/code&gt;&lt;br&gt;
&lt;code&gt;/resource/{id} → single item&lt;/code&gt;&lt;br&gt;
&lt;code&gt;/resource/{id}/sub-resource → nested (e.g. /users/123/orders)&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid deep nesting (&amp;gt;2–3 levels)&lt;br&gt;
Use query params or references instead&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Use proper status codes &amp;amp; error payloads&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Never return a generic 200 OK with an error message in the body — it's misleading
&lt;em&gt;Refer codes above.&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Prefer RFC 9457application/problem+json for errors (modern standard):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; JSON{
  "type": "https://example.com/errors/validation",
  "title": "Validation Failed",
  "status": 400,
  "detail": "Email is already in use",
  "instance": "/users",
  "invalidParams": [ ... ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Much better than plain 
&lt;code&gt;{ "error": "something went wrong" }&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Basic versioning strategies&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Two main approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;URL versioning (most common &amp;amp; beginner-friendly)
&lt;code&gt;/v1/users, /v2/users&lt;/code&gt;
Easy to read, cache, and route in the gateway. &lt;/li&gt;
&lt;li&gt;Header versioning (more RESTful)
&lt;code&gt;Accept: application/vnd.myapi.v2+json&lt;/code&gt;
Cleaner URLs, but harder for humans &amp;amp; some clients&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Avoid versioning every minor change&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Only version when you break backward compatibility (breaking changes, removing fields, changing semantics)&lt;/li&gt;
&lt;li&gt;Minor additions (new optional fields) → no new version needed&lt;/li&gt;
&lt;li&gt;Semantic Versioning rule: major version bump only for breaking changes&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing and Tooling for REST APIs
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Unit/Integration tests (Spring ecosystem)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;@WebMvcTest — &lt;em&gt;lightweight, fast unit test for controllers only
Mocks the service layer&lt;/em&gt;
Example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@WebMvcTest(UserController.class)
class UserControllerTest {
    @Autowired MockMvc mockMvc;

    @Test
    void shouldReturnUser() throws Exception {
        mockMvc.perform(get("/users/1"))
               .andExpect(status().isOk())
               .andExpect(jsonPath("$.name").value("John"));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;MockMvc → simulate HTTP requests without starting a full server&lt;/li&gt;
&lt;li&gt;Use TestRestTemplate or WebTestClient for full integration tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Contract tests&lt;/strong&gt;&lt;br&gt;
Goal: Ensure provider (API) &amp;amp; consumer (client) agree on contract&lt;br&gt;
Popular tools:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Spring Cloud Contract

&lt;ul&gt;
&lt;li&gt;Producer generates stubs + contract tests&lt;/li&gt;
&lt;li&gt;Consumer uses stubs for testing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;OpenAPI/Swagger driven (most common in 2025–2026)

&lt;ul&gt;
&lt;li&gt;Generate OpenAPI spec → use it for:&lt;/li&gt;
&lt;li&gt;Validation (springdoc + openapi-validator)&lt;/li&gt;
&lt;li&gt;Client codegen (openapi-generator)&lt;/li&gt;
&lt;li&gt;Contract testing (e.g. Dredd, Schemathesis, REST assured + OpenAPI)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&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%2Feonek1tdshmo9scqzpdf.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%2Feonek1tdshmo9scqzpdf.png" alt="Best Practices" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>restapi</category>
      <category>api</category>
      <category>programming</category>
      <category>microservices</category>
    </item>
    <item>
      <title>SOLID Design Principle</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Tue, 13 Jan 2026 07:59:52 +0000</pubDate>
      <link>https://dev.to/gokul_gk/solid-design-principle-5g90</link>
      <guid>https://dev.to/gokul_gk/solid-design-principle-5g90</guid>
      <description>&lt;h2&gt;
  
  
  What is SOLID?
&lt;/h2&gt;

&lt;p&gt;SOLID stands for: &lt;strong&gt;Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion&lt;/strong&gt;. Robert C. Martin popularized these principles, and they are now widely used as the foundation for maintainable object-oriented design.&lt;/p&gt;

&lt;p&gt;SOLID is a way to manage dependencies between classes, allowing you to add features without breaking existing Code. Empirical work shows that applying SOLID tends to improve modularity, reduce coupling, and make it easier for developers to understand and extend Code.&lt;br&gt;
These are some &lt;a href="https://github.com/GKcodebase/Design/tree/main/ObjectOrientedDesign/src/main/java/SOLID" rel="noopener noreferrer"&gt;example&lt;/a&gt; in Java for the SOLID principle.&lt;/p&gt;
&lt;h3&gt;
  
  
  Single Responsibility Principle (SRP)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A class should have one, and only one, reason to change.&lt;/strong&gt;&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%2Fx1wlbzteme1maut65iyb.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%2Fx1wlbzteme1maut65iyb.png" alt="Single Responsibility Principle" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
The chef's knife is a good example of SRP, as a tool with a single, focused responsibility: cutting. It doesn't try to be a spoon or a whisk.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package SOLID;
//A class should have only one reason to change, meaning it should have only one responsibility.
public class SingleResponsibilityPrinciple {
    //Example violating SRP
    class Employee {
        public void calculatePay() {
            //Code to calculate pay
        }
        public void saveEmployeeData() {
            //Code to save employee data to the database
        }
    }
    // Refactored classes adhering to SRP
    class PayCalculator {
        public void calculatePay() {
            //Code to calculate pay
        }
    }
    class EmployeeDataSaver {
        public void saveEmployeeData() {
            //Code to save employee data to the database
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the above code, the first version (Employee class) violates SRP because it has multiple responsibilities as it both calculates an employee's pay and saves employee data to the database.&lt;br&gt;
After refactoring, these responsibilities are split into two separate classes (PayCalculator and EmployeeDataSaver), so each class has only one reason to change and follows the Single Responsibility Principle.&lt;/p&gt;
&lt;h3&gt;
  
  
  Open/Closed Principle (OCP)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Classes should be open for extension, but closed for modification.&lt;/strong&gt;&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%2Fw9sh3c6bty52d1ag2a96.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%2Fw9sh3c6bty52d1ag2a96.png" alt="Open/Closed Principle" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
A Lego brick is another good example; it's closed for modification, but can be modified by adding other bricks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package SOLID;
/**
 * Software entities (classes, modules, functions) should be open for extension but closed for modification.
 * */
public class OpenClosePrinciple {
    //Example violating OCP
    abstract class Rectangle {
        public double area(double length, double width) {
            return length * width;
        }
    }
    // Extending Rectangle  and  modifying are
    class Square extends Rectangle {
        public double area(double side) {
            return side * side;
        }
    }
    // OCP Strategy  Use proper abstraction (most common &amp;amp; clean)
    interface Shape {
        double area();           // closed for modification
    }
    // Now we can add any new shape without touching the existing Code
    class Rectangleocp implements Shape {
        private double length;
        private double width;

        public Rectangleocp(double length, double width) {
            this.length = length;
            this.width = width;
        }
        @Override
        public double area() {
            return length * width;
        }
    }
    class Squareocp implements Shape {
        private double side;

        public Squareocp(double side) {
            this.side = side;
        }
        @Override
        public double area() {
            return side * side;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the code above, the bad Example (inheritance from concrete Rectangle) forces the modification of existing Code or awkward design when adding new shapes.&lt;br&gt;
The reasonable approach is to use a stable Shape interface that allows you to add any new shape by writing new classes without ever touching existing ones.&lt;/p&gt;
&lt;h3&gt;
  
  
  Liskov Substitution Principle (LSP)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Subtypes must be substitutable for their base types without breaking the program's expectations&lt;/strong&gt;&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%2F4ctpktjlrzdubrwkydac.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%2F4ctpktjlrzdubrwkydac.png" alt="Liskov Substitution Principle" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
Another real-life example is a universal power strip acts as a &lt;em&gt;"superclass,"&lt;/em&gt; and any plug type (US, UK, EU) is a &lt;em&gt;"subclass"&lt;/em&gt; that can be used with it without any issues, as they all fulfill the contract of providing a power connection.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package SOLID;

/**
 * Subtypes must be substitutable for their base types without affecting the correctness of the program.
 * **/
public class LiskovSubstitutionPrinciple {
    // Example violating LSP (classic Rectangle-Square problem)
    static class Rectangle {
        protected int width;
        protected int height;
        public void setWidth(int width) {
            this.width = width;
        }
        public void setHeight(int height) {
            this.height = height;
        }
        public int area() {
            return width * height;
        }
    }
    static class Square extends Rectangle {
        @Override
        public void setWidth(int width) {
            this.width = width;
            this.height = width;   // Forces height = width
        }
        @Override
        public void setHeight(int height) {
            this.height = height;
            this.width = height;   // Forces width = height
        }
    }
    // Fixed version - separate classes implementing a common interface (recommended)
    interface Shape {
        int area();
    }
    static class RectangleFixed implements Shape {
        private int width;
        private int height;

        public RectangleFixed(int width, int height) {
            this.width = width;
            this.height = height;
        }
        public void setWidth(int width)   { this.width = width; }
        public void setHeight(int height) { this.height = height; }

        @Override
        public int area() {
            return width * height;
        }
    }
    static class SquareFixed implements Shape {
        private int side;

        public SquareFixed(int side) {
            this.side = side;
        }
        public void setSide(int side) {
            this.side = side;
        }
        @Override
        public int area() {
            return side * side;
        }
    }
    // One-liner usage example showing the violation vs fixed behavior
    public static void main(String[] args) {
        // Violating version - unexpected result when treating Square as Rectangle
        Rectangle r = new Square();
        r.setWidth(5); r.setHeight(10);                // Area should be 50, but becomes 100!
        // Fixed version - safe and predictable
        Shape rect = new RectangleFixed(5, 10);        // Area = 50
        Shape sq   = new SquareFixed(5);               // Area = 25
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first part shows the classic LSP violation where Square extends Rectangle and overrides setters, breaking substitutability because a Square used as a Rectangle no longer behaves as expected (area becomes incorrect).&lt;br&gt;
The fixed version removes inheritance between Rectangle and Square, instead having both implement a common Shape interface, ensuring any Shape can be substituted safely.&lt;/p&gt;
&lt;h3&gt;
  
  
  Interface Segregation Principle (ISP)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Clients should not be forced to depend on methods they do not use.&lt;/strong&gt;&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%2Fk82apuu37duui3xuxmm9.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%2Fk82apuu37duui3xuxmm9.png" alt="Interface Segregation Principle" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package SOLID;

/**
 * Clients should not be forced to depend on methods they do not use. Interfaces should be specific to the client's needs.
 * */
public class InterfaceSegregation {
    //Example violating ISP
    interface Worker {
        void work();
        void eat();
    }
    class Robot implements Worker {
        @Override
        public void work() {
            //Code for the robot to work
        }
        @Override
        public void eat() {
            // Robots don't eat, an unnecessary method for them
        }
    }
    // Refactored into segregated interfaces
    interface Workable {
        void work();
    }
    interface Feedable {
        void eat();
    }
    class RobotRefactored implements Workable {
        @Override
        public void work() {
            //Code for the robot to work
        }
    }
}

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

&lt;/div&gt;



&lt;p&gt;In the bad Example, Robot is polluted with an irrelevant eat() method just because it implements a fat Worker interface.&lt;br&gt;
By splitting the interface into smaller, purpose-specific ones (Workable and Feedable), we eliminate unnecessary dependencies and make the design cleaner and more maintainable.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dependency Inversion Principle (DIP)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Depend on abstractions, not on concrete implementations.&lt;/strong&gt;&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%2Fdto4wg1zgkenjhycq1q4.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%2Fdto4wg1zgkenjhycq1q4.png" alt="Dependency Inversion Principle" width="800" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package SOLID;
/**
 * High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details. Details should depend on abstractions.
 * **/
public class DependencyInversion {
    //Example violating DIP
    class EmailService {
        public void sendEmail(String message, String recipient) {
            //Code to send email
        }
    }
    class UserManager {
        private final EmailService emailService;

        public UserManager() {
            this.emailService = new EmailService();
        }
        public void sendWelcomeEmail(String user) {
            emailService.sendEmail("Welcome!", user);
        }
    }
    // Refactored with abstraction
    interface MessageService {
        void sendMessage(String message, String recipient);

        void sendEmail(String s, String user);
    }
    class EmailServiceRefactored implements MessageService {
        @Override
        public void sendMessage(String message, String recipient) {
            //Code to send email
        }
        @Override
        public void sendEmail(String s, String user) {
        }
    }
    class UserManagerRefactored {
        private MessageService messageService;

        public void UserManager(MessageService messageService) {
            this.messageService = messageService;
        }
        UserManagerRefactored(MessageService messageService) {
            this.messageService = messageService;
        }
        public void sendWelcomeMessage(String user) {
            messageService.sendMessage("Welcome!", user);
        }
    }

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

&lt;/div&gt;



&lt;p&gt;In the bad Example, UserManager is tightly coupled to EmailService — making it hard to change or test.&lt;br&gt;
In the refactored version, we invert the dependency; both high-level (UserManager) and low-level (EmailService, SmsService, etc.) depend on the MessageService abstraction, achieving loose coupling and flexibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to tie SOLID into &lt;em&gt;"system design."&lt;/em&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Scaling teams: SOLID supports modular ownership, where different teams can evolve different modules with fewer cross‑impacts.
​&lt;/li&gt;
&lt;li&gt;Evolving requirements: OCP and DIP support changing external systems or adding new features with localized changes.
​ &lt;/li&gt;
&lt;li&gt;Reliability and testing: Smaller, single‑responsibility classes are easier to test and mock, which helps build confidence when changing complex systems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;In brief: Why follow SOLID? &lt;br&gt;
&lt;em&gt;"It makes code easier to maintain, test, and extend as requirements change."&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;All images generated using nano banana.&lt;/em&gt;​&lt;/p&gt;

</description>
      <category>programming</category>
      <category>java</category>
      <category>design</category>
      <category>solidprinciples</category>
    </item>
    <item>
      <title>Polyglot Microservices Communication in Kubernetes with DNS, CoreDNS, and Istio (Java &amp; Python)</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Mon, 05 Jan 2026 05:33:49 +0000</pubDate>
      <link>https://dev.to/gokul_gk/polyglot-microservices-communication-in-kubernetes-with-dns-coredns-and-istio-java-python-4gb9</link>
      <guid>https://dev.to/gokul_gk/polyglot-microservices-communication-in-kubernetes-with-dns-coredns-and-istio-java-python-4gb9</guid>
      <description>&lt;h2&gt;
  
  
  Exploring service registry, service discovery, and service mesh in Kubernetes.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/gokul_gk/lets-talk-about-service-discovery-service-registry-and-service-mesh-1ebi"&gt;Here we have already discussed service discovery, registry, and service mesh.&lt;/a&gt;&lt;br&gt;
We will discuss&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How does Kubernetes implement service registry and discovery natively?&lt;/li&gt;
&lt;li&gt;What does a service mesh add on top of Kubernetes networking?&lt;/li&gt;
&lt;li&gt;How to test cross-service communication (Java ↔ Python) on Minikube?
### Codespace
We can utilize Codespace for installation and application development.
&lt;a href="https://docs.github.com/en/codespaces/quickstart" rel="noopener noreferrer"&gt;Codespaces Documentation&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can get the complete application code &lt;a href="https://github.com/GKcodebase/MiniKube/tree/main" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why "polyglot" microservices are complex?
&lt;/h3&gt;

&lt;p&gt;Polyglot microservices enable teams to use different programming languages and tech stacks for each service, allowing for the "best tool for the job." This introduces significant challenges in distributed systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each language has its own libraries for HTTP communication, configuration management, retries, circuit breakers, and resilience patterns&lt;/li&gt;
&lt;li&gt;Development setups (e.g., localhost) differ significantly from clustered production environments, making testing, debugging, and configuration (such as service URLs or credentials) error-prone and inconsistent.&lt;/li&gt;
&lt;li&gt;Inter-service calls over networks can fail due to latency, timeouts, or partitions, requiring robust handling (e.g., fallbacks, timeouts) that must be re-implemented per language/stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Kubernetes provides native mechanisms for service discovery and networking, eliminating the need for external tools in many cases&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  MiniKube
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Farm64%2Fstable%2Fbinary+download" rel="noopener noreferrer"&gt;MiniKube Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Minikube is a local Kubernetes cluster designed to make it easy to learn and develop with Kubernetes. &lt;br&gt;
&lt;em&gt;Note: Local clusters enable developers to experience real Kubernetes networking (DNS, services) without relying on cloud infrastructure.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When developing locally with Minikube, you typically build Docker images on your host machine and then deploy pods that reference those images.&lt;br&gt;
Minikube runs its own Docker engine inside the Minikube VM (or container, depending on the driver). This is often referred to as &lt;strong&gt;"Docker-in-Docker"&lt;/strong&gt; in this context—though technically it's Docker running inside the Minikube environment, separate from your host Docker daemon.&lt;/p&gt;
&lt;h4&gt;
  
  
  Minikube Installation
&lt;/h4&gt;

&lt;p&gt;Run below commands for installation and verfification&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
sudo install minikube-linux-amd64 /usr/local/bin/minikube
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Start and verify Minikube
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Start Minikube server
minikube start --driver=docker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#Verify installation
kubectl get nodes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Applications
&lt;/h2&gt;

&lt;p&gt;I have already built the Java and Spring Boot applications, as well as the Kubernetes configuration file.&lt;br&gt;
The project structure looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GitHub Codespace
 └── Minikube (Docker driver)
     ├── Kubernetes Services (DNS-based discovery)
     ├── FastAPI App (Python)
     ├── Spring Boot App (Java)
     ├── Istio (Service Mesh)
     │    ├── Envoy sidecars
     │    ├── mTLS
     │    └── Observability

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

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Check the application exposed API's readme file, if you want to change/scale anything.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GKcodebase/MiniKube/tree/main/SpringBootService" rel="noopener noreferrer"&gt;Java - Spring Boot application&lt;/a&gt;&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%2Ftkyc2saasbclahjhj4r9.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%2Ftkyc2saasbclahjhj4r9.png" alt="Java - Spring Boot application Api's" width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/GKcodebase/MiniKube/tree/main/FastApiService" rel="noopener noreferrer"&gt;Python - FastApi application&lt;/a&gt;&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%2Fos2u7us6rvocgc28vvi5.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%2Fos2u7us6rvocgc28vvi5.png" alt="Python - FastApi application Api's" width="800" height="204"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Build Docker Image of applications
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/get-started/" rel="noopener noreferrer"&gt;Docker Documentation&lt;/a&gt;.&lt;br&gt;
We will generate a Docker image from our Java and Python applications to run inside Minikube.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;eval $(minikube docker-env)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;If you skip &lt;code&gt;eval $(minikube docker-env)&lt;/code&gt;, your locally built images won't be visible to the cluster&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker build -t fastapi-app:1.0 ./fastapi-app&lt;br&gt;
docker build -t spring-app:1.0 ./spring-boot-app&lt;br&gt;
&lt;/code&gt;&lt;br&gt;
&lt;em&gt;This pulls in Minikube's Docker daemon, so images built inside Minikube don't need to be pushed to a registry&lt;/em&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%2Ft5kbfxhbrlo0d63apmsq.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%2Ft5kbfxhbrlo0d63apmsq.png" alt="The whole project" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Kubernetes Deployment, Service Discovery, and Service Registry
&lt;/h2&gt;

&lt;p&gt;In Kubernetes, service objects and CoreDNS replace traditional service registries, such as Eureka/Consul. &lt;strong&gt;You don't register services manually&lt;/strong&gt; — Kubernetes does it automatically via labels/selectors.&lt;/p&gt;

&lt;p&gt;In Kubernetes, &lt;strong&gt;Service objects act as the service registry&lt;/strong&gt;.&lt;br&gt;
When a Service is created, it becomes a stable, discoverable entry that represents one or more running Pods. Pods that match a Service's selector are automatically registered as endpoints for the service.&lt;/p&gt;

&lt;p&gt;Kubernetes provides &lt;strong&gt;built-in service discovery using DNS via CoreDNS&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every service is automatically assigned a DNS name following this format:&lt;br&gt;
&lt;code&gt;&amp;lt;service-name&amp;gt;.&amp;lt;namespace&amp;gt;.svc.cluster.local&lt;/code&gt;&lt;br&gt;
Applications can communicate using &lt;strong&gt;service names instead of IP addresses&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://github.com/GKcodebase/MiniKube/tree/main/KubernetesService" rel="noopener noreferrer"&gt;here&lt;/a&gt; for Kubernetes configs and needed commands.&lt;/p&gt;

&lt;p&gt;Once you check out the config, apply the manifest files.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f KubernetesService/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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%2F0abs7mophd284r6wqs4n.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%2F0abs7mophd284r6wqs4n.png" alt="Service Registry and Service Discovery in Kubernetes" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Verify the Inbuilt service registry
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;kubectl get svc&lt;/code&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inspect label and selectors
&lt;/h4&gt;

&lt;p&gt;Labels are key-value metadata attached to Kubernetes objects, while selectors define which labels a Service should match.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl describe svc spring-service&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl label pod &amp;lt;spring-pod&amp;gt; app=wrong --overwrite
kubectl describe svc spring-service

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

&lt;/div&gt;



&lt;h4&gt;
  
  
  Service Discovery (DNS, No Hardcoded IPs)
&lt;/h4&gt;

&lt;p&gt;Let's navigate to the shell of the FastAPI service, retrieve the service name of the Spring Boot service, and verify the cross-service call.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#get the list of all pods running
kubectl get pods

#Go to the FastAPI service shell
kubectl exec -it &amp;lt;fastapi-pod&amp;gt; -- sh

#Get the IP address/service name of the spring service
getent hosts spring-service

#call the Spring service api from the FastAPI service shell.
curl http://spring-service:8080/hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;_Use the command below if curl is having issues.&lt;br&gt;
_&lt;code&gt;kubectl exec -it &amp;lt;fastapi-pod&amp;gt; -- sh -c "apt-get update &amp;amp;&amp;amp; apt-get install -y curl &amp;amp;&amp;amp; curl http://spring-service:8080/hello"&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why DNS-Only Is Not Enough?
&lt;/h3&gt;

&lt;p&gt;Kubernetes's built-in DNS-based service discovery and load balancing are powerful—they give you reliable reachability: services can find each other via stable DNS names, and traffic is automatically distributed across healthy pods.&lt;/p&gt;

&lt;p&gt;But it lacks&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mLTS&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;li&gt;Retires&lt;/li&gt;
&lt;li&gt;Traffic Management etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is precisely where a service mesh steps in—adding a dedicated infrastructure layer that provides retries, traffic shaping, mTLS, and rich observability uniformly across all services, without requiring changes to the application code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Istio / Service Mesh
&lt;/h2&gt;

&lt;p&gt;Istio is an open-source service mesh that integrates seamlessly with existing distributed applications. Its powerful features provide a consistent and efficient way to secure, connect, and monitor services.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://istio.io/latest/docs/setup/platform-setup/minikube/" rel="noopener noreferrer"&gt;Istio Documentation&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;curl -L https://istio.io/downloadIstio | sh -
cd istio-*
sudo install bin/istioctl /usr/local/bin/istioctl

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;istioctl install --set profile=demo -y&lt;/code&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%2F4jkkgp33355i74t8q1ro.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%2F4jkkgp33355i74t8q1ro.png" alt="Istio sidecar,mTLS and Kiali Observability" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Enable sidecar
&lt;/h3&gt;

&lt;p&gt;A service mesh introduces a sidecar proxy alongside each application container.&lt;/p&gt;

&lt;p&gt;With Istio, an Envoy proxy is automatically injected into every Pod.&lt;br&gt;
All inbound and outbound traffic flows through this proxy, rather than directly between services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl label namespace default istio-injection=enabled&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;restaServiceice&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;kubectl rollout restart deployment fastapi spring&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;visualize sidecar&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;kubectl get pod &amp;lt;fastapi-pod&amp;gt; -o jsonpath='{.spec.containers[*].name}'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sidecar enables advanced features such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Traffic control&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Observability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Most importantly, these features are added without modifying the application code, allowing teams to focus solely on business logic&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  mTLS
&lt;/h3&gt;

&lt;p&gt;Istio enables mutual TLS (mTLS) by default between services.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;istioctl authn tls-check spring-service.default.svc.cluster.local&lt;/code&gt;&lt;br&gt;
Service Mesh mTLS provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Encryption in transit&lt;/li&gt;
&lt;li&gt;Service identity verification&lt;/li&gt;
&lt;li&gt;Zero-trust networking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this happens transparently; applications are completely unaware that encryption is being handled in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Observability
&lt;/h3&gt;

&lt;p&gt;A service mesh provides &lt;strong&gt;deep observability out of the box&lt;/strong&gt;.&lt;br&gt;
Because all traffic flows through Envoy proxies, Istio can automatically collect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request rates&lt;/li&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Error percentages&lt;/li&gt;
&lt;li&gt;Service dependencies
Tools like Kiali visualize this data as a live service graph, making it easy to understand how services interact and where problems occur.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Achieving this level of insight is extremely challenging at the application level alone.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://kiali.io/docs/installation/quick-start/" rel="noopener noreferrer"&gt;kiali Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;install kiali&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.28/samples/addons/kiali.yaml&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Sample Dashboard&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%2Fzc3j0qu2bavo7et1tevw.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%2Fzc3j0qu2bavo7et1tevw.png" alt="Kiali - Mesh" width="800" height="421"&gt;&lt;/a&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%2Fmzuf1tkfryy93vp8k94h.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%2Fmzuf1tkfryy93vp8k94h.png" alt="Kiali - workloads" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All images generated using nano banana.&lt;/li&gt;
&lt;li&gt;Reference added section-wise.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This is a very brief demonstration of how service discovery, service registry, and service mesh work. I will be creating a detailed version focusing on Service Mesh (Istio) and Observability tool (Kiali)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>kubernetes</category>
      <category>java</category>
      <category>python</category>
    </item>
    <item>
      <title>Let's talk about service discovery, service registry, and service mesh.</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Sun, 28 Dec 2025 13:11:03 +0000</pubDate>
      <link>https://dev.to/gokul_gk/lets-talk-about-service-discovery-service-registry-and-service-mesh-1ebi</link>
      <guid>https://dev.to/gokul_gk/lets-talk-about-service-discovery-service-registry-and-service-mesh-1ebi</guid>
      <description>&lt;h2&gt;
  
  
  How Do Our Microservices Find Each Other and Communicate With Each Other?
&lt;/h2&gt;

&lt;p&gt;Imagine a system with over 50 microservices, each running on a different machine.&lt;br&gt;
Instances scale up and down, IPs change, services crash and restart.&lt;/p&gt;

&lt;p&gt;Yet somehow, everything still works.&lt;br&gt;
So the natural questions arise:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do microservices find each other?&lt;br&gt;
How do they know where an upstream service is running?&lt;br&gt;
How do they communicate securely and reliably at scale?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To answer these questions, we need to understand three key concepts:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Service Registry&lt;br&gt;
Service Discovery&lt;br&gt;
Service Mesh&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Core Problem
&lt;/h2&gt;

&lt;p&gt;In a distributed microservices system:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Services don’t have fixed IP addresses&lt;/li&gt;
&lt;li&gt;Instances are created and destroyed dynamically&lt;/li&gt;
&lt;li&gt;Hardcoding endpoints is impossible&lt;/li&gt;
&lt;li&gt;Manual configuration does not scale&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So we need a dynamic, automated way for services to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Know &lt;strong&gt;what services exist&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Find &lt;strong&gt;where they are currently running&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Communicate &lt;strong&gt;securely and reliably&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Service registry
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;It's a database&lt;/strong&gt; that will store network information for all registered instances. It's a key part of service discovery; the registry must be up-to-date and highly available.&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%2Fwaeq8rx9d0qo3eqd8f3r.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%2Fwaeq8rx9d0qo3eqd8f3r.png" alt="Service Registry" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Typical service registries (pre-Kubernetes):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Eureka&lt;/li&gt;
&lt;li&gt;Consul&lt;/li&gt;
&lt;li&gt;Zookeeper&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Service Registration
&lt;/h3&gt;

&lt;p&gt;Service instances need to be registered and deregistered with the service registry in all types of service discovery.&lt;/p&gt;

&lt;h4&gt;
  
  
  Self Registration
&lt;/h4&gt;

&lt;p&gt;The &lt;strong&gt;service instance itself&lt;/strong&gt; handles registration and deregistration with the service registry. It registers its address with the registry and immediately deregisters itself when the instance terminates.&lt;/p&gt;

&lt;h4&gt;
  
  
  Third-party Registration
&lt;/h4&gt;

&lt;p&gt;The third-party registration pattern prevents service instances from self-registering. Instead, the registration and deregistration processes are &lt;strong&gt;managed by the service registrar&lt;/strong&gt;, a component that monitors changes in the set of running instances.&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%2Ffliud6khjomu3qtyjxm3.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%2Ffliud6khjomu3qtyjxm3.png" alt="Service Registration" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Discovery
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Service discovery is the mechanism by which a service finds the network location of another service at runtime.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The primary goal of service discovery is to simplify communication between microservices, enabling automatic connection through a dedicated system. &lt;em&gt;Instead of hardcoding the network address, we tend to ask where the service is.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How does it work?
&lt;/h3&gt;

&lt;p&gt;Service discovery involves three key functions: it allows an instance to register and announce, "I’m here!" It also provides a method to locate the service after registration. Finally, it updates any changes in the service's location.&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%2Ffws28lurd90sznn87qat.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%2Ffws28lurd90sznn87qat.jpg" alt="Service Discovery" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In more detailed steps (a generalized version)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Service Instance Starts&lt;/strong&gt; - A microservice instance starts on a VM. It gets an IP address dynamically (payment service)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Registers Itself&lt;/strong&gt; - The service registers with a service registry. It sends: Service name, IP address, Port, Health info
payment-service → 10.0.1.12:8080 &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Registry Stores Metadata&lt;/strong&gt; - The registry maintains a list of healthy service instancesPeriodic heartbeats update health(orange box)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Client Requests a Service&lt;/strong&gt;- A client service (order service) requests a call to the payment service. It queries the registry&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Service Discovery Happens&lt;/strong&gt; - Registry responds with:[10.0.1.12, 10.0.1.15, 10.0.1.18]&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load Balancing&lt;/strong&gt; -  Client picks one instance, makes the network call. This is client-side discovery &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Updates&lt;/strong&gt; -  Failed instances are removed, Registry stays up-to-date&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;There are two main service discovery patterns: client-side discovery and server-side discovery.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-Side Discovery Pattern
&lt;/h3&gt;

&lt;p&gt;In the client-side discovery pattern, the client/consumer service (in this case, the order service) is responsible for determining the network location and load-balancing the request between them.&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%2Fk8tyyas5erjaf2e9kdvq.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%2Fk8tyyas5erjaf2e9kdvq.png" alt="Client Side Discovery" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It has an advantage because it saves an additional step that would have been needed with a dedicated load balancer. However, it also has a disadvantage as the Service Consumer must implement the load-balancing logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-side Discovery Pattern
&lt;/h3&gt;

&lt;p&gt;In the server-side discovery pattern, there is an intermediary layer of router/load balancer. The client makes a discovery and communicates through this load balancer, which acts as an orchestrator.&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%2Fululqf55v6iiema5ro6u.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%2Fululqf55v6iiema5ro6u.png" alt="Server Side Discovery" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this approach, a dedicated component called the Load Balancer handles the task of load balancing. This is a major advantage, as it simplifies the responsibilities of the Service Consumer, which no longer has to manage the lookup process. Consequently, there's no need to implement discovery logic separately for each programming language or framework used by the Service Consumer.&lt;br&gt;
It is essential to note that we must either set up and manage the Load Balancer ourselves or ensure it is already available in the deployment environment.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;In Kubernetes-based systems, you usually do not need a separate service registry or discovery tool.&lt;/em&gt;&lt;br&gt;
But Discovery Alone Is Not Enough&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Even with discovery solved, new challenges appear:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How do services communicate securely?&lt;br&gt;
How do we handle retries and failures?&lt;br&gt;
How do we prevent cascading outages?&lt;br&gt;
How do we apply consistent policies across services written in different languages?&lt;br&gt;
This is where service mesh comes in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Service mesh
&lt;/h2&gt;

&lt;p&gt;A Service Mesh is a method for &lt;strong&gt;managing communication between individual services&lt;/strong&gt; that comprise modern applications in a microservice-based architecture. It helps to add security, reliability, and observability.&lt;br&gt;
Service Mesh enables security, observability, traffic management, and reliability.&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%2Fdd58zlac3mq5vhr4hxlq.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%2Fdd58zlac3mq5vhr4hxlq.png" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The dedicated infrastructure layer of a service mesh complements an API gateway, serving a distinct purpose. &lt;strong&gt;While a service mesh manages communication between the various services within a system, an API gateway separates the internal workings of that system from the API that is presented to clients&lt;/strong&gt;, which can include other systems within the organization or external clients.&lt;/p&gt;

&lt;p&gt;The distinction between an API gateway and a service mesh is often described in terms of north-south (for the API gateway) versus east-west (for the service mesh) communication. However, this characterization may not fully capture the nuances of their respective functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  How does a service mesh work?
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Architecture: Data Plane vs. Control Plane&lt;/em&gt;&lt;br&gt;
A service mesh is split into two distinct parts:&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%2Fzky9ib95f4ha84b5lhtg.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%2Fzky9ib95f4ha84b5lhtg.png" alt="Service Mesh" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The Data Plane (The Muscle)&lt;/strong&gt;&lt;br&gt;
This consists of the &lt;strong&gt;thousands of intelligent sidecar proxies&lt;/strong&gt; deployed throughout your cluster.&lt;/p&gt;

&lt;p&gt;The Data Plane handles the actual data packets, performs load balancing, terminates TLS (encryption), enforces rate limits, and collects metrics (including latency and error rates). These proxies are highly optimized to add minimal latency (milliseconds).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. The Control Plane (The Brain)&lt;/strong&gt;&lt;br&gt;
This is a &lt;strong&gt;centralized management server&lt;/strong&gt;. The proxies are stateless; they require instructions on what to do.&lt;/p&gt;

&lt;p&gt;The control plane manages and configures the proxies. The Control Plane then pushes this configuration to all the Data Plane proxies in real-time. It often acts as a Certificate Authority (CA), rotating security certificates for the proxies to use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step: How a Request Works
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;Imagine Service A (Frontend) wants to call Service B (Inventory).&lt;/em&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%2Fz8x3qjfbl821l45j5gn8.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%2Fz8x3qjfbl821l45j5gn8.png" alt="Service Mesh Architecture" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Outbound Intercept&lt;/strong&gt;: Service A sends a request to Service B. The network rules trap this packet and redirect it to Service A's local sidecar proxy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discovery &amp;amp; Load Balancing&lt;/strong&gt;: The sidecar asks, "Where is Service B?" It examines its configuration (from the Control Plane) and selects the best instance of Service B (e.g., the one with the lowest latency).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Encryption (mTLS)&lt;/strong&gt;: The sidecar encrypts the request using a mutual TLS certificate to ensure no one else can read it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transmission&lt;/strong&gt;: The encrypted request travels over the network to the machine where Service B is running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inbound Intercept&lt;/strong&gt;: The request is caught by Service B's sidecar proxy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decryption &amp;amp; Check&lt;/strong&gt;: Service B's sidecar decrypts the packet and verifies that Service A is authorized to communicate with Service B (Access Control).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Delivery&lt;/strong&gt;: If allowed, the sidecar forwards the clean request to the actual Service B application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference
&lt;/h2&gt;

&lt;p&gt;1.&lt;a href="https://www.baeldung.com/cs/service-discovery-microservices" rel="noopener noreferrer"&gt;https://www.baeldung.com/cs/service-discovery-microservices&lt;/a&gt;&lt;br&gt;
2.&lt;a href="https://www.f5.com/company/blog/nginx/service-discovery-in-a-microservices-architecture" rel="noopener noreferrer"&gt;https://www.f5.com/company/blog/nginx/service-discovery-in-a-microservices-architecture&lt;/a&gt;&lt;br&gt;
3.&lt;a href="https://middleware.io/blog/service-discovery/" rel="noopener noreferrer"&gt;https://middleware.io/blog/service-discovery/&lt;/a&gt;&lt;br&gt;
4.&lt;a href="https://api7.ai/blog/service-discovery" rel="noopener noreferrer"&gt;https://api7.ai/blog/service-discovery&lt;/a&gt;&lt;br&gt;
5.&lt;a href="https://microservices.io/tags/service%20discovery" rel="noopener noreferrer"&gt;https://microservices.io/tags/service%20discovery&lt;/a&gt;&lt;br&gt;
7.&lt;a href="https://konghq.com/blog/learning-center/what-is-a-service-mesh" rel="noopener noreferrer"&gt;https://konghq.com/blog/learning-center/what-is-a-service-mesh&lt;/a&gt;&lt;br&gt;
*Images generated using nano banana&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I wrote these blogs based on my understanding and research. Please comment if you find any errors or suggest improvements.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>serviceregistry</category>
      <category>servicemesh</category>
      <category>servicediscovery</category>
    </item>
    <item>
      <title>Getting Started with Prometheus and Grafana in Java</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Thu, 14 Nov 2024 00:02:29 +0000</pubDate>
      <link>https://dev.to/gokul_gk/getting-started-with-prometheus-and-grafana-in-java-19ia</link>
      <guid>https://dev.to/gokul_gk/getting-started-with-prometheus-and-grafana-in-java-19ia</guid>
      <description>&lt;p&gt;Monitoring is a crucial aspect of application performance management. As applications scale, ensuring that they run smoothly and that system health is continually tracked becomes imperative. In microservices, distributed systems, and cloud-native applications, monitoring tools are not just an add-on but a critical part of your infrastructure.&lt;/p&gt;

&lt;p&gt;Two of the most popular tools for monitoring modern systems are Prometheus and Grafana. These tools are often used to collect, store, and visualize metrics, helping developers and operations teams detect issues, analyze performance, and keep systems running efficiently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Do We Need Monitoring?
&lt;/h2&gt;

&lt;p&gt;Monitoring is essential for identifying problems before they affect users. Whether you're working with a Java-based backend, a complex microservices environment, or any other system, continuous monitoring provides insights into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Application performance:&lt;br&gt;
Track key performance metrics such as response times, requests, and error rates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;System health:&lt;br&gt;
Monitor server health, CPU usage, memory usage, and disk space to ensure the infrastructure operates optimally.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Alerting:&lt;br&gt;
Set up thresholds and alerts for critical metrics that notify you when something goes wrong.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Capacity planning:&lt;br&gt;
Collecting and analyzing historical data can help you plan for scaling your application.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prometheus and Grafana offer robust solutions to monitor, visualize, and analyze data from your systems and applications.&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%2Fog9odl2unc9lqzb8tmme.jpeg" 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%2Fog9odl2unc9lqzb8tmme.jpeg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Grafana and Prometheus
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prometheus&lt;/strong&gt;&lt;br&gt;
Prometheus is an open-source monitoring and alerting toolkit designed for reliability and scalability. It focuses on gathering time-series data and supports multidimensional data collection, allowing for powerful queries and analysis. Prometheus collects metrics from targets via HTTP endpoints and stores them in a time-series database. These metrics can then be queried using Prometheus's query language, PromQL.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Grafana&lt;/strong&gt;&lt;br&gt;
Grafana is an open-source platform for monitoring and observability. It allows users to visualize time-series data from multiple sources, including Prometheus. Grafana's ability to create dashboards, set up alerts, and integrate with a wide range of data sources makes it one of the most popular tools for visualizing metrics.&lt;/p&gt;

&lt;p&gt;Together, Prometheus collects the metrics, while Grafana displays them in an interactive and visually appealing way.&lt;/p&gt;
&lt;h2&gt;
  
  
  Running Prometheus in Docker
&lt;/h2&gt;

&lt;p&gt;Running Prometheus and Grafana in Docker is a simple and effective way to set up a monitoring environment quickly. Let's start with running Prometheus in Docker.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Running Prometheus in Docker&lt;/strong&gt;&lt;br&gt;
You can run Prometheus as a container using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --name prometheus -d -p 127.0.0.1:9090:9090 prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start a &lt;em&gt;Prometheus&lt;/em&gt; container.&lt;/li&gt;
&lt;li&gt;Map the local port &lt;em&gt;9090&lt;/em&gt; to the container’s port &lt;em&gt;9090&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Use the official Prometheus Docker image from Docker Hub.
You can verify that Prometheus is running by opening your browser and navigating to &lt;a href="http://localhost:9090/" rel="noopener noreferrer"&gt;http://localhost:9090/&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Configuring Prometheus&lt;/strong&gt;&lt;br&gt;
You must adjust the Prometheus configuration file if you need to configure Prometheus to scrape metrics from specific endpoints (e.g., a Java application). By mounting it into the container, you can run Prometheus with a custom prometheus.yml file. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run \
    -p 9090:9090 \
    -v /prometheus.yml:/etc/prometheus/prometheus.yml \
    prom/prometheus
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This mounts your local prometheus.yml file into the container. After starting Prometheus, you can go to &lt;a href="http://localhost:9090/" rel="noopener noreferrer"&gt;http://localhost:9090/&lt;/a&gt; to access the Prometheus dashboard.&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%2Fnl9mj3sqfgc01yn5q3y6.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%2Fnl9mj3sqfgc01yn5q3y6.png" alt=" " width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Grafana in Docker
&lt;/h2&gt;

&lt;p&gt;Now that Prometheus is running adding Grafana to visualize the data is time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Running Grafana in Docker&lt;/strong&gt;&lt;br&gt;
Grafana is simple to deploy via Docker. Run the following command to start the Grafana container:&lt;/p&gt;

&lt;p&gt;Running Grafana in docker&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -p 3000:3000 grafana/grafana-enterprise

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

&lt;/div&gt;



&lt;p&gt;Once Grafana is running, you can access the web UI at &lt;a href="http://localhost:3000/login" rel="noopener noreferrer"&gt;http://localhost:3000/login&lt;/a&gt;. The default login credentials are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Username: admin&lt;/li&gt;
&lt;li&gt;Password: admin&lt;/li&gt;
&lt;/ul&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%2Ffqmkf0kmu10gmec0cuth.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%2Ffqmkf0kmu10gmec0cuth.png" alt=" " width="581" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Connecting Prometheus and Grafana&lt;/strong&gt;&lt;br&gt;
Now that both Prometheus and Grafana are running, the next step is to connect them. Grafana needs to know where to get the metrics from. Here's how you can add Prometheus as a data source in Grafana:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to &lt;em&gt;Grafana&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;click the &lt;em&gt;gear&lt;/em&gt; icon on the left sidebar to open the &lt;em&gt;Configuration&lt;/em&gt; menu.&lt;/li&gt;
&lt;li&gt;Select &lt;em&gt;Data Sources&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;Add data source&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Choose &lt;em&gt;Prometheus&lt;/em&gt; as the data source type.&lt;/li&gt;
&lt;li&gt;In the &lt;em&gt;HTTP&lt;/em&gt; section, set the URL to your Prometheus instance (e.g., &lt;a href="http://172.0.0.1:9090" rel="noopener noreferrer"&gt;http://172.0.0.1:9090&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;Click &lt;em&gt;Save &amp;amp; Test&lt;/em&gt; to ensure Grafana can successfully connect to Prometheus.&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Creating a Sample Java Project
&lt;/h2&gt;

&lt;p&gt;Let's create a simple Java-based project that exposes metrics to Prometheus. We will use Micrometer, a metrics collection facade for JVM-based applications, which integrates easily with Prometheus.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Create a Java Application&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Add the necessary dependencies to your pom.xml file:&lt;br&gt;
Connecting everything.&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;dependency&amp;gt;
    &amp;lt;groupId&amp;gt;io.micrometer&amp;lt;/groupId&amp;gt;
    &amp;lt;artifactId&amp;gt;micrometer-registry-prometheus&amp;lt;/artifactId&amp;gt;
&amp;lt;/dependency&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, in your Java application, expose an endpoint that Prometheus can scrape. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import io.micrometer.core.instrument.Metrics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import io.micrometer.prometheus.PrometheusMeterRegistry;

@SpringBootApplication
public class MonitoringApp {

    public static void main(String[] args) {
        SpringApplication.run(MonitoringApp.class, args);
    }
}

@RestController
class MetricsController {

    private final PrometheusMeterRegistry registry;

    public MetricsController(PrometheusMeterRegistry registry) {
        this.registry = registry;
    }

    @GetMapping("/metrics")
    public String getMetrics() {
        return registry.scrape();
    }
}

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

&lt;/div&gt;



&lt;p&gt;This setup creates an endpoint /metrics that Prometheus can scrape. It exposes metrics collected by Micrometer and is available in the Prometheus format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 6: Expose Metrics to Prometheus&lt;/strong&gt;&lt;br&gt;
Now that the Java application is collecting metrics, we need to tell Prometheus to scrape the /metrics endpoint from your application. Update your prometheus.yml configuration file to include the target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scrape_configs:
  - job_name: 'java_application'
    static_configs:
      - targets: ['&amp;lt;your-app-ip&amp;gt;:8080']
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace  with the IP address or localhost if running on the same machine. Prometheus will now collect metrics from your Java 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%2Fjgfev378uu65aojs91kw.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%2Fjgfev378uu65aojs91kw.png" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Connecting Everything
&lt;/h2&gt;

&lt;p&gt;At this point, you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus scraping metrics from your Java application.&lt;/li&gt;
&lt;li&gt;Grafana is set up as the visualization tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 7: Creating Dashboards in Grafana&lt;/strong&gt;&lt;br&gt;
To visualize the data in Grafana:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;em&gt;Dashboard&lt;/em&gt; tab in Grafana.&lt;/li&gt;
&lt;li&gt;Click + &lt;em&gt;New Dashboard&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;Add a &lt;em&gt;Panel&lt;/em&gt; and select &lt;em&gt;Prometheus&lt;/em&gt; as the data source.&lt;/li&gt;
&lt;li&gt;Write a &lt;em&gt;PromQL&lt;/em&gt; query to retrieve the metrics, for example, &lt;em&gt;http_requests_total&lt;/em&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can now build a dashboard with various panels that show metrics like request counts, response times, and error rates.&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%2Fu4ukj0gty6gqmaugorj6.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%2Fu4ukj0gty6gqmaugorj6.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Monitoring is crucial for maintaining high availability and performance. With tools like Prometheus and Grafana, you can easily set up an efficient monitoring solution for your Java applications.&lt;/p&gt;

</description>
      <category>java</category>
      <category>promethus</category>
      <category>grafana</category>
      <category>monitoring</category>
    </item>
    <item>
      <title>Let's create a website with NextJS and deploy it with Vercel.</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Tue, 12 Nov 2024 17:21:04 +0000</pubDate>
      <link>https://dev.to/gokul_gk/create-a-website-with-the-next-js-and-deploy-it-with-vercel-4883</link>
      <guid>https://dev.to/gokul_gk/create-a-website-with-the-next-js-and-deploy-it-with-vercel-4883</guid>
      <description>&lt;p&gt;Building and deploying a website with Next.js is easier than you might think, and the best part? It's platform-agnostic, so the steps remain the same whether using macOS, Windows, or Linux. In this guide, I'll walk you through creating a Next.js app, setting it up locally, and deploying it to Vercel with just a few simple commands.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. &lt;strong&gt;Set Up Your Next.js Project&lt;/strong&gt;
Start by creating a new Next.js app. Open your terminal, and run the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest my-website
-- Click yes for all dependencies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a new Next.js project in a folder called my-website. When prompted, click "Yes" to install all necessary dependencies.&lt;/p&gt;

&lt;p&gt;Next, navigate to your project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; cd my-website
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;2. &lt;strong&gt;Ensure Node is Installed&lt;/strong&gt;
If you encounter any issues while setting up your project, it's likely due to an outdated version of Node.js. To fix this, you can install the latest version of Node:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nvm install node --latest-npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ensure you have the correct Node.js version installed by checking the Next.js installation guide for the latest version requirements.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3. &lt;strong&gt;Open the Project Files&lt;/strong&gt;
Once the project is set up, open your project folder in your preferred code editor. You should see a file structure similar to the one below:&lt;/li&gt;
&lt;/ul&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%2Fl7k3wubjdxpe5dzufh4f.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%2Fl7k3wubjdxpe5dzufh4f.png" alt="File Structure" width="374" height="769"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the app name I've used here is portfolio2.0, but feel free to name your project whatever you like. If you want more details on these files, check out the &lt;a href="https://nextjs.org/docs/getting-started/project-structure" rel="noopener noreferrer"&gt;Next.js Project Structure documentation&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4. &lt;strong&gt;Install Dependencies&lt;/strong&gt;
Next, install the necessary dependencies:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After installation, you can run your app locally to see it in action. Head to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in your browser, and you should see the Next.js default page!&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%2Fxyhrhj2jh0eiz3wisdep.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%2Fxyhrhj2jh0eiz3wisdep.png" alt="Deployed in localhost" width="800" height="475"&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;5.&lt;strong&gt;Push Code to GitHub&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now that your app is set up locally push the code to your GitHub repository. You'll need this to deploy it to Vercel.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;6.&lt;strong&gt;Deploy to Vercel&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Sign up for Vercel:&lt;/em&gt;&lt;br&gt;
If you don't have a Vercel account, sign up at vercel.com. You can use your GitHub account for easy integration.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Connect Vercel to GitHub:&lt;/em&gt;&lt;br&gt;
Once signed in to Vercel, link your GitHub account to your Vercel dashboard.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Import Your GitHub Repository:&lt;/em&gt;&lt;br&gt;
Click "New Project" in your Vercel dashboard.&lt;br&gt;
Select "Import Git Repository" and choose the repository containing your Next.js project.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Configure the Project:&lt;/em&gt;&lt;br&gt;
Vercel will automatically detect that your project is built with Next.js.&lt;br&gt;
Set the build command to the next build.&lt;br&gt;
Set the output directory to .next (this is usually auto-configured).&lt;br&gt;
Add any environment variables you might need (optional).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Deploy Your Project:&lt;/em&gt;&lt;br&gt;
Click "Deploy," and Vercel will start the deployment process.&lt;br&gt;
Vercel will clone your repository, install the dependencies, build your app, and deploy it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Wait for the Deployment to Complete:&lt;/em&gt;&lt;br&gt;
Vercel will provide real-time deployment logs so you can follow along with the process.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Access Your Live Site:&lt;/em&gt;&lt;br&gt;
Once deployment is finished, you'll receive a link to your site, which will look like your-project-name.vercel.app. That's it! Your Next.js app is now live.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F02whzpkm9nvmf0g9eem8.jpeg" 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%2F02whzpkm9nvmf0g9eem8.jpeg" alt=" " width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Recap: Steps for Any Next.js Project
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Prepare Your Next.js Project:&lt;/strong&gt;&lt;br&gt;
Ensure your project is in a GitHub repository with a package.json file containing the necessary scripts (next dev, next build, next start).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sign Up for Vercel:&lt;/strong&gt;&lt;br&gt;
Head to Vercel's website and sign up using your GitHub account.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect Vercel to GitHub:&lt;/strong&gt;&lt;br&gt;
Link your GitHub account in the Vercel dashboard.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Import Your GitHub Repository:&lt;/strong&gt;&lt;br&gt;
In the Vercel dashboard, click "New Project" and choose your GitHub repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Configure Your Project:&lt;/strong&gt;&lt;br&gt;
Vercel automatically detects Next.js projects and configures most settings. You can fine-tune settings if needed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy:&lt;/strong&gt;&lt;br&gt;
Click "Deploy" and let Vercel handle the rest. It will build and deploy your app automatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wait for the Deployment:&lt;/strong&gt;&lt;br&gt;
You can monitor the deployment logs in real-time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Check Your Live Site:&lt;/strong&gt;&lt;br&gt;
Once deployment is complete, Vercel will give you a URL to access your site.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>ui</category>
      <category>javascript</category>
      <category>vercel</category>
    </item>
    <item>
      <title>What would you do if your encrypted credentials and the key got compromised?</title>
      <dc:creator>Gokul G.K.</dc:creator>
      <pubDate>Mon, 11 Jul 2022 16:50:09 +0000</pubDate>
      <link>https://dev.to/gokul_gk/what-would-you-do-if-your-encrypted-credentials-and-the-key-got-compromised-27oh</link>
      <guid>https://dev.to/gokul_gk/what-would-you-do-if-your-encrypted-credentials-and-the-key-got-compromised-27oh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;What will you do if your encrypted credentials and key got compromised?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a rhetorical question.&lt;/p&gt;

&lt;p&gt;Securing API using API keys, tokens or password is common in any application. In the case of basic authentication generally, we try to store the credentials after encrypting them. Here let's see how we can use one-way hash functions like md5 or SHA-256 to achieve basic authentication.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Idea
&lt;/h2&gt;

&lt;p&gt;The idea is to have the credentials converted to hash strings using hash functions for the first time or during sign-up. During login, convert the user entered credentials to hash string and check for equality. Simple as that :D.&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%2F1yn6orinkrjegxj4wj6e.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%2F1yn6orinkrjegxj4wj6e.png" alt=" " width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we aren't storing any encrypted passwords, so even if there is an attack on your application and data is compromised, your credentials are safe.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Implementation
&lt;/h2&gt;

&lt;p&gt;For a complete implementation of the same using java and spring boot (&lt;a href="https://github.com/GKcodebase/Tutorials-blogs-workshop/tree/master/Blogs/Security/BasicAuthentication" rel="noopener noreferrer"&gt;click here&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;let me do a walkthrough :&lt;/p&gt;

&lt;p&gt;so we have a minimal controller interface and implementation&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
public interface LoginApi {

    @GetMapping("/user/login")
    @ResponseBody
    String userLogin();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Component
public class LoginApiImpl implements LoginApi{

    /**
     * User login string.
     *
     * @return the string
     */
    @Override
    public String userLogin() {
        return "Login Successful";
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we have the filter implementation to verify authentication&lt;br&gt;
&lt;a href="https://github.com/GKcodebase/Tutorials-blogs-workshop/blob/master/Blogs/Security/BasicAuthentication/src/main/java/com/basicauth/infrastructure/filter/BasicAuthFilter.java" rel="noopener noreferrer"&gt;Basic Authentication Filter Implementation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The service implementation is where we check the hashed string and given credential, for simplicity let's focus on password.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/**
 * The type Login service.
 */
@Service
public class LoginService {

    /**
     * The constant USER.
     */
    private static final String USER = "ADMIN";

    /**
     * The constant PASSWORD.
     * Actual value is : password
     */
    private static final String PASSWORD = "5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8";

    /**
     * Check authentication boolean.
     *
     * @param user     the user
     * @param password the password
     * @return the boolean
     * @throws NoSuchAlgorithmException the no such algorithm exception
     */
    public boolean checkAuthentication(String user,String password) throws NoSuchAlgorithmException {
        String generatedHash = generateHash(password);
        if(PASSWORD.equals(generatedHash) &amp;amp;&amp;amp; USER.equals(user))
            return true;
        return false;
    }

    /**
     * Generate hash string.
     *
     * @param password the password
     * @return the string
     * @throws NoSuchAlgorithmException the no such algorithm exception
     */
    public  String generateHash(String password) throws NoSuchAlgorithmException {
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hash =  md.digest(password.getBytes(StandardCharsets.UTF_8));
        BigInteger number = new BigInteger(1, hash);
        StringBuilder hexString = new StringBuilder(number.toString(16));
        while (hexString.length() &amp;lt; 64)
        {
            hexString.insert(0, '0');
        }
        return hexString.toString();
    }
}

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

&lt;/div&gt;



&lt;p&gt;finally, let's run the code and hit the API {in this example username is: ADMIN and password is: password}&lt;/p&gt;

&lt;p&gt;Here is the curl for the above API:  curl --location --request GET '&lt;a href="http://localhost:8443/service/api/v1/user/login" rel="noopener noreferrer"&gt;http://localhost:8443/service/api/v1/user/login&lt;/a&gt;' \&lt;br&gt;
--header 'Authorization: Basic QURNSU46cGFzc3dvcmQ='&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%2F0wnmmdm3wyj79k7zdowb.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%2F0wnmmdm3wyj79k7zdowb.png" alt=" " width="800" height="93"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all for now, Hope this is useful.&lt;br&gt;
Share your thoughts in the comment section.&lt;/p&gt;

</description>
      <category>api</category>
      <category>security</category>
      <category>tutorial</category>
      <category>blog</category>
    </item>
  </channel>
</rss>
