<?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: Naman Raj</title>
    <description>The latest articles on DEV Community by Naman Raj (@denyme24).</description>
    <link>https://dev.to/denyme24</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%2F2986332%2Fb5115442-0d3d-45b1-b11b-1b20bb60eec3.jpg</url>
      <title>DEV Community: Naman Raj</title>
      <link>https://dev.to/denyme24</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/denyme24"/>
    <language>en</language>
    <item>
      <title>Learning Istio the Hard Way: A Real Service Mesh Lab with Canary, mTLS, and Tracing.</title>
      <dc:creator>Naman Raj</dc:creator>
      <pubDate>Thu, 04 Dec 2025 22:12:16 +0000</pubDate>
      <link>https://dev.to/denyme24/learning-istio-the-hard-way-a-real-service-mesh-lab-with-canary-mtls-and-tracing-m82</link>
      <guid>https://dev.to/denyme24/learning-istio-the-hard-way-a-real-service-mesh-lab-with-canary-mtls-and-tracing-m82</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Why I Built a Service Mesh Lab Instead of Just Reading Docs
&lt;/li&gt;
&lt;li&gt;
The 3RVision Platform: Real App, Real Traffic
&lt;/li&gt;
&lt;li&gt;
Setting the Stage: Kind + Terraform + Namespaces
&lt;/li&gt;
&lt;li&gt;
How Istio Fits In: Sidecars, Gateways, and the Data Plane
&lt;/li&gt;
&lt;li&gt;
Traffic Management 101: VirtualServices, DestinationRules, and Subsets
&lt;/li&gt;
&lt;li&gt;
Implementing Canary Releases with Headers and Weights
&lt;/li&gt;
&lt;li&gt;
Enforcing Zero-Trust with STRICT mTLS
&lt;/li&gt;
&lt;li&gt;
Load Balancing, Connection Pools, and Circuit Breaking
&lt;/li&gt;
&lt;li&gt;
Observability: Metrics, Dashboards, and Traces
&lt;/li&gt;
&lt;li&gt;
Walking Through a Single Request
&lt;/li&gt;
&lt;li&gt;
Key Takeaways
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why I Built a Service Mesh Lab Instead of Just Reading Docs
&lt;/h2&gt;

&lt;p&gt;This project started as a personal lab to &lt;em&gt;really&lt;/em&gt; understand what a service mesh does beyond the buzzwords. Instead of using sample apps, the goal was to take a real 3-tier app (Next.js frontend, Go backend, Flask ML service) and see how Istio changes the way traffic, security, and observability work in practice.&lt;/p&gt;

&lt;p&gt;The idea was simple: if this setup feels like something that could ship to production one day, then the learning will stick and this repo becomes a living reference for future work.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 3RVision Platform: Real App, Real Traffic.
&lt;/h2&gt;

&lt;p&gt;3RVision is split into three logical services, each running in its own Kubernetes namespace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;frontend&lt;/strong&gt; → Next.js UI
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;backend&lt;/strong&gt; → Go API server
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ml&lt;/strong&gt; → Flask ML inference service
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend talks to the backend, and the backend calls the ML service for model inference, exactly the kind of hop-by-hop traffic that benefits from a service mesh.&lt;/p&gt;

&lt;p&gt;Each service has two deployment variants:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stable&lt;/code&gt; version (production)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;canary&lt;/code&gt; version (testing new features)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where Istio’s traffic management features come into play.&lt;/p&gt;




&lt;h2&gt;
  
  
  Setting the Stage: Kind + Terraform + Namespaces
&lt;/h2&gt;

&lt;p&gt;To avoid dealing with cloud accounts, Terraform provisions a local &lt;strong&gt;Kind cluster&lt;/strong&gt; with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 control plane node
&lt;/li&gt;
&lt;li&gt;2 worker nodes
&lt;/li&gt;
&lt;li&gt;Port mappings for HTTP (80) and HTTPS (443)
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cluster Setup Workflow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Provision the cluster&lt;/span&gt;
terraform init
terraform apply

&lt;span class="c"&gt;# Create namespaces&lt;/span&gt;
kubectl create namespace frontend
kubectl create namespace backend
kubectl create namespace ml

&lt;span class="c"&gt;# Enable Istio sidecar injection&lt;/span&gt;
kubectl label namespace frontend istio-injection&lt;span class="o"&gt;=&lt;/span&gt;enabled
kubectl label namespace backend istio-injection&lt;span class="o"&gt;=&lt;/span&gt;enabled
kubectl label namespace ml istio-injection&lt;span class="o"&gt;=&lt;/span&gt;enabled
&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%2Fbg5zw9i2ncily16hwde3.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%2Fbg5zw9i2ncily16hwde3.jpg" alt="istio_injection" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This gives you a clean separation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terraform&lt;/strong&gt; → cluster lifecycle
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes&lt;/strong&gt; → application resources
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Istio&lt;/strong&gt; → traffic shaping and security
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How Istio Fits In: Sidecars, Gateways, and the Data Plane
&lt;/h2&gt;

&lt;p&gt;Istio works by injecting an &lt;strong&gt;Envoy sidecar proxy&lt;/strong&gt; next to each application container. All inbound and outbound traffic flows through this sidecar, which means you can add routing, retries, mTLS, and telemetry &lt;strong&gt;without changing application code&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%2Fnlsyc7frmd0pli9qh87w.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%2Fnlsyc7frmd0pli9qh87w.jpg" alt="sidecar_container" width="800" height="401"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Architecture Overview
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                            ┌─────────────────────┐
                            │    User/Client      │
                            └──────────┬──────────┘
                                       │
                                       ▼
┌──────────────────────────────────────────────────────────────────────────┐
│                        KIND KUBERNETES CLUSTER                            │
│                        (Terraform Provisioned)                            │
│  ┌────────────────┐  ┌────────────────┐  ┌────────────────┐              │
│  │ Control Plane  │  │   Worker #1    │  │   Worker #2    │              │
│  └────────────────┘  └────────────────┘  └────────────────┘              │
├──────────────────────────────────────────────────────────────────────────┤
│                          ISTIO SERVICE MESH                               │
│                                                                           │
│    Gateway ──────► VirtualService ──────► DestinationRule                │
│   (Ingress)          (Routing)           (mTLS + Load Balancing)         │
├──────────────────────────────────────────────────────────────────────────┤
│                           MICROSERVICES                                   │
│                                                                           │
│   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐               │
│   │   FRONTEND   │    │   BACKEND    │    │   ML MODEL   │               │
│   │   (Next.js)  │───►│     (Go)     │───►│   (Flask)    │               │
│   │  Port: 3000  │    │  Port: 8080  │    │  Port: 5001  │               │
│   │              │    │              │    │              │               │
│   │ stable/canary│    │ stable/canary│    │ stable/canary│               │
│   └──────────────┘    └──────────────┘    └──────────────┘               │
├──────────────────────────────────────────────────────────────────────────┤
│                        OBSERVABILITY STACK                                │
│                                                                           │
│   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐               │
│   │  Prometheus  │    │    Jaeger    │    │   Grafana    │               │
│   │   (Metrics)  │    │  (Tracing)   │    │ (Dashboards) │               │
│   │  Port: 9090  │    │ Port: 16686  │    │  Port: 3000  │               │
│   └──────────────┘    └──────────────┘    └──────────────┘               │
└──────────────────────────────────────────────────────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the edge, an &lt;strong&gt;Istio Ingress Gateway&lt;/strong&gt; receives external requests, applies routing rules defined by VirtualServices, and forwards traffic deeper into the mesh.&lt;/p&gt;




&lt;h2&gt;
  
  
  Traffic Management 101: VirtualServices, DestinationRules, and Subsets
&lt;/h2&gt;

&lt;p&gt;The main Istio building blocks used in this project are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&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;&lt;strong&gt;Gateway&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Exposes services to external traffic on specific ports&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;VirtualService&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines &lt;em&gt;how&lt;/em&gt; requests are routed (by header, weight, path)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DestinationRule&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Defines &lt;em&gt;policies&lt;/em&gt; for traffic (subsets, load balancing, connection pools)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Example: Frontend VirtualService
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;VirtualService&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-vs&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;hosts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;frontend.local"&lt;/span&gt;
  &lt;span class="na"&gt;gateways&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;frontend-gateway&lt;/span&gt;
  &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;match&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;x-canary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;exact&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
      &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-service&lt;/span&gt;
            &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;canary&lt;/span&gt;
          &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;route&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-service&lt;/span&gt;
            &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;
          &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend-service&lt;/span&gt;
            &lt;span class="na"&gt;subset&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;canary&lt;/span&gt;
          &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each service (frontend, backend, ml) has: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;VirtualService&lt;/strong&gt; that decides which version handles the request
&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;DestinationRule&lt;/strong&gt; that defines two subsets based on the &lt;code&gt;version&lt;/code&gt; label: &lt;code&gt;stable&lt;/code&gt; and &lt;code&gt;canary&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Implementing Canary Releases with Headers and Weights
&lt;/h2&gt;

&lt;p&gt;The canary strategy is intentionally simple but powerful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Traffic Routing Logic
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;If request has header &lt;code&gt;x-canary: true&lt;/code&gt;&lt;/strong&gt; → 100% to canary version.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If header is missing&lt;/strong&gt; → Split by weight (for example, 90% stable, 10% canary).
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This pattern makes it easy to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send only internal testers to canary by setting the header.
&lt;/li&gt;
&lt;li&gt;Gradually increase canary weight without touching deployment specs.
&lt;/li&gt;
&lt;li&gt;Roll back instantly by adjusting VirtualService weights.
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing Canary Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Send request to canary version&lt;/span&gt;
curl &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"x-canary: true"&lt;/span&gt; http://frontend.local

&lt;span class="c"&gt;# Send request with default routing (weight-based)&lt;/span&gt;
curl http://frontend.local
&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%2Famcrh5wcdhu5rnelgbv1.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%2Famcrh5wcdhu5rnelgbv1.png" alt="traffic_split" width="800" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the same pattern is applied to all three services (frontend, backend, ML), a single user journey can be fully on canary or fully on stable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Enforcing Zero-Trust with STRICT mTLS
&lt;/h2&gt;

&lt;p&gt;To move toward a &lt;strong&gt;zero-trust model&lt;/strong&gt;, each namespace has a &lt;code&gt;PeerAuthentication&lt;/code&gt; resource that sets mTLS mode to &lt;code&gt;STRICT&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What This Means
&lt;/h3&gt;

&lt;p&gt;Services &lt;strong&gt;only accept encrypted traffic&lt;/strong&gt; from other sidecars in the mesh plain HTTP between pods is rejected.&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%2F5g5sjfgsgux6ew0gp92y.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%2F5g5sjfgsgux6ew0gp92y.png" alt="mTLS_verification" width="800" height="706"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Istio mTLS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Encryption&lt;/strong&gt; → Nobody can sniff requests or responses in transit.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutual authentication&lt;/strong&gt; → Prevents unknown workloads from accessing services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automated cert management&lt;/strong&gt; → No manual cert rotation or key generation.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example: PeerAuthentication
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security.istio.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PeerAuthentication&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mtls&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STRICT&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Istio documentation shows similar namespace-level policies to enforce strict mTLS for all workloads in a namespace.&lt;/p&gt;




&lt;h2&gt;
  
  
  Load Balancing, Connection Pools, and Circuit Breaking
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt;: Round-robin across all healthy pods in a subset.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection pools&lt;/strong&gt;: Limits on TCP connections and HTTP pending requests.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outlier detection&lt;/strong&gt;: After N consecutive errors, a pod is temporarily ejected from the pool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example: DestinationRule with Circuit Breaking
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.istio.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DestinationRule&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend-dr&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend-service&lt;/span&gt;
  &lt;span class="na"&gt;trafficPolicy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;connectionPool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;tcp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;maxConnections&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;
      &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;http1MaxPendingRequests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt;
        &lt;span class="na"&gt;maxRequestsPerConnection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
    &lt;span class="na"&gt;outlierDetection&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;consecutiveErrors&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
      &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10s&lt;/span&gt;
      &lt;span class="na"&gt;baseEjectionTime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;30s&lt;/span&gt;
  &lt;span class="na"&gt;subsets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;stable&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;canary&lt;/span&gt;
      &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;canary&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means if a canary version starts throwing errors, Istio automatically reduces its impact by isolating bad instances, &lt;strong&gt;without waiting for a rollback&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Observability: Metrics, Dashboards, and Traces
&lt;/h2&gt;

&lt;p&gt;The observability stack is built around Istio’s built-in telemetry.&lt;/p&gt;

&lt;h3&gt;
  
  
  Components
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&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;&lt;strong&gt;Prometheus&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Scrapes metrics from Envoy sidecars (request counts, errors, latency)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Grafana&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Visualizes mesh metrics (success rate, p99 latency per route)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Jaeger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Distributed tracing with high sampling for end-to-end visibility&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Deployment
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Deploy observability stack&lt;/span&gt;
kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; k8s/observability/

&lt;span class="c"&gt;# Access Grafana&lt;/span&gt;
kubectl port-forward &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system svc/grafana 3000:3000

&lt;span class="c"&gt;# Access Jaeger&lt;/span&gt;
kubectl port-forward &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system svc/jaeger-query 16686:16686

&lt;span class="c"&gt;# Access Prometheus&lt;/span&gt;
kubectl port-forward &lt;span class="nt"&gt;-n&lt;/span&gt; istio-system svc/prometheus 9090:9090
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Grafana Dashboard&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%2Fnbcjtkkppr3xi47og5wj.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%2Fnbcjtkkppr3xi47og5wj.png" alt="grafana_dashboard" width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Request Rate Per Service&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%2Fgua7az833anrtbiwruuf.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%2Fgua7az833anrtbiwruuf.png" alt="req_rate_per_svc" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distributed Tracing&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%2F8roj7n031koxqan5cwcu.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%2F8roj7n031koxqan5cwcu.jpg" alt="distributed_tracing" width="800" height="406"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Istio provides ready-made metrics and dashboards so you can quickly monitor mesh traffic, latency, and error rates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Walking Through a Single Request
&lt;/h2&gt;

&lt;p&gt;When a user hits the frontend through the Istio Ingress Gateway, the flow looks like this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request Flow
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1. User → Istio Ingress Gateway
   ↓ (VirtualService matches host/path)

2. Gateway → Frontend pod (stable or canary based on x-canary header/weight)
   ↓ (Frontend calls backend via Kubernetes DNS)

3. Frontend Envoy → Backend pod (VirtualService applies routing again)
   ↓ (Backend calls ML service)

4. Backend Envoy → ML pod (same routing logic)
   ↓ (ML inference completes)

5. Response flows back through the chain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What Happens at Each Hop
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;mTLS encryption&lt;/strong&gt; between all services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Metrics emission&lt;/strong&gt; to Prometheus.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace spans&lt;/strong&gt; sent to Jaeger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Circuit breaking&lt;/strong&gt; and &lt;strong&gt;outlier detection&lt;/strong&gt; enforced by DestinationRules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Seeing this full path in Jaeger, with timing for each hop, is one of the most useful parts of the setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Building this lab taught me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Service mesh adds &lt;strong&gt;zero-downtime deployments&lt;/strong&gt; and &lt;strong&gt;fine-grained traffic control&lt;/strong&gt; without code changes.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;mTLS enforcement&lt;/strong&gt; is straightforward with Istio and significantly improves security posture.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Observability&lt;/strong&gt; becomes a first-class thing with minimal instrumentation effort.
&lt;/li&gt;
&lt;li&gt;Understanding Istio’s primitives (&lt;strong&gt;Gateway&lt;/strong&gt;, &lt;strong&gt;VirtualService&lt;/strong&gt;, &lt;strong&gt;DestinationRule&lt;/strong&gt;, &lt;strong&gt;PeerAuthentication&lt;/strong&gt;) unlocks powerful traffic patterns.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For deeper reading, check out:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Istio Official Docs – &lt;a href="https://istio.io/latest/docs/concepts/traffic-management/" rel="noopener noreferrer"&gt;Traffic Management&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Istio Security – &lt;a href="https://istio.io/latest/docs/reference/config/security/peer_authentication/" rel="noopener noreferrer"&gt;PeerAuthentication&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Visualizing Metrics – &lt;a href="https://istio.io/latest/docs/tasks/observability/metrics/using-istio-dashboard/" rel="noopener noreferrer"&gt;Istio + Grafana Dashboard&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Full project README on GitHub: &lt;strong&gt;&lt;a href="https://github.com/Denyme24/3RVision-Platform" rel="noopener noreferrer"&gt;3RVision-Platform&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If this Istio lab setup helped you, consider ⭐ starring the &lt;a href="https://github.com/Denyme24/3RVision-Platform" rel="noopener noreferrer"&gt;repo&lt;/a&gt; or opening an issue/PR with improvements or ideas. Every bit of feedback, bug report, or contribution helps make this a better reference for anyone learning service mesh in the real world.&lt;/p&gt;




</description>
      <category>istio</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>servicemesh</category>
    </item>
    <item>
      <title>Model Context Protocol (MCP): Explained &amp; Built from Scratch.</title>
      <dc:creator>Naman Raj</dc:creator>
      <pubDate>Tue, 03 Jun 2025 05:20:34 +0000</pubDate>
      <link>https://dev.to/denyme24/model-context-protocol-mcp-explained-built-from-scratch-4fpa</link>
      <guid>https://dev.to/denyme24/model-context-protocol-mcp-explained-built-from-scratch-4fpa</guid>
      <description>&lt;p&gt;Hi, I’m &lt;strong&gt;Naman&lt;/strong&gt; a full stack developer.&lt;br&gt;
In this blog, I’m diving into the Model Context Protocol (MCP): what it is, why it matters, and how I went about building my own MCP server from the ground up.&lt;br&gt;
This will be a detailed breakdown: first, we’ll explore all the &lt;strong&gt;core concepts of MCP&lt;/strong&gt;, and then we’ll put that knowledge to work by &lt;strong&gt;building a functional MCP server from scratch&lt;/strong&gt;.&lt;br&gt;
Whether you're just hearing about MCP or looking to implement it yourself, this post breaks it down both conceptually and practically&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🧩 What is the Model Context Protocol (MCP)?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;Model Context Protocol (MCP)&lt;/strong&gt; is basically a way for different parts of a system to talk to each other but with context.&lt;/p&gt;

&lt;p&gt;It’s not just about asking the system to do something, it’s about helping it understand the situation around that action. So instead of just saying &lt;em&gt;&lt;strong&gt;“do X,”&lt;/strong&gt;&lt;/em&gt; you're saying &lt;strong&gt;&lt;em&gt;“do X, knowing that Y and Z are also true right now.”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;dimage ke upar se gya&lt;/em&gt;(sounds a bit vague), here’s a simple example:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Let’s say you walk into a coffee shop and say, “I’ll have a latte.”&lt;br&gt;
A regular system gives you a latte, no questions asked.&lt;br&gt;
But a system using context? That’s the barista who notices it’s raining, sees you’re soaked, and decides to make your latte extra hot and finds you a warm seat inside.&lt;br&gt;
That’s what context does. And that’s the idea behind MCP, it helps systems make better decisions based on what’s going on around them&lt;/em&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🧭 Where Did MCP Come From?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;MCP actually started off in the &lt;strong&gt;Minecraft modding scene&lt;/strong&gt; yeah, really. Developers used it to understand and tweak how the game behaved internally.&lt;/p&gt;

&lt;p&gt;Over time, the concept became more general. Now, it's useful in things like &lt;strong&gt;AI systems&lt;/strong&gt;, &lt;strong&gt;backend workflows&lt;/strong&gt;, and apps where understanding the bigger picture matters&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🔍 Why MCP?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Most systems work in a straightforward way. You send a request, they do something.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;strong&gt;&lt;em&gt;“Give me the user data”&lt;br&gt;
“Update this post”&lt;br&gt;
“Delete that file”&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That works fine when everything is simple. But when your system needs to &lt;strong&gt;make decisions based on what’s happening&lt;/strong&gt;, those basic calls fall short.&lt;/p&gt;

&lt;p&gt;That’s where MCP comes in. It asks questions like:&lt;br&gt;
&lt;em&gt;&lt;strong&gt;What’s the current state of the system?&lt;br&gt;
What just happened before this command?&lt;br&gt;
Should we respond differently depending on the situation?&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;System ko thoda samajhdaar banane jaisa hai, jaise backend ko bol diya ho, &lt;strong&gt;"bhai, thoda dimaag laga."&lt;/strong&gt;&lt;br&gt;
(It’s like giving your backend a bit more awareness as if you’ve told it, “bro, use your brain a little.”)&lt;br&gt;
Aur jab system fast changing ho, jaise AI tools ya complex workflows fir to bhai &lt;strong&gt;waha yeh samajh bohot kaam aata hai&lt;/strong&gt;.&lt;br&gt;
(And when your system is fast changing like AI tools or workflow engines  that extra awareness really helps.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🛠 Real Life Example: Your Desi Smart Assistant&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you’ve got a smart assistant at home let’s call it &lt;em&gt;&lt;strong&gt;“Marco AI.”&lt;/strong&gt;&lt;/em&gt;&lt;br&gt;
Now you say:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Marco, light band kar de.”&lt;br&gt;
(“Marco, turn off the lights.”)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If it’s a basic assistant, it'll just go:&lt;br&gt;
&lt;strong&gt;Poof. Lights off. Kaam khatam.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But if it's context-aware using something like MCP, here’s how it might think:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;Time check&lt;/strong&gt;: Oh, it’s 11:30 PM.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Motion detection&lt;/strong&gt;: There’s still someone moving in the kitchen.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Recent command&lt;/strong&gt;: You just said “Good night” 2 minutes ago in the bedroom.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So now instead of killing all the lights like a power cut:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It only &lt;strong&gt;turns off the bedroom light&lt;/strong&gt;, not the kitchen one (because someone's still grabbing water).&lt;/li&gt;
&lt;li&gt;It &lt;strong&gt;starts your night routine&lt;/strong&gt;: turns on DND on your phone, lowers fan speed, and maybe even plays that lo-fi playlist you always fall asleep to.&lt;/li&gt;
&lt;li&gt;And yeah, it doesn’t turn off the bathroom light because &lt;strong&gt;you left it on and MCP knows you always forget&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Yeh wahi baat hai — ek normal banda bolta hai “light band kar,” aur doosra poochta hai, “kaunsi? sab ki?&lt;/strong&gt;”&lt;br&gt;
(It’s the difference between someone who follows orders and someone who thinks before acting.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🔧 2. Core Concepts of MCP&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The beauty of MCP lies in how it structures &lt;strong&gt;communication between models&lt;/strong&gt;, making them aware of the environment they’re operating in. Think of it as building systems that “&lt;em&gt;know what’s going on&lt;/em&gt;” instead of blindly executing commands.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;🧠 2.1 Model-Context Design&lt;/strong&gt;&lt;br&gt;
In MCP, a “&lt;em&gt;context&lt;/em&gt;” is a set of facts or environmental data that helps a model understand what’s happening right now. This includes things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The current state of the system&lt;/li&gt;
&lt;li&gt;Recent events or actions&lt;/li&gt;
&lt;li&gt;Inputs from other models&lt;/li&gt;
&lt;li&gt;External data like time, user info, etc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why it matters&lt;/strong&gt;:&lt;br&gt;
Instead of just saying "do task X", you're saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“&lt;em&gt;Do task X, but keep in mind we’re in state Y, action Z just happened, and model A is waiting on your output.&lt;/em&gt;”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Example&lt;/strong&gt;: If a user says “cancel my subscription” in an app, the model doesn’t just delete the plan it checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Did the user already initiate a refund request?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Are there any active services running?&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Is there a promotion that could retain them?&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🧾 2.2 Command-based Architecture&lt;/strong&gt;&lt;br&gt;
MCP systems rely on a command driven flow like a structured conversation where each action is a clearly defined message.&lt;/p&gt;

&lt;p&gt;A command is not just an API call or function; it’s a semantic instruction:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CreateOrder&lt;br&gt;
 UpdateInventory&lt;br&gt;
 NotifyUser&lt;br&gt;
 EvaluateResponse&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Each command carries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Intent&lt;/strong&gt;: What action is requested&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Context&lt;/strong&gt;: What the system knows right now&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Payload&lt;/strong&gt;: Any required data (e.g., user ID, product ID)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it easy to &lt;strong&gt;track, test, and extend behavior&lt;/strong&gt;. Think of it like building with Lego blocks each command has a clear shape and job and can plug into other parts cleanly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;📦 2.3 State Handling&lt;/strong&gt;&lt;br&gt;
MCP treats state as a first-class citizen. That means each model doesn’t just operate in isolation, it shares and consumes state via a &lt;strong&gt;central context manager&lt;/strong&gt; or store.&lt;/p&gt;

&lt;p&gt;Key aspects of state handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Models read from shared context&lt;/li&gt;
&lt;li&gt;They update the context with new outcomes&lt;/li&gt;
&lt;li&gt;The context flows with the execution kind of like a memory that travels&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Let’s say you’re using GitHub Copilot in Agent mode, and you switch between different models during the session say from GPT-4 to Claude 3 Sonnet, or Gemini 2.5.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Despite switching models, your &lt;strong&gt;session context stays intact&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your previous code&lt;/li&gt;
&lt;li&gt;The task you're working on&lt;/li&gt;
&lt;li&gt;The error you just ran into&lt;/li&gt;
&lt;li&gt;Even the last thing you asked the assistant&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;“Model badal gaya, par yaadein wahi rahi. 😂”&lt;/em&gt;&lt;br&gt;
&lt;em&gt;(The model changed, but the memories stayed the same.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That’s basically how &lt;strong&gt;MCP handles state&lt;/strong&gt; like a central memory bank all models read from and write to. So whether it’s one model or many, they all operate with a shared understanding of ‘what’s going on’&lt;/p&gt;

&lt;p&gt;This is what allows things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Chaining responses across models&lt;/li&gt;
&lt;li&gt;Smarter multi-agent reasoning&lt;/li&gt;
&lt;li&gt;Being able to &lt;em&gt;"pause and resume"&lt;/em&gt; with full context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;🧩 2.4 Decoupling Logic&lt;/strong&gt;&lt;br&gt;
This is where MCP really shines. By using &lt;strong&gt;commands + shared context&lt;/strong&gt;, MCP naturally leads to modular and decoupled system design.&lt;/p&gt;

&lt;p&gt;What this means in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each model (or agent) focuses on its specific job&lt;/li&gt;
&lt;li&gt;No model needs to know how others work internally&lt;/li&gt;
&lt;li&gt;Communication happens only via commands and context not direct calls or dependencies&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to scale&lt;/li&gt;
&lt;li&gt;Easier to test (you can unit-test models independently)&lt;/li&gt;
&lt;li&gt;Easier to swap in new models (AI version A to version B, for example)&lt;/li&gt;
&lt;li&gt;Less fragile one model crashing doesn't break the others&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;strong&gt;🧠 MCP Server Architecture Explained&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The Model Context Protocol (MCP) Server is a modular system designed to handle model driven command execution with a focus on tools, resources, and prompt management. This architecture is scalable, extensible, and supports multiple transport protocols and storage backends.&lt;/p&gt;

&lt;p&gt;Here is the architecture diagram (Zoom in) ⬇️&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%2Fscwts1889wblu5sxkvje.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%2Fscwts1889wblu5sxkvje.png" alt="architecture diagram" width="800" height="2034"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  📦 Components Breakdown
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Transport Layer&lt;/strong&gt;&lt;br&gt;
The Transport Layer handles the actual communication between the AI client and your MCP server. Think of it as the "delivery method" for messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STDIO Transport:&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;const transport = new StdioServerTransport();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Uses standard input/output streams&lt;/li&gt;
&lt;li&gt;Most common for local MCP servers&lt;/li&gt;
&lt;li&gt;No network configuration required&lt;/li&gt;
&lt;li&gt;Direct process-to-process communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;HTTP Transport:&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;const transport = new HTTPServerTransport();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Uses HTTP protocol over network&lt;/li&gt;
&lt;li&gt;Useful for remote MCP servers&lt;/li&gt;
&lt;li&gt;Requires port and URL configuration&lt;/li&gt;
&lt;li&gt;Can handle multiple concurrent clients&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;WebSocket Transport:&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;const transport = new WebSocketTransport();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Real-time bidirectional communication&lt;/li&gt;
&lt;li&gt;Good for streaming data&lt;/li&gt;
&lt;li&gt;Maintains persistent connections&lt;/li&gt;
&lt;li&gt;Lower latency than HTTP&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Custom Transport:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can implement your own transport method&lt;/li&gt;
&lt;li&gt;Must follow MCP protocol specifications&lt;/li&gt;
&lt;li&gt;Useful for specialized communication needs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Command Dispatcher&lt;/strong&gt;&lt;br&gt;
The Command Dispatcher is the "traffic controller" of your MCP server. It receives all incoming requests and decides where to send them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request Analysis: Examines the incoming JSON-RPC message&lt;/li&gt;
&lt;li&gt;Route Determination: Decides which handler should process the request&lt;/li&gt;
&lt;li&gt;Schema Validation: Ensures request format is correct&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example Request Routing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Incoming request
{
  "method": "tools/call",
  "params": { "name": "get_completed_payments" }
}

// Router logic
if (method === "tools/call") {
  route_to_tools_handler();
} else if (method === "resources/read") {
  route_to_resources_handler();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is like a traffic cop 🚦:&lt;/p&gt;

&lt;p&gt;If the request says &lt;code&gt;"tools/call"&lt;/code&gt; → send it to the Tools Handler&lt;br&gt;
If it says &lt;code&gt;"resources/read"&lt;/code&gt; → send it to the Resources Handler&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Handler Components&lt;/strong&gt;&lt;br&gt;
The server has three main types of handlers, each responsible for different MCP capabilities:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.1 Tools Handler&lt;/strong&gt;&lt;br&gt;
Processes executable functions that perform actions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handles Two Request Types:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;tools/list&lt;/code&gt;: Returns available tools&lt;br&gt;
&lt;code&gt;tools/call&lt;/code&gt;: Executes a specific tool&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Implementation:&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;// tools/list response
{
  "tools": [
    {
      "name": "weather_forecast",
      "description": "Get weather forecast for a location",
      "inputSchema": {
        "type": "object",
        "properties": {
          "location": {
            "type": "string",
            "description": "City name"
          }
        },
        "required": ["location"]
      }
    },
    {
      "name": "calculator",
      "description": "Perform basic math calculations",
      "inputSchema": {
        "type": "object",
        "properties": {
          "operation": {
            "type": "string",
            "enum": ["add", "subtract", "multiply", "divide"]
          },
          "num1": { "type": "number" },
          "num2": { "type": "number" }
        },
        "required": ["operation", "num1", "num2"]
      }
    }
  ]
}
&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;// tools/call execution
// Example 1: Weather forecast tool
async function executeWeatherForecast(params) {
  const { location } = params;

  // Get weather data (simplified)
  const weather = {
    location: location,
    temperature: "72°F",
    condition: "Sunny",
    forecast: "Clear skies all day"
  };

  return { 
    content: [
      { 
        type: "text", 
        text: `Weather for ${location}: ${weather.temperature}, ${weather.condition}. 
               Forecast: ${weather.forecast}`
      }
    ] 
  };
}

// Example 2: Calculator tool
async function executeCalculator(params) {
  const { operation, num1, num2 } = params;
  let result;

  // Perform calculation
  switch(operation) {
    case "add": 
      result = num1 + num2;
      break;
    case "subtract":
      result = num1 - num2;
      break;
    case "multiply":
      result = num1 * num2;
      break;
    case "divide":
      result = num1 / num2;
      break;
  }

  return { 
    content: [
      { 
        type: "text", 
        text: `${num1} ${operation} ${num2} = ${result}`
      }
    ] 
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.2 Resources Handler&lt;/strong&gt;&lt;br&gt;
Manages static data and content that can be read.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Handles Two Request Types:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;resources/list&lt;/code&gt;: Returns available resources&lt;br&gt;
&lt;code&gt;resources/read&lt;/code&gt;: Retrieves resource content&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;resources/list Response:&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;{
  "resources": [
    {
      "uri": "recipes://breakfast",
      "name": "Breakfast Recipes",
      "description": "Collection of breakfast recipes",
      "mimeType": "application/json"
    },
    {
      "uri": "notes://shopping-list",
      "name": "Shopping List",
      "description": "Current shopping list items",
      "mimeType": "text/plain"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;resources/read Execution:&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;// Example resource handler
async function readResource(uri) {
  // Breakfast recipes resource
  if (uri === "recipes://breakfast") {
    const breakfastRecipes = [
      { name: "Scrambled Eggs", ingredients: ["eggs", "butter", "salt"] },
      { name: "Pancakes", ingredients: ["flour", "milk", "eggs", "sugar"] }
    ];

    return { 
      contents: [
        { 
          uri: uri,
          text: JSON.stringify(breakfastRecipes, null, 2),
          mimeType: "application/json" 
        }
      ] 
    };
  } 
  // Shopping list resource
  else if (uri === "notes://shopping-list") {
    const shoppingList = 
      "1. Milk\n" +
      "2. Bread\n" +
      "3. Eggs\n" +
      "4. Apples\n" +
      "5. Coffee";

    return { 
      contents: [
        { 
          uri: uri,
          text: shoppingList,
          mimeType: "text/plain" 
        }
      ] 
    };
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3.3 Prompts Handler&lt;/strong&gt;&lt;br&gt;
Manages pre-defined prompts that can be used by the AI client.&lt;/p&gt;

&lt;p&gt;In your architecture, the Prompt Handler is the part of the server that deals with prompts aka the messages or instructions that you send to the AI to make it do something.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Think of prompts like the script you give an actor. The AI is the actor, and your prompt tells it what to say or do.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;strong&gt;Prompt Handler&lt;/strong&gt; helps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;List all available prompts&lt;/li&gt;
&lt;li&gt;Fetch a specific prompt&lt;/li&gt;
&lt;li&gt;Inject variables into prompts (dynamic prompts)&lt;/li&gt;
&lt;li&gt;Send these prompts to the AI client (like Claude, GPT, etc.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;prompts/list&lt;/code&gt;: Returns a list of all available prompts.&lt;br&gt;
&lt;strong&gt;Example response:&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;["generate_invoice", "summarize_text", "write_lawyer_reply"]

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

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;prompts/get&lt;/code&gt;: Fetches the full prompt template for a given name.&lt;br&gt;
&lt;strong&gt;Example request:&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;{
  "method": "prompts/get",
  "params": { "name": "summarize_text" }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example response:&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;{
  "template": "Summarize the following text:\n\n{{input_text}}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then plug in dynamic input like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"input_text": "The Supreme Court ruled in favor of the plaintiff in a landmark decision..."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the final prompt becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Summarize the following text:

The Supreme Court ruled in favor of the plaintiff in a landmark decision...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Model Registry&lt;/strong&gt;&lt;br&gt;
The Model Registry is the "rulebook" for your MCP server. It stores schemas, validation rules, and metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three Main Components:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;Tool Schemas:&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;{
  "name": "convert_temperature",
  "description": "Convert between Fahrenheit and Celsius",
  "inputSchema": {
    "type": "object",
    "properties": {
      "value": { 
        "type": "number",
        "description": "Temperature value to convert" 
      },
      "from": { 
        "type": "string",
        "enum": ["celsius", "fahrenheit"],
        "description": "Source temperature unit" 
      }
    },
    "required": ["value", "from"]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Defines input/output validation&lt;/li&gt;
&lt;li&gt;Stores tool metadata and descriptions&lt;/li&gt;
&lt;li&gt;Ensures type safety&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Resource Schemas:&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;{
  "uri": "payments://done",
  "mimeType": "application/json",
  "description": "All completed payments"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Defines URI patterns&lt;/li&gt;
&lt;li&gt;Specifies content types&lt;/li&gt;
&lt;li&gt;Provides resource descriptions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Prompt Templates:&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;{
  "name": "payment_summary",
  "template": "Summarize {count} payments totaling ${amount}",
  "arguments": ["count", "amount"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Stores reusable prompt templates&lt;/li&gt;
&lt;li&gt;Manages dynamic prompt generation&lt;/li&gt;
&lt;li&gt;Defines prompt arguments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Context Storage&lt;/strong&gt;&lt;br&gt;
The Context Storage layer manages data persistence and retrieval. Your MCP server can use multiple storage backends.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storage Types:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;In-Memory Storage:&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;const sessionData = new Map();
const cache = new Map();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Fast access for temporary data&lt;/li&gt;
&lt;li&gt;Session management&lt;/li&gt;
&lt;li&gt;Caching frequently accessed data&lt;/li&gt;
&lt;li&gt;Lost when server restarts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Database Storage:&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;// MongoDB example
const payments = await db.collection('payments').find({}).toArray();

// PostgreSQL example
const result = await client.query('SELECT * FROM payments WHERE done = true');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Persistent data storage&lt;/li&gt;
&lt;li&gt;Complex queries and relationships&lt;/li&gt;
&lt;li&gt;ACID compliance (for SQL databases)&lt;/li&gt;
&lt;li&gt;Scalable for large datasets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;File System Storage:&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;const fs = require('fs');
const data = fs.readFileSync('/path/to/data.json');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Local file operations&lt;/li&gt;
&lt;li&gt;Log storage&lt;/li&gt;
&lt;li&gt;Configuration files&lt;/li&gt;
&lt;li&gt;Simple data persistence&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;External APIs:&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;// REST API call
const response = await fetch('https://api.example.com/payments');

// GraphQL query
const result = await graphql(schema, query);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Integration with external services&lt;/li&gt;
&lt;li&gt;Real-time data from third parties&lt;/li&gt;
&lt;li&gt;Webhook processing&lt;/li&gt;
&lt;li&gt;Microservices communication&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;ALRIGHT DEVS! I'M GLAD WE MAKE IT TILL HERE, BECAUSE IT'S TIME WE BUILD ONE 🔥&lt;/strong&gt;
&lt;/h2&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;🧠Building Our Own MCP Server: A Step-by-Step Guide&lt;/strong&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;In this guide, I'll walk you through creating a Model Context Protocol (MCP) server that exposes my MongoDB data to Large Language Models (LLMs) like Claude. We'll build a server that manages payment data and makes it accessible through both MCP Resources and Tools.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before we begin, make sure we have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed (v14 or higher)&lt;/li&gt;
&lt;li&gt;MongoDB Atlas account (or a local MongoDB instance)&lt;/li&gt;
&lt;li&gt;Basic understanding of JavaScript/Node.js&lt;/li&gt;
&lt;li&gt;Claude Desktop installed (for testing with LLM)&lt;/li&gt;
&lt;li&gt;MCP Inspector (for debugging and testing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Project Setup&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;mkdir mcp_server
cd mcp_server
npm init -y
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the required dependencies:&lt;br&gt;
&lt;code&gt;npm install @modelcontextprotocol/sdk mongodb&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Server Implementation&lt;/strong&gt;&lt;br&gt;
Let's create our &lt;code&gt;index.js&lt;/code&gt; file and break down each component in detail:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Basic Server Setup and Imports&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;import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListToolsRequestSchema,
  CallToolRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { MongoClient } from "mongodb";

// Initialize the MCP server
const server = new Server(
  {
    name: "NextApp Payments Resource",
    version: "1.0.0",
  },
  {
    capabilities: {
      resources: {}, // We'll expose payment resources
      tools: {}, // We'll expose payment-related tools
    },
  }
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Imports necessary MCP SDK components&lt;/li&gt;
&lt;li&gt;Imports MongoDB client&lt;/li&gt;
&lt;li&gt;Creates a new MCP server instance with metadata&lt;/li&gt;
&lt;li&gt;Defines server capabilities (resources and tools)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. MongoDB Connection Setup&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;// MongoDB connection setup with error handling
const uri = process.env.MONGODB_URI;
if (!uri) {
  console.error(
    JSON.stringify({
      type: "error",
      message: "MONGODB_URI environment variable is required",
    })
  );
  process.exit(1);
}

// Helper function for MongoDB operations
async function withMongoDB(operation) {
  let client;
  try {
    client = new MongoClient(uri);
    await client.connect();
    const db = client.db("test");
    return await operation(db);
  } catch (error) {
    console.error(
      JSON.stringify({
        type: "error",
        message: "MongoDB Error",
        error: error.message,
      })
    );
    throw error;
  } finally {
    if (client) {
      await client.close();
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates MongoDB connection string&lt;/li&gt;
&lt;li&gt;Creates a reusable helper function for database operations&lt;/li&gt;
&lt;li&gt;Implements proper connection handling and cleanup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Implementing MCP Tools&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;// Define and implement tools
server.setRequestHandler(ListToolsRequestSchema, async () =&amp;gt; {
  return {
    tools: [
      {
        name: "get_completed_payments",
        description: "\"Get all payments where done is true\","
        inputSchema: {
          type: "object",
          properties: {},
          required: [],
        },
      },
      {
        name: "get_all_payments",
        description: "\"Get all payments from the database\","
        inputSchema: {
          type: "object",
          properties: {},
          required: [],
        },
      },
    ],
  };
});

// Handle tool execution
server.setRequestHandler(CallToolRequestSchema, async (request) =&amp;gt; {
  const { name } = request.params;

  const handlePayments = async (query = {}) =&amp;gt; {
    return await withMongoDB(async (db) =&amp;gt; {
      const payments = await db.collection("payments").find(query).toArray();
      return {
        content: [
          {
            type: "text",
            text: JSON.stringify(payments, null, 2),
          },
        ],
      };
    });
  };

  switch (name) {
    case "get_completed_payments":
      return handlePayments({ done: true });
    case "get_all_payments":
      return handlePayments();
    default:
      throw new Error(`Unknown tool: ${name}`);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This implements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tool registration with clear descriptions&lt;/li&gt;
&lt;li&gt;Input schema definitions (empty in this case)&lt;/li&gt;
&lt;li&gt;Reusable payment handling logic&lt;/li&gt;
&lt;li&gt;Specific tool implementations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;get_completed_payments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Description: Retrieves all payments where done is true&lt;/li&gt;
&lt;li&gt;Input: No parameters required&lt;/li&gt;
&lt;li&gt;Output: JSON array of completed payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;get_all_payments&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Description: Retrieves all payments from the database&lt;/li&gt;
&lt;li&gt;Input: No parameters required&lt;/li&gt;
&lt;li&gt;Output: JSON array of all payments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Implementing MCP Resources&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;// Define available resources
server.setRequestHandler(ListResourcesRequestSchema, async () =&amp;gt; {
  return {
    resources: [
      {
        uri: "payments://done",
        name: "Completed Payments",
        description: "\"All payments where done is true\","
        mimeType: "application/json",
      },
    ],
  };
});

// Handle resource reading
server.setRequestHandler(ReadResourceRequestSchema, async (request) =&amp;gt; {
  const { uri } = request.params;

  if (uri === "payments://done") {
    return await withMongoDB(async (db) =&amp;gt; {
      const payments = await db
        .collection("payments")
        .find({ done: true })
        .toArray();

      return {
        contents: [
          {
            uri: uri,
            text: JSON.stringify(payments, null, 2),
            mimeType: "application/json",
          },
        ],
      };
    });
  }

  throw new Error(`Unknown resource: ${uri}`);
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defines a resource for completed payments&lt;/li&gt;
&lt;li&gt;Implements resource reading logic&lt;/li&gt;
&lt;li&gt;Uses our MongoDB helper function&lt;/li&gt;
&lt;li&gt;Returns properly formatted JSON responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Server Startup&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;// Main function to start the server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);

  console.error(
    JSON.stringify({
      type: "info",
      message: "MCP server started with tools and resources",
    })
  );
}

main().catch((error) =&amp;gt;
  console.error(
    JSON.stringify({
      type: "error",
      message: "Server startup error",
      error: error.message,
    })
  )
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3: Configuration Setup&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;MCP Inspector Configuration&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;MCP Inspector is a development tool that helps you test and debug your MCP server. Here's how to set it up:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Start your server:&lt;/strong&gt;&lt;br&gt;
&lt;code&gt;node index.js&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Access MCP Inspector:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Open your browser and navigate to &lt;code&gt;http://localhost:6274/#resources&lt;/code&gt;&lt;br&gt;
The Inspector will automatically connect to your running server&lt;br&gt;
You can test resources and tools directly from the interface&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%2Fq3nh8t4c9ffkijw49grn.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%2Fq3nh8t4c9ffkijw49grn.png" alt="mcp inspector" width="800" height="432"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The image above shows the MCP Inspector interface displaying the payment records retrieved from MongoDB Atlas through the MCP server.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Claude Desktop Configuration&lt;/strong&gt;&lt;br&gt;
Let's walk through the process of configuring your MCP server in Claude Desktop:&lt;/p&gt;

&lt;p&gt;Step 1: Access Settings&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Claude Desktop application&lt;/li&gt;
&lt;li&gt;Click on the hamburger menu (three lines) in the top-left corner&lt;/li&gt;
&lt;li&gt;Select "File" → "Settings"&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%2Fzcvs4mq6h8w2sdpnnzw6.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%2Fzcvs4mq6h8w2sdpnnzw6.png" alt="claude setup" width="479" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 2: Configure MCP Server&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &lt;strong&gt;In the Settings window, select the "Developer" tab&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Click on "Edit Config" button&lt;/strong&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%2F14hb3hnytvob7adn9uyq.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%2F14hb3hnytvob7adn9uyq.png" alt="claude settings" width="800" height="543"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;This will open your Claude configuration file in your default text editor&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Windows: &lt;code&gt;C:\Users\&amp;lt;username&amp;gt;\AppData\Roaming\claude\claude_desktop_config.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;macOS: &lt;code&gt;~/Library/Application Support/claude/claude_desktop_config.json&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Linux: &lt;code&gt;~/.config/claude/claude_desktop_config.json&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%2Fs03vhh75iducrynxl4dj.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%2Fs03vhh75iducrynxl4dj.png" alt="claude config file" width="800" height="666"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Add your server configuration to the file:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "mcpServers": {
    "PaymentsResource": {
      "command": "node",
      "args": ["C:/path/to/your/index.js"],
      "env": {
        "MONGODB_URI": "mongodb+srv://your-connection-string"
      }
    }
  }
}

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

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Step 3: Apply Changes&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Save the configuration file&lt;/li&gt;
&lt;li&gt;Close the text editor&lt;/li&gt;
&lt;li&gt;Close Claude Desktop completely&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Important&lt;/strong&gt;: Sometimes just closing the application isn't enough

&lt;ul&gt;
&lt;li&gt;Windows: Open Task Manager (Ctrl + Shift + Esc)&lt;/li&gt;
&lt;li&gt;Find "Claude" in the processes&lt;/li&gt;
&lt;li&gt;Right-click and select "End Task"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Restart Claude Desktop&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Verify Server Connection&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Claude Desktop&lt;/li&gt;
&lt;li&gt;Go to Settings → Developer tab&lt;/li&gt;
&lt;li&gt;You should see your MCP server listed as &lt;strong&gt;"running"&lt;/strong&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%2Feqr1opyfloda1uiupcr9.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%2Feqr1opyfloda1uiupcr9.png" alt="mcp server running" width="800" height="548"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Using Your MCP Server&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to the main Claude chat interface&lt;/li&gt;
&lt;li&gt;Look for the search and tools options at the top&lt;/li&gt;
&lt;li&gt;You'll find your configured MCP server in the tools list&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;[NOTE: You will be asked to give the permission, to use those tools.]&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%2Fkd09sd9kz1q2v7id5cqn.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%2Fkd09sd9kz1q2v7id5cqn.jpg" alt="claude permission" width="800" height="829"&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%2F83mbj7n3gmqs8e1oypaw.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%2F83mbj7n3gmqs8e1oypaw.png" alt="mcp configured in claude" width="800" height="473"&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%2Foyeqjinpyie5pkmp6y1e.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%2Foyeqjinpyie5pkmp6y1e.png" alt="mcp tools in claude" width="800" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To use resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the upload button (+) on the left sidebar&lt;/li&gt;
&lt;li&gt;Select from your available resources&lt;/li&gt;
&lt;li&gt;Query the resource as needed&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%2Fqiwrtfz0gfl2g6ripfdm.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%2Fqiwrtfz0gfl2g6ripfdm.png" alt="payment resource" width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Once you click on that "Add from Payment Resource"&lt;/strong&gt;&lt;br&gt;
You will be able to upload your Completed Payments resource&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%2Fvas2298jh928be68f6b7.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%2Fvas2298jh928be68f6b7.png" alt="payment resource 1" width="800" height="375"&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%2F4ujm0rj7x8c6nxs64qpk.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%2F4ujm0rj7x8c6nxs64qpk.png" alt="payment resource 2" width="800" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Testing Your Implementation&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Start your server:&lt;br&gt;
&lt;code&gt;node index.js&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In Claude Desktop:&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Verify server status in Settings → Developer&lt;/li&gt;
&lt;li&gt;Your server should show as "running"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Test commands&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;# Test resource access
Use the MCP resource payments://done and show me all completed payments

# Test tools
Use the MCP tool get_completed_payments to show me successful transactions
Use the MCP tool get_all_payments to display all payment records
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;USING TOOL&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%2Fjs8q4qg9s3xxblck8ab0.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%2Fjs8q4qg9s3xxblck8ab0.jpg" alt="final result" width="690" height="927"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;USING RESOURCE&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%2Fzyihh95xtphfp21kl4ah.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%2Fzyihh95xtphfp21kl4ah.png" alt="final result 2" width="800" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting Guide
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Common Issues and Solutions
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Server Won't Start&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check Node.js version&lt;/li&gt;
&lt;li&gt;Verify file paths in config&lt;/li&gt;
&lt;li&gt;Check for syntax errors&lt;/li&gt;
&lt;li&gt;Verify MongoDB URI&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Claude Can't Connect&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check config file location&lt;/li&gt;
&lt;li&gt;Verify absolute paths&lt;/li&gt;
&lt;li&gt;Check environment variables&lt;/li&gt;
&lt;li&gt;Restart Claude Desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MCP Inspector Issues&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify server is running&lt;/li&gt;
&lt;li&gt;Check port 6274 is available&lt;/li&gt;
&lt;li&gt;Look for console errors&lt;/li&gt;
&lt;li&gt;Check browser console&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;MongoDB Connection Failed&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verify connection string&lt;/li&gt;
&lt;li&gt;Check network connectivity&lt;/li&gt;
&lt;li&gt;Verify database permissions&lt;/li&gt;
&lt;li&gt;Check IP whitelist&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;em&gt;&lt;strong&gt;"SHEEESHHH!! NOW WE HAVE OUR OWN MCP SERVER"&lt;/strong&gt;&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Working on this project was honestly a fun deep dive into how we can make large language models a lot smarter with real world, live data. We built a custom MCP server that connects directly to MongoDB, giving Claude access to actual payment data using tools and resources and We designed from scratch. This whole thing isn’t just a tech demo; it’s a glimpse into how we can build AI apps that are actually aware of context and data that matters in the moment.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;We've now built a fully functional MCP server that:&lt;/li&gt;
&lt;li&gt;Exposes MongoDB data through MCP resources&lt;/li&gt;
&lt;li&gt;Provides tools for querying payments&lt;/li&gt;
&lt;li&gt;Integrates with Claude Desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That’s it from my end for now!&lt;br&gt;
If you’ve made it this far thanks for checking it out. If you’re building something similar, playing around with MCP, or just wanna collaborate on AI ideas, feel free to fork the repo, drop a star, or hit me up on GitHub: &lt;a href="https://github.com/Denyme24" rel="noopener noreferrer"&gt;@Denyme24&lt;/a&gt; or LinkedIn: &lt;a href="https://www.linkedin.com/in/namanraj24/" rel="noopener noreferrer"&gt;in/namanraj24&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;🔗 Repo for reference: &lt;a href="https://github.com/Denyme24/my-mcp-server" rel="noopener noreferrer"&gt;my-mcp-server&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Catch ya in the next project.&lt;br&gt;
Stay curious &amp;amp; keep building 🚀🧠&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>architecture</category>
      <category>webdev</category>
      <category>backend</category>
    </item>
    <item>
      <title>We Came. We Coded. We Cleaned the Planet (and Won).</title>
      <dc:creator>Naman Raj</dc:creator>
      <pubDate>Tue, 15 Apr 2025 13:43:50 +0000</pubDate>
      <link>https://dev.to/denyme24/we-came-we-coded-we-cleaned-the-planet-and-won-4ich</link>
      <guid>https://dev.to/denyme24/we-came-we-coded-we-cleaned-the-planet-and-won-4ich</guid>
      <description>&lt;blockquote&gt;
&lt;h2&gt;
  
  
  ⚙️ Set the Scene
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;It all started with an open problem, a crew too stubborn to quit, and 24 hours to ship something real.&lt;/p&gt;

&lt;p&gt;We entered this &lt;strong&gt;national-level hackathon&lt;/strong&gt; with a clear goal: to build something that didn’t just work but mattered. The theme was &lt;strong&gt;Open Innovation&lt;/strong&gt;, and while the freedom was exciting, we knew we had to be intentional. Instead of chasing trends, we focused on a problem that’s real, relevant, and way too often ignored- &lt;strong&gt;waste management&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s how &lt;strong&gt;3RVision&lt;/strong&gt; was born. An AI-powered platform designed to help users identify household waste and figure out whether it can be &lt;em&gt;reused, recycled, or resold&lt;/em&gt;. It’s a practical, user-focused solution for a global issue. Built with machine learning, clean UI, and an emphasis on sustainability, we aimed to make responsible living more accessible and a little bit smarter.&lt;/p&gt;

&lt;p&gt;We weren’t trying to impress with flashy features we wanted to solve a real-world problem in a way that actually sticks.&lt;/p&gt;

&lt;p&gt;The 24 hours were intense. &lt;strong&gt;Between debugging models&lt;/strong&gt;, &lt;strong&gt;designing flows&lt;/strong&gt;, and &lt;strong&gt;juggling backend chaos&lt;/strong&gt;, there were moments we genuinely thought we wouldn’t make it in time. But somehow, everything clicked just enough in the final stretch. &lt;strong&gt;And yeah that last-minute demo that somehow actually worked?&lt;/strong&gt; Definitely one for the memory books.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  👥 The Dream Team
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every winning project needs a team that just &lt;em&gt;clicks&lt;/em&gt;, and we had that from the jump.&lt;/p&gt;

&lt;p&gt;There weren’t strict roles or &lt;strong&gt;&lt;em&gt;“you do this, I do that&lt;/em&gt;&lt;/strong&gt;” energy. We were all in, all the time switching gears between frontend, backend, ML, and sometimes just keeping each other sane. Everyone wore multiple hats, and somehow, it worked.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/khushiiagrawal" rel="noopener noreferrer"&gt;&lt;strong&gt;Khushi&lt;/strong&gt;&lt;/a&gt; – The &lt;strong&gt;team lead&lt;/strong&gt; and the brain behind the idea. She steered &lt;br&gt;
the ship, worked on the ML side, and constantly pushed the UI to &lt;br&gt;
look and feel better. Super picky about the frontend—and yeah, she &lt;br&gt;
kept me on my toes with it 😮‍💨.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Denyme24" rel="noopener noreferrer"&gt;Naman (me)&lt;/a&gt;&lt;/strong&gt; – Took charge of the &lt;strong&gt;frontend&lt;/strong&gt;, handled components, API stuff, Authentication and also chipped in on the backend. Made sure everything worked like it should, visually and under the hood.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Arpit529Srivastava" rel="noopener noreferrer"&gt;Arpit&lt;/a&gt;&lt;/strong&gt; – The utility player who pulled off two big wins building the &lt;strong&gt;Chrome extension&lt;/strong&gt; and strengthening the backend. He was the kind of dev who quietly shipped features that just worked no fuss, no fluff, just clean execution.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href="https://github.com/Shrey327" rel="noopener noreferrer"&gt;Shreyansh&lt;/a&gt;&lt;/strong&gt; – The wild card turned MVP. He went all-in on the ML side &lt;strong&gt;training our custom models&lt;/strong&gt;, fine-tuning performance, and basically doing the kind of wizardry that made the AI magic real. He joined in a little later but made a massive impact in no time&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🌱 Birth of 3RVision
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;The idea for &lt;strong&gt;3RVision&lt;/strong&gt; came from a simple realization: there’s a ton of waste out there, and people often don’t know what to do with it. With increasing environmental concerns, we wanted to create a practical solution that helps people identify whether an item can be &lt;strong&gt;reused, recycled, or resold&lt;/strong&gt; right from their phone.&lt;/p&gt;

&lt;p&gt;It was clear that the challenge of waste management wasn’t just about &lt;em&gt;knowing&lt;/em&gt; what could be recycled, but &lt;em&gt;how&lt;/em&gt; to make it easy for people to make informed, eco-friendly decisions. So, we decided to tackle this with AI, combining image recognition to offer suggestions for each item whether it was fit for recycling, resale, or reuse.&lt;/p&gt;

&lt;p&gt;There were debates along the way could we expand beyond just waste management? Should we focus on something more abstract? But in the end, we locked onto this problem because it felt practical, relevant, and scalable. Plus, we could really make a difference with it. And let’s be real, who doesn’t love building something that can make a positive impact?&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🛠️ Game Time – The Hack Begins
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;We kicked off the hack with all the enthusiasm in the world. The morning went pretty smooth frontend coming together, models being trained, vibes were solid.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Khushi&lt;/strong&gt; and &lt;strong&gt;Shreyansh&lt;/strong&gt; were deep into training the core ML models, I was locking in the frontend, and &lt;strong&gt;Arpit was busy setting up the Chrome extension&lt;/strong&gt; getting those early pieces in place so we could integrate it all later.&lt;/p&gt;

&lt;p&gt;Around evening, the organizers hit us with a surprise &lt;strong&gt;jamming session&lt;/strong&gt; and not gonna lie, it was &lt;em&gt;exactly&lt;/em&gt; what we needed. 10/10 would jam again.&lt;/p&gt;

&lt;p&gt;Now, back to the grind. Post-jam, things got a bit… spicy.&lt;/p&gt;

&lt;p&gt;There were some weird bugs in the extension it wasn’t properly classifying items into &lt;strong&gt;degradable vs. biodegradable&lt;/strong&gt;. &lt;strong&gt;Me and Arpit&lt;/strong&gt; tag-teamed it and squashed that mess before dinner. Clean fix, good vibes&lt;/p&gt;

&lt;p&gt;But the real pain hit when &lt;strong&gt;Shreyansh’s model training crashed&lt;/strong&gt; network issues mid-process. Bro left it training during the jam, and came back to find everything wiped. Khushi, on the other side, had another model training simultaneously, so Shreyansh had to restart from scratch. 🫠&lt;/p&gt;

&lt;p&gt;By the time dinner rolled around, everything seemed set up frontend ✅, extension ✅, ML ✅.&lt;/p&gt;

&lt;p&gt;But the &lt;strong&gt;backend?&lt;/strong&gt; Not even close.&lt;br&gt;
We didn’t know it yet, but we were about to enter chaos mode.&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%2Fd33qfops3rgi8ffwm9xh.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%2Fd33qfops3rgi8ffwm9xh.jpg" alt="Fixing Chrome Extension" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  ⚡ Clutch Moments – Bounce Back Energy
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Okay, so here’s where things went full &lt;strong&gt;&lt;em&gt;“will they make it or not”&lt;/em&gt;&lt;/strong&gt; mode.&lt;/p&gt;

&lt;p&gt;By 11 PM, the backend was the only thing standing between us and a fully functional system. And it wasn’t just one integration we had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect the &lt;strong&gt;frontend to the ML model&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Connect the &lt;strong&gt;frontend to the backend&lt;/strong&gt; (built in Go)&lt;/li&gt;
&lt;li&gt;And finally, connect the &lt;strong&gt;backend to the ML model (running on a Flask server)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Basically, a full-on relay race with two different servers and a lot of bugs in between.&lt;/p&gt;

&lt;p&gt;Me and Arpit sat down thinking, &lt;em&gt;“Okay, couple hours max.”&lt;/em&gt;&lt;br&gt;
Reality check: it took us &lt;strong&gt;till 6 AM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There were CORS issues, data not syncing right, weird behavior when Go tried to communicate with Flask, and a bunch of edge cases that kept popping out of nowhere. But with each successful response, we got closer.&lt;/p&gt;

&lt;p&gt;Finally, when we saw the frontend fully talk to Go, which then made a clean call to Flask and got back a prediction it was like…&lt;br&gt;
&lt;strong&gt;inner peace unlocked.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Watching the entire pipeline run smoothly after 6 hours of chaos?&lt;br&gt;
Yeah, that moment hit different.&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%2F5a5g8596eep5lwmsd81h.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%2F5a5g8596eep5lwmsd81h.jpg" alt="Late night chaos" width="800" height="1035"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🎤 The Pitch – It’s Show Time
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;We were riding on zero sleep and infinite adrenaline.&lt;br&gt;
The product? Ready.&lt;br&gt;
The presentation? Not so much.&lt;/p&gt;

&lt;p&gt;We hadn’t prepped any fancy slides or rehearsed a pitch just raw conviction and a working build. Some features didn’t make it in due to time (rip to our extra functionalities).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First round&lt;/strong&gt;, we were called to one of the labs.&lt;br&gt;
&lt;strong&gt;Khushi and Arpit&lt;/strong&gt; stepped up, laptops in hand.&lt;br&gt;
Khushi took the lead and bro, she &lt;strong&gt;snapped&lt;/strong&gt;.&lt;br&gt;
Clear, confident, and straight to the point. It wasn’t just a walkthrough—it was a proper storytelling session of what 3RVision stood for and what it could do.&lt;/p&gt;

&lt;p&gt;We walked the judges through the features—&lt;strong&gt;ML predictions&lt;/strong&gt;, &lt;strong&gt;waste classification&lt;/strong&gt;, the &lt;strong&gt;Chrome extension&lt;/strong&gt; in action, &lt;strong&gt;clean UI&lt;/strong&gt;, and &lt;strong&gt;smooth backend integration&lt;/strong&gt;.&lt;br&gt;
And the &lt;strong&gt;live demo?&lt;/strong&gt; Bro… it actually worked. Like, everything just clicked at the right time. No bugs, no lags. It felt good- &lt;em&gt;really&lt;/em&gt; good.&lt;/p&gt;

&lt;p&gt;After wrapping up, we headed to the auditorium for another jamming session.&lt;br&gt;
It was just what we needed. Chill vibes, music, and a moment to breathe after the storm.&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%2Fsw4yvu6ai86ygwusowri.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%2Fsw4yvu6ai86ygwusowri.jpg" alt="first_round_pitch" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🏁 The Final Lap – Top 6, Showdown &amp;amp; The Win
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;We were just vibing in the auditorium post-demo, soaking it all in, when Khushi got a call.&lt;br&gt;
We were selected in the &lt;strong&gt;Top 6&lt;/strong&gt;.&lt;br&gt;
For a second, we just froze. Like &lt;strong&gt;wait, us?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The final round was calling, and we had to show up again. No room for error now.&lt;br&gt;
We prepped in silence, running through key points, refining our story this time, it wasn’t just about features. It was about &lt;strong&gt;vision&lt;/strong&gt;, &lt;strong&gt;scalability&lt;/strong&gt;, and the &lt;strong&gt;“why us?”&lt;/strong&gt; of it all.&lt;/p&gt;

&lt;p&gt;Back to the same lab, but this time with &lt;strong&gt;more judges&lt;/strong&gt;, and a slightly heavier vibe. The pressure was real.&lt;br&gt;
Still, Khushi stepped up again and &lt;em&gt;&lt;strong&gt;killed it&lt;/strong&gt;&lt;/em&gt;. This round dove deeper into the &lt;strong&gt;business model&lt;/strong&gt;, &lt;strong&gt;revenue possibilities&lt;/strong&gt;, and &lt;strong&gt;future roadmap&lt;/strong&gt;. We highlighted the packed set of features and why this wasn't just another hackathon build, it had potential. Real, tangible potential.&lt;/p&gt;

&lt;p&gt;There were some solid cross-questions from the panel. We held our ground and answered them all.&lt;br&gt;
No blank stares. No panic. Just a team that knew what it built.&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%2F0koqhiwcyr9e4wfb2y4p.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%2F0koqhiwcyr9e4wfb2y4p.jpg" alt="second_round_pitch" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After about 15 minutes, we were told to head for Lunch.&lt;br&gt;
And on the way, something wild happened &lt;br&gt;
The &lt;strong&gt;Professor of ISE&lt;/strong&gt; came up to us and asked for a &lt;strong&gt;selfie&lt;/strong&gt;.&lt;br&gt;
We were like, &lt;em&gt;“Uhhh… what just happened?”&lt;/em&gt;&lt;br&gt;
That moment? Kinda confirmed what we were all feeling inside we might just take this.&lt;/p&gt;

&lt;p&gt;Fast forward to &lt;strong&gt;auditorium&lt;/strong&gt;, final results.&lt;/p&gt;

&lt;p&gt;Started with the usual boring speeches 😒 (no offense, Chief Guest), but all we could hear was our own heartbeat.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third place... not us.&lt;/strong&gt;&lt;br&gt;
Bittersweet. Still hoping.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Second place... also not us.&lt;/strong&gt;&lt;br&gt;
Now we’re fully in “it’s either us or nothing” mode.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And then...&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🥇 “First Position… Team Quaternary!”
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;Bruhhh,we &lt;strong&gt;exploded&lt;/strong&gt;. Screams. Hugs. Pure disbelief.&lt;br&gt;
Out of &lt;strong&gt;21&lt;/strong&gt; solid teams, &lt;strong&gt;we came out on top&lt;/strong&gt;.&lt;br&gt;
The sleepless night, the endless debugging, the full-stack hustle, the caffeine-fueled grind—&lt;strong&gt;all of it was worth it.&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%2Fg6x9ndoefofndxifmmv3.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%2Fg6x9ndoefofndxifmmv3.jpg" alt="final_glory" width="800" height="533"&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%2Fwpy023qiyjbprmuzyiga.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%2Fwpy023qiyjbprmuzyiga.jpg" alt="certificates" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  🚀 That’s a Wrap
&lt;/h2&gt;
&lt;/blockquote&gt;

&lt;p&gt;From day-one brainstorming to that final pitch, the whole journey was wild in the best way.&lt;br&gt;
We built, broke, fixed, and figured things out as a team, learning more in 24 hours than we probably did in weeks.&lt;/p&gt;

&lt;p&gt;What started as just an idea turned into something we’re genuinely proud of.&lt;br&gt;
Walking away with the win? Yeah, that felt amazing.&lt;br&gt;
But honestly, it’s the grind, the laughs, the chaos, and the crew that made it all worth it.&lt;/p&gt;

&lt;p&gt;Thanks for sticking around and reading our story! 🙌&lt;br&gt;
This wasn’t meant to be a technical deep-dive but more of a raw, real peek into our hackathon journey.&lt;/p&gt;

&lt;p&gt;Here’s to more late-night builds, good vibes, and taking ideas beyond the hackathon.&lt;/p&gt;

&lt;p&gt;Till the next all-nighter. 👋&lt;/p&gt;

</description>
      <category>hackathon</category>
      <category>devjournal</category>
      <category>machinelearning</category>
      <category>showdev</category>
    </item>
    <item>
      <title>DNS Explained: From Basics to Building My Own DNS Server</title>
      <dc:creator>Naman Raj</dc:creator>
      <pubDate>Sat, 29 Mar 2025 19:01:39 +0000</pubDate>
      <link>https://dev.to/denyme24/dns-explained-from-basics-to-building-my-own-dns-server-25o6</link>
      <guid>https://dev.to/denyme24/dns-explained-from-basics-to-building-my-own-dns-server-25o6</guid>
      <description>&lt;p&gt;Hey everyone! 👋 I'm &lt;strong&gt;Naman&lt;/strong&gt;, a full-stack developer passionate about networking and system design. Recently, I built my own &lt;strong&gt;DNS server using Go&lt;/strong&gt;, and in this blog, I'll walk you through the fundamentals of DNS and how did i create my own DNS server from scratch. Let's dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  🌍 What is DNS and Why is it Important?
&lt;/h2&gt;

&lt;p&gt;DNS (Domain Name System) is like the &lt;strong&gt;phonebook of the internet&lt;/strong&gt;. It translates human-friendly domain names &lt;strong&gt;(like google.com)&lt;/strong&gt; into machine-readable IP addresses &lt;strong&gt;(like 142.250.182.206)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Imagine if every time you wanted to visit a website, you had to type in a long, numeric IP address. DNS eliminates that hassle by handling the lookup for you!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Example:&lt;/strong&gt;&lt;br&gt;
When you type &lt;strong&gt;namanraj.tech&lt;/strong&gt; in your browser:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your computer asks a DNS server: "&lt;em&gt;What is the IP address of&lt;/em&gt; &lt;em&gt;namanraj.tech&lt;/em&gt;?"&lt;/li&gt;
&lt;li&gt;The DNS server replies with the correct IP (e.g., &lt;strong&gt;&lt;em&gt;76.76.21.93&lt;/em&gt;&lt;/strong&gt;).&lt;/li&gt;
&lt;li&gt;Your browser connects to that IP and loads the website.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🔄 How DNS Works (Step-by-Step Resolution Process)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Stub Resolver Initiates the Query&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;strong&gt;Stub Resolver&lt;/strong&gt; is a small built-in DNS client in your &lt;strong&gt;operating system&lt;/strong&gt; (Windows, Linux, macOS).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Its job is to check &lt;strong&gt;if the domain’s IP is already cached&lt;/strong&gt; in your local system.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the IP is not found, the stub resolver forwards the request to a Recursive DNS Resolver for further lookup&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. Recursive Resolver Handles the Query&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Recursive Resolver&lt;/strong&gt; is a DNS server that helps find the IP address on behalf of your device.&lt;/li&gt;
&lt;li&gt;Common recursive resolvers include:

&lt;ul&gt;
&lt;li&gt;Google Public DNS &lt;strong&gt;(&lt;em&gt;8.8.8.8&lt;/em&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Cloudflare DNS &lt;strong&gt;(&lt;em&gt;1.1.1.1&lt;/em&gt;)&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Your &lt;strong&gt;ISP’s DNS resolver&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Query to the Root DNS Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The recursive resolver first asks a &lt;strong&gt;Root Name Server&lt;/strong&gt; for guidance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What is a Root Server?&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Root servers are the &lt;strong&gt;highest level in the DNS hierarchy&lt;/strong&gt;, acting as the entry point for all DNS lookups.&lt;/li&gt;
&lt;li&gt;There are &lt;strong&gt;13 root servers worldwide&lt;/strong&gt;, and they know where to find the &lt;strong&gt;TLD (Top-Level Domain)&lt;/strong&gt; servers for different domains.&lt;/li&gt;
&lt;li&gt;Since the root server does not store individual website IPs, it replies:&lt;/li&gt;
&lt;li&gt; "&lt;em&gt;I don’t have the IP for namanraj.tech, but ask a &lt;strong&gt;.tech&lt;/strong&gt; TLD server&lt;/em&gt;" &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a dig command that queries the root DNS server (&lt;strong&gt;a.root-servers.net&lt;/strong&gt;) for the &lt;strong&gt;nameservers&lt;/strong&gt; (NS records) responsible for the com top-level domain (TLD). It essentially asks the root server which DNS servers handle requests for domain names ending in .com.&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%2Fuz4kav7586utig52qw22.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%2Fuz4kav7586utig52qw22.jpg" alt=" " width="800" height="628"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It returns the list of nameservers that are &lt;strong&gt;authoritative&lt;/strong&gt; for the com TLD. These are the servers that handle DNS queries for domains ending in &lt;strong&gt;.com&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Query to the TLD Name Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The recursive resolver now asks the &lt;strong&gt;TLD Name Server&lt;/strong&gt; for &lt;strong&gt;.tech&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;What is a &lt;strong&gt;TLD Server&lt;/strong&gt;?

&lt;ul&gt;
&lt;li&gt;A Top-Level Domain (TLD) Name Server manages all domains with a specific extension, like: &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;.com&lt;/em&gt;&lt;/strong&gt; domains → Managed by .com TLD servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;.org&lt;/em&gt;&lt;/strong&gt; domains → Managed by .org TLD servers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;.tech&lt;/em&gt;&lt;/strong&gt; domains → Managed by .tech TLD servers&lt;/li&gt;
&lt;li&gt;Since the TLD server still does not store the IP of &lt;strong&gt;&lt;em&gt;namanraj.tech&lt;/em&gt;&lt;/strong&gt;, it responds:

&lt;ul&gt;
&lt;li&gt;"I don’t have the IP, but ask the &lt;strong&gt;Authoritative Name Server&lt;/strong&gt; for &lt;em&gt;namanraj.tech&lt;/em&gt;"&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dig command queries the DNS server at &lt;strong&gt;a.gtld-servers.net&lt;/strong&gt; for the nameservers (NS records) responsible for the domain &lt;em&gt;namanraj.tech&lt;/em&gt;. It essentially asks the a.gtld-servers.net server which DNS servers handle requests for &lt;em&gt;namanraj.tech&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%2F6l7rzbb7jbb2cn2r5mgs.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%2F6l7rzbb7jbb2cn2r5mgs.jpg" alt=" " width="800" height="521"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will list the nameservers that are authoritative for the &lt;em&gt;namanraj.tech&lt;/em&gt; domain. These are the servers that handle DNS queries for &lt;em&gt;namanraj.tech&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AUTHORITY SECTION&lt;/strong&gt;: If the DNS server does not have the direct answer, it may provide a list of nameservers that are closer to the authoritative source&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Query to the Authoritative Name Server&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The recursive resolver now queries the Authoritative Name Server.&lt;/li&gt;
&lt;li&gt;What is an Authoritative Name Server?

&lt;ul&gt;
&lt;li&gt;It is the final authority for a domain.&lt;/li&gt;
&lt;li&gt;It stores and manages DNS records (A, CNAME, MX, etc.) for a domain (we will come to this later).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The authoritative name server for &lt;em&gt;namanraj.tech&lt;/em&gt; (e.g., &lt;strong&gt;&lt;em&gt;ns1.vercel-dns.com&lt;/em&gt;&lt;/strong&gt;) replies:

&lt;ul&gt;
&lt;li&gt;"&lt;em&gt;The IP address for&lt;/em&gt; &lt;em&gt;namanraj.tech&lt;/em&gt; is &lt;strong&gt;&lt;em&gt;76.76.21.93&lt;/em&gt;&lt;/strong&gt;."&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dig command queries the DNS system to find the nameservers responsible for the domain namanraj.tech. It asks which DNS servers handle requests for this domain.&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%2F43ddj0j1gzdm6or7z1lt.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%2F43ddj0j1gzdm6or7z1lt.jpg" alt=" " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It will give the list of nameservers that are associated with &lt;em&gt;namanraj.tech&lt;/em&gt; domain that stores and manages DNS records. Here, they are: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;ns2.vercel-dns.com&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;ns1.vercel-dns.com&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Recursive Resolver Returns the IP&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;recursive resolver caches&lt;/strong&gt; the response for future use.&lt;/li&gt;
&lt;li&gt;It sends the final &lt;strong&gt;IP address&lt;/strong&gt; &lt;em&gt;(76.76.21.93)&lt;/em&gt; back to your device.&lt;/li&gt;
&lt;li&gt;Now that your device knows the correct IP, it sends an &lt;strong&gt;&lt;em&gt;HTTP request to 76.76.21.93.&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;web server&lt;/strong&gt; &lt;strong&gt;at that IP&lt;/strong&gt; responds, and &lt;strong&gt;&lt;em&gt;namanraj.tech&lt;/em&gt;&lt;/strong&gt; loads in your browser!&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  🛠️ Visualizing DNS: The Complete Resolution Flow (Step-by-Step)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Let's say you visit namanraj.tech , here's what happens :&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%2F0fsi57u4sm1cqoldn5fg.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%2F0fsi57u4sm1cqoldn5fg.jpg" alt=" " width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  🗂️ Types of DNS Records
&lt;/h2&gt;

&lt;p&gt;DNS records define how a &lt;strong&gt;domain functions&lt;/strong&gt; by mapping domain names to &lt;strong&gt;IP addresses&lt;/strong&gt;, &lt;strong&gt;handling emails&lt;/strong&gt;, and &lt;strong&gt;managing domain settings&lt;/strong&gt;. Here are the most important ones:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.  A Record (Address Record) 🏠&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maps a domain to an IPv4 address, allowing browsers to locate websites.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;namanraj.tech → 192.0.2.1&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: When a user types &lt;em&gt;namanraj.tech&lt;/em&gt;, the A record helps find the &lt;strong&gt;web server’s IP&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This dig command &lt;strong&gt;&lt;em&gt;dig namanraj.tech A&lt;/em&gt;&lt;/strong&gt; queries the DNS system to find the A (Address) record for the domain &lt;em&gt;namanraj.tech&lt;/em&gt;. It asks for the IP address associated with this domain.&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%2Fw5qvtj0mwva4x9c86fy3.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%2Fw5qvtj0mwva4x9c86fy3.jpg" alt=" " width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. AAAA Record (IPv6 Address Record) 🌍&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Similar to an A record but stores an &lt;strong&gt;IPv6 address&lt;/strong&gt; instead of IPv4.&lt;/li&gt;
&lt;li&gt;An &lt;strong&gt;AAAA (Quad-A)&lt;/strong&gt; record is similar to an A record but maps a domain to an &lt;strong&gt;IPv6 address&lt;/strong&gt;. IPv6 uses a &lt;strong&gt;128-bit address format&lt;/strong&gt;, supporting &lt;strong&gt;trillions of IP addresses&lt;/strong&gt; solving the issue of IPv4 exhaustion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;google.com → 2607:f8b0:4005:80b::200e&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Websites that support IPv6 use AAAA records for better future-proofing.&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%2Fl96y0ml2oirjloap5daj.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%2Fl96y0ml2oirjloap5daj.jpg" alt=" " width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. CNAME (Canonical Name Record) 🔗&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates an alias by pointing one domain to another domain instead of an IP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;&lt;a href="http://www.namanraj.tech" rel="noopener noreferrer"&gt;www.namanraj.tech&lt;/a&gt; → namanraj.tech&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Ensures &lt;strong&gt;&lt;em&gt;&lt;a href="http://www.namanraj.tech" rel="noopener noreferrer"&gt;www.namanraj.tech&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; always resolves to the same IP as &lt;strong&gt;&lt;em&gt;namanraj.tech&lt;/em&gt;&lt;/strong&gt; without maintaining separate A records.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. MX Record (Mail Exchange Record) 📧&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defines the mail server responsible for handling &lt;strong&gt;email delivery&lt;/strong&gt; for a domain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;namanraj.tech → mail.google.com (Priority: 10)&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: When someone emails &lt;em&gt;&lt;a href="mailto:you@namanraj.tech"&gt;you@namanraj.tech&lt;/a&gt;&lt;/em&gt;, the MX record ensures it reaches the correct mail server.&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%2Fxfxp5bsrt4f5iqsjx1pc.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%2Fxfxp5bsrt4f5iqsjx1pc.jpg" alt=" " width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The answer section lists one &lt;strong&gt;MX record for google.com&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Priority: 10&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mail server: &lt;em&gt;smtp.google.com&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In MX records, the priority value determines the &lt;strong&gt;order of mail servers to be used&lt;/strong&gt;. &lt;strong&gt;Lower values have higher priority&lt;/strong&gt;. If the primary server is unavailable, the next server with a higher priority value is used.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. NS Record (Name Server Record) 📡&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Specifies the &lt;strong&gt;authoritative name servers&lt;/strong&gt; that manage a domain’s DNS settings.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;em&gt;namanraj.tech → &lt;strong&gt;ns1.vercel-dns.com&lt;/strong&gt;, &lt;strong&gt;ns2.vercel-dns.com&lt;/strong&gt;&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: These servers handle all DNS queries for namanraj.tech.&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%2Fp2ykd3v5r4hpt2s7jxvn.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%2Fp2ykd3v5r4hpt2s7jxvn.jpg" alt=" " width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. TXT Record (Text Record) 🔒&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;TXT (Text) Record&lt;/strong&gt; is a DNS record that allows a domain owner to store text-based information in the DNS. Unlike A or MX records, which are used for website and email routing, TXT records do not affect how a domain functions directly. Instead, they are mostly used for &lt;strong&gt;verification, security, and authentication purposes&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores arbitrary text, often used for security &amp;amp; authentication (SPF, DKIM, verification).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: "&lt;strong&gt;&lt;em&gt;v=spf1 include:_spf.google.com ~all&lt;/em&gt;&lt;/strong&gt;" (SPF record for email validation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: Prevents email spoofing and domain ownership verification.&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%2Faptp1x45gv974gi6z01e.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%2Faptp1x45gv974gi6z01e.jpg" alt=" " width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The answer section lists multiple &lt;strong&gt;TXT records for google.com&lt;/strong&gt;, including:

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;google-site-verification values&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;docusign values&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;onetrust-domain-verification value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;globalsign-smime-dv value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;v=spf1 include:_spf.google.com ~all (SPF record for email validation)&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;facebook-domain-verification value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;MS (Microsoft) verification value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;apple-domain-verification value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;em&gt;cisco-ci-domain-verification value&lt;/em&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;7. SOA Record (Start of Authority) 📜&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The SOA (Start of Authority) record is a special DNS record that provides important &lt;strong&gt;administrative details&lt;/strong&gt; about a domain’s DNS settings. It acts as the &lt;em&gt;"boss"&lt;/em&gt; of the DNS zone and ensures everything is properly managed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contains administrative information about a domain, including the primary DNS server and refresh intervals&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Example&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;Primary NS: ns1.vercel-dns.com, Admin: hostmaster.nsone.net&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use Case&lt;/strong&gt;: &lt;em&gt;Ensures DNS records are properly synchronized across name servers&lt;/em&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%2Fsrkpa6rupfa45sibr6xc.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%2Fsrkpa6rupfa45sibr6xc.jpg" alt=" " width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  ⚡ Building My Own DNS Server in Go: A Journey Through Networking Fundamentals 🚀
&lt;/h2&gt;

&lt;p&gt;To truly understand how DNS works, I decided to build my own &lt;strong&gt;custom DNS server in Go&lt;/strong&gt;—and in this Part, I’ll walk you through how I did it, the challenges I faced, and what I learned along the way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;&lt;a href="https://github.com/Denyme24/my-dns-server" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt; (Feel free to star ⭐ or contribute!)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Build a DNS Server?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How DNS queries/responses work (UDP vs. TCP)&lt;/li&gt;
&lt;li&gt;Authoritative vs. Recursive DNS (mine is authoritative)&lt;/li&gt;
&lt;li&gt;Real-world use cases (local development, ad-blocking, privacy)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;This project was less about replacing Cloudflare and more about learning by doing.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up the Project&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Installing Go &amp;amp; Fiber - &lt;strong&gt;&lt;em&gt;&lt;a href="https://go.dev/dl/" rel="noopener noreferrer"&gt;Click Here&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Dependencies Used (&lt;strong&gt;&lt;em&gt;github.com/miekg/dns&lt;/em&gt;&lt;/strong&gt; for DNS handling, Fiber for API).&lt;/li&gt;
&lt;li&gt;In-memory storage (Simple &lt;strong&gt;&lt;em&gt;map[string]string&lt;/em&gt;&lt;/strong&gt; for records)&lt;/li&gt;
&lt;li&gt;Project Structure Overview :
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/my-dns-server
│── main.go        # Entry point of the DNS server
│── go.mod         # Dependency management
│── go.sum         # Dependency checksum file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Building the DNS Server: Core Implementation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Initializing the DNS Server (&lt;em&gt;startDNSServer&lt;/em&gt;)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before handling requests, we need to launch our DNS server. Here's the foundation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func startDNSServer() {
    // Set up DNS server
    server := &amp;amp;dns.Server{
        Addr: "0.0.0.0:9090", // Bind to all interfaces
        Net:  "udp",
    }

    // Handle DNS requests
    dns.HandleFunc(".", handleDNSRequest)

    // Start server
    log.Printf("Starting DNS server on port 9090...")
    err := server.ListenAndServe()
    if err != nil {
        log.Fatalf("Failed to start DNS server: %v", err)
    } else {
        log.Printf("DNS server is running on port 9090")
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Decisions:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;UDP Protocol&lt;/strong&gt;: Chosen for performance (DNS mostly uses UDP for quick queries)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port 9090&lt;/strong&gt;: Avoids needing root privileges (vs standard port 53)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UDPSize&lt;/strong&gt;: Supports large DNS responses (like DNSSEC)&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%2Fbtouccdxk2zpv07tizhe.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%2Fbtouccdxk2zpv07tizhe.jpg" alt=" " width="800" height="311"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Concurrent Operation with Fiber&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Since DNS runs continuously, we launch it in a &lt;strong&gt;goroutine&lt;/strong&gt; alongside our Fiber API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func main() {
    go startDNSServer() // Run DNS in background
    startWebServer()    // Start Fiber API
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why This Matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The DNS server keeps running while:

&lt;ul&gt;
&lt;li&gt;The Fiber API manages records&lt;/li&gt;
&lt;li&gt;You query DNS from &lt;strong&gt;multiple clients simultaneously&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. DNS Server (UDP Port 9090)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The core DNS functionality listens for &lt;strong&gt;UDP requests&lt;/strong&gt; and responds with stored records.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;func handleDNSRequest(w dns.ResponseWriter, r *dns.Msg) {
    m := new(dns.Msg)
    m.SetReply(r)
    m.Authoritative = true // Mark this server as authoritative
    found := false

    for _, q := range r.Question {
        log.Printf("Query: %s (%s)", q.Name, dns.TypeToString[q.Qtype])
        if q.Qtype == dns.TypeA {
            if ip, exists := dnsRecords[q.Name]; exists {
                rr, _ := dns.NewRR(fmt.Sprintf("%s A %s", q.Name, ip))
                m.Answer = append(m.Answer, rr)
                found = true
            }
        }
    }

    if !found {
        m.Rcode = dns.RcodeNameError // NXDOMAIN
    }

    w.WriteMsg(m)
}
&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%2Fzobdlc7h60gwix8z98ar.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%2Fzobdlc7h60gwix8z98ar.jpg" alt=" " width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Using UDP and not TCP?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;DNS primarily uses UDP (User Datagram Protocol) instead of TCP for 3 key reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UDP is &lt;strong&gt;connectionless&lt;/strong&gt; (no handshake like TCP).&lt;/li&gt;
&lt;li&gt;A DNS query + response fits in &lt;strong&gt;1 UDP packet&lt;/strong&gt; (usually &amp;lt; 512 bytes).&lt;/li&gt;
&lt;li&gt;UDP’s lightweight nature lets them &lt;strong&gt;serve more queries with fewer resources&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. Web Management API (Fiber, Port 3000)&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;A simple &lt;strong&gt;REST API&lt;/strong&gt; to add DNS records dynamically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    // Web interface to manage DNS records
    app.Get("/records", func(c *fiber.Ctx) error {
        return c.JSON(dnsRecords)
    })

    app.Post("/records", func(c *fiber.Ctx) error {
        type Record struct {
            Domain string `json:"domain"`
            IP     string `json:"ip"`
        }

        var record Record
        if err := c.BodyParser(&amp;amp;record); err != nil {
            return c.Status(400).SendString("Bad request")
        }

        // Ensure domain ends with dot (DNS standard)
        if record.Domain[len(record.Domain)-1] != '.' {
            record.Domain += "."
        }

        dnsRecords[record.Domain] = record.IP
        return c.SendString("Record added successfully")
    })
&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%2F3e18iqmj28nhgaladaut.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%2F3e18iqmj28nhgaladaut.jpg" alt=" " width="800" height="73"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Challenges &amp;amp; Lessons Learned
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. DNS Queries Are UDP-Based (Mostly)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;By default, DNS uses UDP (faster for small requests).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;2. The Importance of the Trailing Dot&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;"example.com"&lt;/em&gt;&lt;/strong&gt; ≠ &lt;strong&gt;&lt;em&gt;"example.com."&lt;/em&gt;&lt;/strong&gt; (fully qualified domain name).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. Port Binding Permissions&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ports below &lt;strong&gt;1024&lt;/strong&gt; require admin rights (&lt;strong&gt;&lt;em&gt;sudo&lt;/em&gt;&lt;/strong&gt; on Linux).&lt;/li&gt;
&lt;li&gt;Used &lt;strong&gt;port 9090&lt;/strong&gt; for testing to avoid permission issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. No Recursion (Yet!)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;My server is &lt;strong&gt;authoritative-only&lt;/strong&gt; (only answers for records it knows).&lt;/li&gt;
&lt;li&gt;A recursive resolver would query other DNS servers if it doesn’t have an answer.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Practical Uses for a Custom DNS Server
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Local Development&lt;/li&gt;
&lt;li&gt;Ad-Blocking&lt;/li&gt;
&lt;li&gt;Network Privacy&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Try It Yourself!
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Clone the repo:&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;git clone https://github.com/Denyme24/my-dns-server.git
cd my-dns-server
go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Start querying!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;Building a DNS server was a &lt;strong&gt;fantastic learning experience&lt;/strong&gt;—I now appreciate how much work goes into something we use daily without thinking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What would you add to this project?&lt;/strong&gt; Let me know in the comments! 🚀&lt;/p&gt;

&lt;p&gt;(P.S. If you found this useful, &lt;strong&gt;consider starring the repo!&lt;/strong&gt; ⭐)&lt;/p&gt;

</description>
      <category>dns</category>
      <category>go</category>
      <category>networking</category>
      <category>selfhosted</category>
    </item>
  </channel>
</rss>
