<?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: BhargavMantha</title>
    <description>The latest articles on DEV Community by BhargavMantha (@bhargavmantha).</description>
    <link>https://dev.to/bhargavmantha</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%2F514798%2F888416a3-db40-4a97-9cfc-8e895bb1b79d.png</url>
      <title>DEV Community: BhargavMantha</title>
      <link>https://dev.to/bhargavmantha</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bhargavmantha"/>
    <language>en</language>
    <item>
      <title>The Secret to Perfect Load Balancing: How I Combined Two ISPs with pfSense and ₹0 in New Hardware</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Mon, 02 Feb 2026 01:37:44 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/the-secret-to-perfect-load-balancing-how-i-combined-two-isps-with-pfsense-and-0-in-new-hardware-50bb</link>
      <guid>https://dev.to/bhargavmantha/the-secret-to-perfect-load-balancing-how-i-combined-two-isps-with-pfsense-and-0-in-new-hardware-50bb</guid>
      <description>&lt;p&gt;Last week, my internet went down during a critical work call. &lt;em&gt;Again.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I have two ISP connections at home—&lt;strong&gt;Mach 1 (500 Mbps)&lt;/strong&gt; and &lt;strong&gt;Airtel (200 Mbps)&lt;/strong&gt;—but I was only using one at a time. When Mach 1 dropped, I'd manually switch cables to Airtel like a caveman. There had to be a better way.&lt;/p&gt;

&lt;p&gt;48 hours later, I had both connections load-balanced through a single router, with automatic failover. Total cost? &lt;strong&gt;₹0&lt;/strong&gt;—I used hardware I already had.&lt;/p&gt;




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

&lt;p&gt;India's internet infrastructure is... unpredictable. My Mach 1 fiber is blazing fast but drops once a week. Airtel is rock-solid but slower. I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Automatic failover&lt;/strong&gt; — If one ISP dies, traffic shifts instantly&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Load balancing&lt;/strong&gt; — Use both connections simultaneously&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Single network&lt;/strong&gt; — One SSID, one LAN, no manual switching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consumer "dual-WAN" routers exist, but they're either expensive (₹15,000+) or garbage. I needed something proper.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hardware I Had
&lt;/h2&gt;

&lt;p&gt;Here's the thing about homelabs—you accumulate hardware. In my drawer:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Device&lt;/th&gt;
&lt;th&gt;Specs&lt;/th&gt;
&lt;th&gt;Original Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell Latitude E7250&lt;/td&gt;
&lt;td&gt;i5-5300U, 8GB RAM, 256GB SSD&lt;/td&gt;
&lt;td&gt;Old work laptop&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TP-Link SG105E&lt;/td&gt;
&lt;td&gt;5-port Gigabit Managed Switch&lt;/td&gt;
&lt;td&gt;Gathering dust&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tenda AC10&lt;/td&gt;
&lt;td&gt;Dual-band router&lt;/td&gt;
&lt;td&gt;Mach 1's router&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Airtel GPON&lt;/td&gt;
&lt;td&gt;Fiber ONT&lt;/td&gt;
&lt;td&gt;Airtel's modem&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Total new purchases: ₹0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Dell laptop has only one Ethernet port. Most guides would say "buy a USB NIC" or "get a proper router." I said: &lt;em&gt;"VLANs."&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Architecture
&lt;/h2&gt;

&lt;p&gt;The magic is using &lt;strong&gt;802.1Q VLANs&lt;/strong&gt; to carry multiple networks over a single cable. The TP-Link SG105E—a ₹2,000 switch—supports this.&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%2Fx2risxjygn1kx1ymbrqg.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%2Fx2risxjygn1kx1ymbrqg.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One cable to the Dell laptop carries three isolated networks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;VLAN 10&lt;/strong&gt;: Mach 1 WAN (PPPoE)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VLAN 20&lt;/strong&gt;: Airtel WAN (DHCP)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VLAN 30&lt;/strong&gt;: My home LAN&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1: The Switch Configuration
&lt;/h2&gt;

&lt;p&gt;The SG105E has a web interface for VLAN configuration. Here's what I set up:&lt;/p&gt;

&lt;h3&gt;
  
  
  802.1Q VLAN Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;VLAN ID&lt;/th&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Tagged Ports&lt;/th&gt;
&lt;th&gt;Untagged Ports&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;WAN1&lt;/td&gt;
&lt;td&gt;Port 1&lt;/td&gt;
&lt;td&gt;Port 2&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;WAN2&lt;/td&gt;
&lt;td&gt;Port 1&lt;/td&gt;
&lt;td&gt;Port 3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;LAN&lt;/td&gt;
&lt;td&gt;Port 1&lt;/td&gt;
&lt;td&gt;Port 4, 5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  PVID Settings
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;PVID&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;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Trunk (all VLANs tagged)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Mach 1 ingress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Airtel ingress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;LAN devices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;LAN devices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This took 10 minutes. The switch does the packet tagging; pfSense sees three separate interfaces over one wire.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Installing pfSense
&lt;/h2&gt;

&lt;p&gt;I grabbed the &lt;strong&gt;Netgate Installer&lt;/strong&gt; (pfSense's official installer) and wrote it to a USB drive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;gunzip&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; netgate-installer-amd64.iso.gz | &lt;span class="nb"&gt;sudo dd &lt;/span&gt;&lt;span class="nv"&gt;of&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/dev/sdf &lt;span class="nv"&gt;bs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4M &lt;span class="nv"&gt;status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;progress
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One snag: the Dell E7250 has an Intel WiFi card that crashes FreeBSD's kernel. The fix? &lt;strong&gt;Disable WiFi in BIOS.&lt;/strong&gt; This is a router—it doesn't need WiFi.&lt;/p&gt;

&lt;p&gt;The installation was straightforward until interface assignment. When pfSense asked about VLANs, I created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Parent interface: em0
VLAN 10 → em0.10 (WAN)
VLAN 20 → em0.20 (WAN2)  
VLAN 30 → em0.30 (LAN)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Configuring Dual-WAN
&lt;/h2&gt;

&lt;p&gt;With pfSense installed and interfaces assigned, configuration happens in the web GUI.&lt;/p&gt;

&lt;h3&gt;
  
  
  WAN Interface (Mach 1)
&lt;/h3&gt;

&lt;p&gt;Mach 1 uses PPPoE authentication:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IPv4 Type&lt;/td&gt;
&lt;td&gt;PPPoE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Username&lt;/td&gt;
&lt;td&gt;&lt;code&gt;your_username&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;your_password&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  WAN2 Interface (Airtel)
&lt;/h3&gt;

&lt;p&gt;Airtel is simpler—just DHCP:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Setting&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;IPv4 Type&lt;/td&gt;
&lt;td&gt;DHCP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  The Gateway Group
&lt;/h3&gt;

&lt;p&gt;This is where the magic happens. Under &lt;strong&gt;System → Routing → Gateway Groups&lt;/strong&gt;, I created:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Gateway&lt;/th&gt;
&lt;th&gt;Tier&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;WAN_DHCP (Mach 1)&lt;/td&gt;
&lt;td&gt;Tier 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;WAN2_DHCP (Airtel)&lt;/td&gt;
&lt;td&gt;Tier 1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Both at Tier 1 = Load Balancing.&lt;/strong&gt; Traffic distributes across both ISPs.&lt;/p&gt;

&lt;p&gt;If I wanted pure failover (Airtel only when Mach 1 dies), I'd set Airtel to Tier 2.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying to LAN Traffic
&lt;/h3&gt;

&lt;p&gt;Finally, edit the default LAN firewall rule and set the &lt;strong&gt;Gateway&lt;/strong&gt; to &lt;code&gt;LoadBalance_WAN&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Result
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Status → Gateways

| Gateway    | IP          | RTT     | Loss | Status |
|------------|-------------|---------|------|--------|
| WAN_DHCP   | 192.168.0.1 | 0.843ms | 0.0% | Online |
| WAN2_DHCP  | 192.168.1.1 | 0.638ms | 0.0% | Online |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both gateways online. Both ISPs active. One network.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson 1: VLANs are underrated.&lt;/strong&gt;&lt;br&gt;
A single Ethernet port + a cheap managed switch = infinite virtual interfaces. Most "you need more NICs" advice is wrong.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2: Load balancing ≠ Bonding.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This confused me initially:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;th&gt;Speed Test Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Load Balancing&lt;/td&gt;
&lt;td&gt;Each connection uses one WAN&lt;/td&gt;
&lt;td&gt;~500 Mbps OR ~200 Mbps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;True Bonding&lt;/td&gt;
&lt;td&gt;Single connection uses both&lt;/td&gt;
&lt;td&gt;~700 Mbps combined&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;pfSense does &lt;strong&gt;load balancing&lt;/strong&gt;—great for multiple devices/streams, but a single speed test won't show 700 Mbps. True bonding requires MPTCP and a cloud aggregation server (Speedify, OpenMPTCProuter).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lesson 3: Gateway monitoring is critical.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Set the &lt;strong&gt;Trigger Level&lt;/strong&gt; to "Packet Loss or High Latency." Without this, pfSense won't detect a degraded-but-not-dead connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Financials
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Item&lt;/th&gt;
&lt;th&gt;Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Dell E7250&lt;/td&gt;
&lt;td&gt;₹0 (already owned)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TP-Link SG105E&lt;/td&gt;
&lt;td&gt;₹0 (already owned)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;USB Drive&lt;/td&gt;
&lt;td&gt;₹0 (already owned)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;₹0&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Monthly benefit:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No more dropped calls during ISP outages&lt;/li&gt;
&lt;li&gt;Both connections utilized instead of one sitting idle&lt;/li&gt;
&lt;li&gt;Professional-grade routing without professional-grade prices&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Current Setup
&lt;/h2&gt;

&lt;p&gt;The Dell E7250 now runs 24/7 as my home router. Power draw is ~15W idle. It handles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dual-WAN load balancing + failover&lt;/li&gt;
&lt;li&gt;NAT for 30+ devices&lt;/li&gt;
&lt;li&gt;Firewall rules&lt;/li&gt;
&lt;li&gt;Future: VPN server, traffic shaping, pfBlockerNG&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The laptop screen stays closed. It's headless, fanless (at idle), and silent.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: Complete Port Map
&lt;/h2&gt;

&lt;h2&gt;
  
  
  FINAL SETUP
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnc4v1ga4bbb50v5qvf5z.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%2Fnc4v1ga4bbb50v5qvf5z.png" alt=" " width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;Have you set up dual-WAN at home? Did you go the pfSense/OPNsense route, or use a commercial solution? What's your ISP redundancy story?&lt;/p&gt;

&lt;p&gt;Drop a comment below—I'd love to hear how others are solving the "Indian ISP lottery" problem. 👇&lt;/p&gt;

</description>
      <category>networking</category>
      <category>homelab</category>
      <category>pfsense</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>I Exposed My $70 Kubernetes Cluster to the Internet (Without Opening a Single Port)</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Sun, 11 Jan 2026 01:28:12 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/i-exposed-my-70-kubernetes-cluster-to-the-internet-without-opening-a-single-port-nkk</link>
      <guid>https://dev.to/bhargavmantha/i-exposed-my-70-kubernetes-cluster-to-the-internet-without-opening-a-single-port-nkk</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/bhargavmantha/how-i-quit-the-cloud-and-built-a-3-node-gpu-k8s-cluster-for-6000-gca"&gt;previous&lt;/a&gt; post, I talked about how I built a 3-node Kubernetes cluster for ₹6,000 ($70) to host my AI models and home lab. It worked great, but there was one ugly problem: Networking.&lt;/p&gt;

&lt;p&gt;The Problem&lt;br&gt;
Accessing my services meant one of two things:&lt;/p&gt;

&lt;p&gt;Locally: Typing &lt;code&gt;http://192.168.0.173:30300&lt;/code&gt; for Grafana. Ugly, but works.&lt;br&gt;
Remotely: Setting up WireGuard or Tailscale. Secure, but I can't ask my friends to install a VPN client just to see a dashboard or chat with my LLM.&lt;br&gt;
I considered opening ports on my router (Port Forwarding) pointing to an Nginx Proxy Manager. &lt;strong&gt;Bad idea&lt;/strong&gt;. Opening ports to the internet is like leaving your front door unlocked because you lost your keys. I didn't want to wake up to a crypto-miner running on my GTX 1070 Ti.&lt;/p&gt;

&lt;p&gt;I needed a solution that was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Secure&lt;/strong&gt; (No open ports).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; (I'm still on a budget).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public&lt;/strong&gt; (Accessible via subdomain.domain.com).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter &lt;strong&gt;Cloudflare Tunnel&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I Did
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;The Zero Trust Switch&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
I realized Cloudflare provides a "Zero Trust" plan that is completely free for up to 50 users. This includes Tunnels. A tunnel creates an outbound-only connection from your cluster to Cloudflare's edge network. Traffic flows out to Cloudflare, then back in to your services. No inbound ports needed on my router.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;DNS Migration&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
My domain (bhargavmantha.dev) was hosting a static site on Netlify. To use Tunnels effectively, I needed Cloudflare to manage the DNS.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Old way: Squarespace Registrar -&amp;gt; Netlify DNS.&lt;/li&gt;
&lt;li&gt;New way: Squarespace Registrar -&amp;gt; Cloudflare DNS -&amp;gt; Netlify (for main site) + Tunnel (for subdomains).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I migrated my nameservers to Cloudflare, which automatically imported my existing records. Zero downtime.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deploying cloudflared to K8s&lt;/strong&gt;
Instead of running a binary on my variety of nodes (Pop!_OS desktop, Ubuntu laptop), I deployed the tunnel connector as a native Kubernetes deployment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I created a simple manifest &lt;br&gt;
cloudflared.yaml&lt;br&gt;
 that takes a token (from the Cloudflare dashboard) and runs 2 replicas for high availability.&lt;br&gt;
&lt;/p&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;apps/v1&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;Deployment&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;cloudflared&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;replicas&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;template&lt;/span&gt;&lt;span class="pi"&gt;:&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;containers&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;cloudflared&lt;/span&gt;
        &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cloudflare/cloudflared:latest&lt;/span&gt;
        &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;tunnel&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--no-autoupdate&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;run&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--token&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;$(TUNNEL_TOKEN)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, my cluster dials out to Cloudflare automatically. If I reboot a node, K8s reschedules the pod, and the tunnel reconnects instantly.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Goodbye NodePorts, Hello Subdomains
This is the magic part. In the Cloudflare Dashboard (Network &amp;gt; Tunnels), I simply mapped public hostnames to my internal ClusterIPs (or NodePorts).&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;grafana.bhargavmantha.dev&lt;/code&gt; -&amp;gt; &lt;code&gt;http://192.168.0.173:30300&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ollama.bhargavmantha.dev&lt;/code&gt; -&amp;gt; &lt;code&gt;http://192.168.0.173:31434&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;uptime.bhargavmantha.dev&lt;/code&gt; -&amp;gt; &lt;code&gt;http://192.168.0.173:30001&lt;/code&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%2Fpon3xxphjxjgbsi4myzq.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%2Fpon3xxphjxjgbsi4myzq.png" alt="No CLI magic needed—just pointing domains to local IPs" width="800" height="332"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SSL certificates are handled automatically by Cloudflare at the edge. I get the padlock icon without setting up cert-manager or LetsEncrypt inside my cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lesson 1: Ingress Controllers are Overkill for Homelabs&lt;/em&gt;&lt;/strong&gt;. I spent days trying to get Traefik or Nginx Ingress to play nice with MetalLB on a bare-metal cluster. Cloudflare Tunnel bypassed that entire layer. I don't need an Ingress Controller; I just need a connector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Lesson 2: Security can be convenient&lt;/em&gt;&lt;/strong&gt;. By putting everything behind Cloudflare, I can also add an "Access Application" layer later—meaning I can put grafana.bhargavmantha.dev behind a Google/GitHub logic screen, adding 2FA to apps that don't even support it natively.&lt;/p&gt;

&lt;p&gt;Current State&lt;br&gt;
Now my cheap K8s cluster feels like a production cloud environment.&lt;/p&gt;

&lt;p&gt;Publicly Accessible: Grafana, Uptime Kuma, and Open WebUI.&lt;br&gt;
Cost: still $0 (Cloudflare Free Tier).&lt;br&gt;
Security: 0 Open Ports.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>How I Quit the Cloud and Built a 3-Node GPU K8s Cluster for ₹6,000</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Wed, 24 Dec 2025 03:03:05 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/how-i-quit-the-cloud-and-built-a-3-node-gpu-k8s-cluster-for-6000-gca</link>
      <guid>https://dev.to/bhargavmantha/how-i-quit-the-cloud-and-built-a-3-node-gpu-k8s-cluster-for-6000-gca</guid>
      <description>&lt;p&gt;Last month, I realized I was paying &lt;strong&gt;₹2,500/month&lt;/strong&gt; across various cloud services—photo backups, file sync, a VPN, and a small VM for side projects. &lt;/p&gt;

&lt;p&gt;When I added up the annual cost and compared it to the price of a used ThinkPad on OLX, the math was obvious. Three weeks later, I had a 3-node Kubernetes cluster running in my living room.&lt;/p&gt;

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

&lt;p&gt;I wanted the real Kubernetes experience—not Minikube, not Docker Compose pretending to be orchestration. I needed something that could:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;strong&gt;GPU workloads&lt;/strong&gt; for local LLMs (Ollama).&lt;/li&gt;
&lt;li&gt;Host my &lt;strong&gt;photo library&lt;/strong&gt; (Immich).&lt;/li&gt;
&lt;li&gt;Sync files and run &lt;strong&gt;Home Assistant&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every "budget homelab" guide I found assumed you'd drop ₹50,000+ on a NUC cluster. I had a laptop, an old desktop with a gaming GPU, and about &lt;strong&gt;₹15,000&lt;/strong&gt; to spend.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Did
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. The Hardware Hustle
&lt;/h3&gt;

&lt;p&gt;I started with what I had. My desktop had a &lt;strong&gt;GTX 1070 Ti&lt;/strong&gt; collecting dust. My old &lt;strong&gt;ThinkPad E14&lt;/strong&gt; (16GB RAM, i5) was sitting in a drawer. The only purchase was a &lt;strong&gt;₹6,000 used laptop&lt;/strong&gt; with a &lt;strong&gt;GTX 1650 Ti&lt;/strong&gt; from a local seller—decent specs, terrible screen, perfect for a headless node. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Total hardware cost: ₹6,000.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. K3s over K8s
&lt;/h3&gt;

&lt;p&gt;Full Kubernetes would have eaten my RAM alive. &lt;strong&gt;K3s&lt;/strong&gt; gave me 90% of the functionality at ~20% of the resource overhead. The control plane runs on the ThinkPad, which also hosts lightweight services: Grafana, Prometheus, Home Assistant, and PostgreSQL. Installation was literally one command per node.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The GPU Scheduling "Hack"
&lt;/h3&gt;

&lt;p&gt;I wanted to run Ollama on the 1070 Ti, but I also wanted to use that desktop for work/gaming. The solution? A simple script that joins/leaves the K3s cluster on demand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# athena.sh&lt;/span&gt;
./athena.sh gpu claim   &lt;span class="c"&gt;# Joins cluster, pulls workloads&lt;/span&gt;
./athena.sh gpu release &lt;span class="c"&gt;# Drains node, returns GPU to OS&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The cluster adapts, pods reschedule, and life continues.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. NodePort Everything
&lt;/h3&gt;

&lt;p&gt;I wasted two days trying to get proper pod networking across nodes before accepting reality: my home network and cheap router weren't going to play nice with complex Ingress. I switched to &lt;strong&gt;NodePort services&lt;/strong&gt; with a 30xxx range:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus:&lt;/strong&gt; &lt;code&gt;:30900&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana:&lt;/strong&gt; &lt;code&gt;:30300&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ollama:&lt;/strong&gt; &lt;code&gt;:31434&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Not elegant? Maybe. Reliable? &lt;strong&gt;Absolutely.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lesson 1: Scope is everything.&lt;/strong&gt;&lt;br&gt;
My first attempt tried to replicate a production setup (Traefik, cert-manager, etc.). It was fragile. The working version is simpler: &lt;code&gt;hostPath&lt;/code&gt; volumes instead of a storage provisioner, and NodePorts instead of ingress. "Production-grade" and "Actually usable at home" are different goals.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Lesson 2: GPUs in K8s are easier than they look.&lt;/strong&gt;&lt;br&gt;
Install the NVIDIA device plugin, add a &lt;code&gt;RuntimeClass&lt;/code&gt;, and set resource limits. The hard part isn't the tech; it's the workflow of sharing hardware between "Work" and "Cluster."&lt;/p&gt;

&lt;h2&gt;
  
  
  Current State
&lt;/h2&gt;

&lt;p&gt;The cluster now runs &lt;strong&gt;25+ services&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AI:&lt;/strong&gt; Ollama + Open WebUI&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Media/Files:&lt;/strong&gt; Immich, Nextcloud, Jellyfin&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Home:&lt;/strong&gt; Home Assistant&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Prometheus, Grafana, Postgres&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Financials:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Power Draw:&lt;/strong&gt; ~80W idle / 200W load.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monthly Electricity:&lt;/strong&gt; ~₹400.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Annual Savings:&lt;/strong&gt; ~₹25,000 (and I own my data).&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  Discussion
&lt;/h3&gt;

&lt;p&gt;Have you built a homelab on a budget? What tradeoffs did you make between "doing it right" and "getting it done"? Let me know in the comments!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>homelab</category>
      <category>selfhosted</category>
      <category>devops</category>
    </item>
    <item>
      <title>CQRS</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Thu, 04 Apr 2024 18:08:30 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/cqrs-3e1d</link>
      <guid>https://dev.to/bhargavmantha/cqrs-3e1d</guid>
      <description>&lt;h2&gt;
  
  
  CQRS Like You Were a 5-Year-Old
&lt;/h2&gt;

&lt;p&gt;Imagine you have a &lt;strong&gt;&lt;em&gt;toy box&lt;/em&gt;&lt;/strong&gt;. When you want to play with your &lt;strong&gt;&lt;em&gt;toys&lt;/em&gt;&lt;/strong&gt;, you ask your mom to open the &lt;strong&gt;&lt;em&gt;toy box&lt;/em&gt;&lt;/strong&gt; and give you the toys you want. That's like asking a &lt;strong&gt;question&lt;/strong&gt;, or in computer terms, a &lt;strong&gt;&lt;em&gt;query&lt;/em&gt;&lt;/strong&gt;. You're not changing anything, &lt;strong&gt;&lt;em&gt;just looking at what toys you have&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Now, imagine after playing, you decide to put some of your &lt;code&gt;toys&lt;/code&gt; back in a different way. Maybe you're putting them in order of &lt;code&gt;size&lt;/code&gt; or &lt;code&gt;grouping&lt;/code&gt; them by type. This time, you're not just looking; you're &lt;strong&gt;&lt;em&gt;changing how things are arranged&lt;/em&gt;&lt;/strong&gt;. In computer terms, that's like a &lt;strong&gt;&lt;em&gt;command&lt;/em&gt;&lt;/strong&gt; because you're telling the toy box (or a computer system) to &lt;strong&gt;&lt;em&gt;change something&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;CQRS&lt;/em&gt;&lt;/strong&gt; stands for &lt;strong&gt;&lt;em&gt;Command Query Responsibility Segregation&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It's a fancy way of saying that when we use computers or apps, there are two main things we can do: &lt;strong&gt;&lt;em&gt;look at stuff&lt;/em&gt;&lt;/strong&gt; (&lt;code&gt;queries&lt;/code&gt;) and &lt;strong&gt;&lt;em&gt;change stuff&lt;/em&gt;&lt;/strong&gt; (&lt;code&gt;commands&lt;/code&gt;). CQRS is like having two separate &lt;code&gt;toy boxes&lt;/code&gt;: one for looking at toys and another for deciding how to organize them. This way, it's easier and faster to either find your &lt;code&gt;toys&lt;/code&gt; or &lt;strong&gt;&lt;em&gt;organize&lt;/em&gt;&lt;/strong&gt; them, because you're not mixing up looking and changing toys in the same &lt;strong&gt;&lt;em&gt;toy box&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Now Comes the Fun Part&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;You have 2 different toy boxes: 1 to find and 1 to arrange. But if I change the arrangement of the toys in 1 box, won't the same need to be made in the other box as well, in order to maintain consistency? In the current case, the changes of arrangement are not going to reflect in the other toy box, right?&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Absolutely Right!!!&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you change how your toys are arranged in one &lt;code&gt;toy box&lt;/code&gt;, you'd want the other toy box to show those changes too, so everything matches up. In our CQRS world, this means when you do something in the &lt;strong&gt;&lt;em&gt;change stuff&lt;/em&gt;&lt;/strong&gt; box, someone (usually a smart part of the computer or app) has to make sure the &lt;strong&gt;&lt;em&gt;look at stuff&lt;/em&gt;&lt;/strong&gt; box knows about those changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Let's Continue With Our Toy Analogy&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Imagine you have a magic notebook that keeps track of what you do in the &lt;strong&gt;&lt;em&gt;change stuff&lt;/em&gt;&lt;/strong&gt; box. Every time you move a &lt;code&gt;toy&lt;/code&gt;, you write it down in the &lt;strong&gt;&lt;em&gt;notebook&lt;/em&gt;&lt;/strong&gt;. Then, there's a friendly &lt;strong&gt;&lt;em&gt;elf&lt;/em&gt;&lt;/strong&gt; who takes a look at your notebook while you're asleep, and he makes sure everything you did in the &lt;strong&gt;&lt;em&gt;change stuff&lt;/em&gt;&lt;/strong&gt; box is also done in the &lt;strong&gt;&lt;em&gt;look at stuff&lt;/em&gt;&lt;/strong&gt; box. When you wake up and decide to play again, both your boxes are up to date, and everything matches.&lt;/p&gt;

&lt;p&gt;In computer systems, this &lt;strong&gt;&lt;em&gt;magic notebook&lt;/em&gt;&lt;/strong&gt; can be something like a list of all the changes you've made (we call these &lt;strong&gt;&lt;em&gt;events&lt;/em&gt;&lt;/strong&gt;), and the &lt;strong&gt;&lt;em&gt;friendly elf&lt;/em&gt;&lt;/strong&gt; can be a piece of software that makes sure both sides (the command side and the query side) are kept in sync. This way, whether you're looking at your data or changing it, you always see the latest version.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Let's Explain How CQRS Might Work Using Node.js, MongoDB, and Any Additional Pieces Necessary to Make It Clear&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you're building a simple app where you can add &lt;code&gt;toys&lt;/code&gt; to a collection and view your collection. In a CQRS approach, you would have two main parts: &lt;code&gt;one for adding&lt;/code&gt; or changing toy information (&lt;code&gt;the command side&lt;/code&gt;) and &lt;code&gt;another for viewing&lt;/code&gt; your toy collection (&lt;code&gt;the query side&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  1. MongoDB Setup
&lt;/h3&gt;

&lt;p&gt;You'll use MongoDB to store your toys. But, following the CQRS principle, you might have two collections:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Toys_Commands:&lt;/em&gt;&lt;/strong&gt; This is where you add or update toy information. Think of it as the "change stuff" box.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;em&gt;Toys_Queries:&lt;/em&gt;&lt;/strong&gt; This collection is optimized for reading and displaying toy data. It's your "look at stuff" box.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Node.js Application
&lt;/h3&gt;

&lt;p&gt;Your Node.js app will have different routes or endpoints for commands (adding/updating toys) and queries (getting toy information).&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Command Side&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;When you want to add a new toy or update an existing one, you'll use a command endpoint like POST &lt;code&gt;/toys&lt;/code&gt; or &lt;strong&gt;&lt;em&gt;PUT&lt;/em&gt;&lt;/strong&gt; &lt;code&gt;/toys/:toyId&lt;/code&gt;. This part of the app will interact with the Toys_Commands collection. When a toy is added or updated, the app will also send a message (let's think of it as our "magic notebook" entry) to a messaging system (like RabbitMQ or Kafka), indicating what change was made.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Query Side&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The query part of the app has endpoints like &lt;code&gt;GET /toys&lt;/code&gt; to view the toy collection. It reads from the &lt;strong&gt;&lt;em&gt;Toys_Queries&lt;/em&gt;&lt;/strong&gt; collection, which is optimized for fast, read-only access.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Keeping Things in Sync&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Now, we need our &lt;code&gt;friendly elf&lt;/code&gt; to keep the command and query sides in sync. This can be a separate service or part of your app that listens for messages about changes made on the command side (our &lt;code&gt;magic notebook&lt;/code&gt;). When it receives a message about a change, it updates the &lt;strong&gt;&lt;em&gt;Toys_Queries&lt;/em&gt;&lt;/strong&gt; collection accordingly. This way, the next time you go to view your &lt;code&gt;toys&lt;/code&gt;, the collection is up-to-date with all the latest changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Additional Pieces&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Messaging System (RabbitMQ/Kafka):&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;This acts as the intermediary that passes messages from the command side to the service responsible for updating the query side. It ensures that all changes are queued and processed reliably.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Separate Services/Workers for Syncing:&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;These are specialized parts of your app (or separate apps) that listen to the messaging system and update the query side based on the command side's changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Example Flow&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Add a Toy (Command):&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;You send a request to &lt;code&gt;POST /toys&lt;/code&gt; to add a new toy. The toy is added to &lt;strong&gt;&lt;em&gt;Toys_Commands&lt;/em&gt;&lt;/strong&gt;, and a message is sent to RabbitMQ noting the addition.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Syncing:&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A separate service listens to RabbitMQ, receives the message about the new toy, and adds this toy to &lt;strong&gt;&lt;em&gt;Toys_Queries&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;View Toys (Query):&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;When you request &lt;code&gt;GET /toys&lt;/code&gt;, the app reads from &lt;strong&gt;&lt;em&gt;Toys_Queries&lt;/em&gt;&lt;/strong&gt;, showing you the latest collection, including the toy you just added.&lt;/p&gt;

&lt;p&gt;This setup, with Node.js, MongoDB, and a messaging system, helps keep your app organized according to CQRS principles, separating the concerns of modifying data and reading it, while also ensuring consistency between those views.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Reflect-metadata in JavaScript</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Mon, 11 Dec 2023 13:01:20 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/reflect-metadata-in-javascript-1jgp</link>
      <guid>https://dev.to/bhargavmantha/reflect-metadata-in-javascript-1jgp</guid>
      <description>&lt;p&gt;&lt;strong&gt;&lt;em&gt;Reflection&lt;/em&gt;&lt;/strong&gt; in JavaScript refers to the ability to inspect and modify a program's structure and behaviour at runtime. This concept is not unique to JavaScript but is a common feature in many programming languages. In JavaScript, reflection is typically achieved through certain objects and methods that allow you to work with the properties and methods of other objects dynamically. Here are some key aspects of reflection in JavaScript:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;typeof&lt;/code&gt; Operator: This operator is used to determine the type of a variable. It's a basic form of reflection, as it allows you to inspect the type of an object at runtime.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;instanceof&lt;/code&gt; Operator: This is used to check whether an object is an instance of a specific class or a prototype.&lt;/p&gt;

&lt;p&gt;Object Introspection: JavaScript provides various ways to inspect an object, such as:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Object.keys(obj)&lt;/code&gt;: Returns an array of a given object's property names.&lt;br&gt;
&lt;code&gt;Object.getOwnPropertyNames(obj)&lt;/code&gt;: Similar to Object.keys but includes non-enumerable properties.&lt;br&gt;
&lt;code&gt;Object.getPrototypeOf(obj)&lt;/code&gt;: Retrieves the prototype of an object.&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Property Access and Modification&lt;/em&gt;&lt;/strong&gt;: JavaScript allows for dynamic property access and modification. You can use bracket notation (e.g., obj["property"]) to access properties dynamically based on their names, which can be computed at runtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Function Reflection&lt;/em&gt;&lt;/strong&gt;: Functions in JavaScript are objects, and you can inspect their properties like any other object. Additionally, you can use methods like Function.prototype.apply() and Function.prototype.call() to invoke functions with a specified this context and arguments.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Proxy Objects&lt;/em&gt;&lt;/strong&gt;: Introduced in ES6, proxies allow you to create a wrapper for a target object, where you can intercept and redefine fundamental operations for that object, such as property lookup, assignment, enumeration, function invocation, etc.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Dynamic Code Execution&lt;/em&gt;&lt;/strong&gt;: Functions like eval() allow for the execution of code represented as a string. This is a powerful but potentially risky tool, as it can run arbitrary code.&lt;/p&gt;

&lt;p&gt;Reflection in JavaScript can be powerful for building flexible and dynamic systems, but it should be used judiciously. Overuse of reflection can lead to code that is hard to understand, maintain, and debug. Additionally, it can introduce security vulnerabilities if not handled carefully, especially in the context of dynamic code execution.&lt;/p&gt;

&lt;p&gt;The term "Reflect metadata" in JavaScript is typically associated with the Reflect API and decorators, which are a part of the JavaScript extensions proposed for future ECMAScript versions. These features are more commonly used in TypeScript, a superset of JavaScript, but they're also relevant in the context of modern JavaScript development. Here's a breakdown of these concepts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reflect API&lt;/strong&gt;: This is a built-in object that provides methods for interceptable JavaScript operations. The methods are similar to those of proxy handlers but are static. For example, &lt;code&gt;Reflect.get()&lt;/code&gt; is used to retrieve a property from an object, mirroring the functionality of a proxy's get handler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Metadata Reflection API&lt;/strong&gt;: This is a proposed extension to the Reflect API that allows for the annotation and retrieval of metadata on classes and class members. It's inspired by similar features in languages like C# and Java. The Metadata Reflection API is not part of standard JavaScript but can be used with a library like &lt;code&gt;reflect-metadata&lt;/code&gt; in a TypeScript or modern JavaScript environment.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Decorators&lt;/strong&gt;: These are a proposed feature for JavaScript (and already available in TypeScript) that allows you to annotate and modify classes and properties at design time. Decorators use the Reflect API to attach metadata to class definitions. For instance, you can define a decorator to mark a class method as deprecated, and then use reflection to check if a method is deprecated before invoking it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Relationship Between Reflect and Metadata&lt;/strong&gt;: The Reflect API, combined with the Metadata Reflection API, enables a more powerful form of reflection in JavaScript. It allows developers not only to inspect and modify the structure and behavior of programs but also to attach and retrieve metadata. This metadata can be used for a variety of purposes, such as defining serialization rules, specifying dependency injection parameters, or applying custom behavior to class members.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Usage in Frameworks&lt;/strong&gt;: Many modern JavaScript frameworks and libraries, especially those that use TypeScript, leverage these concepts for advanced features like dependency injection, ORM (Object-Relational Mapping), and custom decorators for various purposes (like in Angular or NestJS).&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In summary, the Reflect metadata in JavaScript refers to the use of the Reflect API and decorators to annotate and modify classes and class members, and to attach and retrieve metadata. While this functionality is not yet part of the ECMAScript standard, it's available through libraries and is widely used in TypeScript and modern JavaScript development.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>reflection</category>
    </item>
    <item>
      <title>Critical Rendering Path</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Thu, 20 Apr 2023 04:30:52 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/critical-rendering-path-44pj</link>
      <guid>https://dev.to/bhargavmantha/critical-rendering-path-44pj</guid>
      <description>&lt;p&gt;There are two important aspects to websites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Speed&lt;/li&gt;
&lt;li&gt;Look&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Even for seasoned web developers, increasing a website's page rendering speed is easier said than done. To get there, we must comprehend what is meant by the term "Critical Rendering Path" in order to understand how we may reduce it and increase the speed at which pages are rendered.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;What is the Critical Rendering Path?&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Engineers refer to the code and resources needed to create the initial view of a web page as the "critical rendering path." We label it as "critical" because doing so results in a "white screen of death" until all the necessary page elements render and are made visible. A webpage's "initial view" is also known as its "above the fold" information. A pretty complex series of interactions could make up the crucial rendering path. We can decide how to organise the parts in the best way if we understand how they affect one another.&lt;/p&gt;

&lt;p&gt;Why should I care?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Optimising the critical rendering path allows the browser to paint the page as quickly as possible: faster pages translate into higher engagement, more pages viewed, and improved conversion. &lt;/li&gt;
&lt;li&gt;To minimise the amount of time a visitor spends viewing a blank screen, we need to optimise which resources are loaded and in what order.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Main components of the Critical Rendering Path&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Network Overhead (Web Server Response Time)&lt;/em&gt;&lt;/strong&gt;: Keep in mind that cell networks ALWAYS have a longer "latency" (also known as round trip time) than other types of networks.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;HTML code:&lt;/em&gt;&lt;/strong&gt; Without the Document Object Model and completely downloaded HTML, we simply cannot render a web page. Outside Link. opens in a fresh tab. (DOM) tree that the browser is creating. Once those events take place, rendering can begin.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;CSS&lt;/em&gt;&lt;/strong&gt;: The DOM must also be created and applied to the CSSOM, the CSS language's own object model. The rendering process is halted by the CSSOM building phase.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;Webfonts&lt;/em&gt;&lt;/strong&gt;: These are fonts that must be downloaded in order to use them on a page.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;em&gt;JavaScript:&lt;/em&gt;&lt;/strong&gt; JavaScript is maybe the most disruptive component in the code because it can interact with both HTML and CSS. Browsers halt rendering while JavaScript is downloading and running unless additional measures are done.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;IMAGES EVEN THOUGH THEY ARE THE HEAVIEST PART OF THE WEBSITE, REQUIRE NO SPECIAL HANDING AS THEY ARE NOT PART OF THE DOM TREE.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Consider the following:&lt;br&gt;
&lt;strong&gt;&lt;em&gt;We are not taking into account the time to fetch resources from&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;cache or&lt;/li&gt;
&lt;li&gt;the network.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Consider the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width,initial-scale=1" /&amp;gt;
    &amp;lt;title&amp;gt;Critical Path: No Style&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;p&amp;gt;Hello &amp;lt;span&amp;gt;web performance&amp;lt;/span&amp;gt; students!&amp;lt;/p&amp;gt;
    &amp;lt;div&amp;gt;&amp;lt;img src="awesome-photo.jpg" /&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://googlesamples.github.io/web-fundamentals/fundamentals/performance/critical-rendering-path/basic_dom_nostyle.html"&gt;Check It Out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Without any CSS or JavaScript, we'll start with simple HTML code and a single image. Let's examine the generated resource waterfall by opening the Network timeline in Chrome DevTools:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdwclwgr602tcch4vgu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdwclwgr602tcch4vgu5.png" alt="WaterFall for the html" width="734" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The predicted download time for the HTML file was 340 milliseconds. &lt;/li&gt;
&lt;li&gt;Note that the solid portion of the blue line indicates how long it takes to complete the download after the first response bytes have been received, while the transparent half of the line shows how long the browser waits on the network before receiving any response bytes.&lt;/li&gt;
&lt;li&gt;Since the HTML download is so small (4K), retrieving the entire file only requires one roundtrip. &lt;/li&gt;
&lt;li&gt;The HTML content must therefore be fetched, which takes about 340ms, of which half is spent waiting on the network and the other waiting on the server answer.&lt;/li&gt;
&lt;li&gt;The browser parses the bytes, transforms them into tokens, and creates the DOM tree as soon as the HTML content is made available. &lt;/li&gt;
&lt;li&gt;The &lt;code&gt;DOMContentLoaded&lt;/code&gt; event's time is easily reported by DevTools at the bottom (595ms), which also matches to the blue vertical line. The time it takes the browser to assemble the DOM tree—in this case, just a few milliseconds—is shown by the space between the end of the HTML download and the blue vertical line (DOMContentLoaded).&lt;/li&gt;
&lt;li&gt;As described earlier, the "awesome photo" does not block the &lt;code&gt;domContentLoad&lt;/code&gt; event.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;When talking about CRP we only talk about the loading mechanisms of HTML markup, CSS, and Javascript.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nykeabw1yz11x78m3yy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2nykeabw1yz11x78m3yy.png" alt="Content Load Time" width="676" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Now Adding Javascript and CSS to the Mix
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html&amp;gt;
&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Critical Path: Measure Script&amp;lt;/title&amp;gt;
    &amp;lt;meta name="viewport" content="width=device-width,initial-scale=1" /&amp;gt;
    &amp;lt;link href="style.css" rel="stylesheet" /&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body onload="measureCRP()"&amp;gt;
    &amp;lt;p&amp;gt;Hello &amp;lt;span&amp;gt;web performance&amp;lt;/span&amp;gt; students!&amp;lt;/p&amp;gt;
    &amp;lt;div&amp;gt;&amp;lt;img src="awesome-photo.jpg" /&amp;gt;&amp;lt;/div&amp;gt;
    &amp;lt;script src="timing.js"&amp;gt;&amp;lt;/script&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://googlesamples.github.io/web-fundamentals/fundamentals/performance/critical-rendering-path/measure_crp_timing.html"&gt;Check it out&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uctkoeudn3go7b75k0t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7uctkoeudn3go7b75k0t.png" alt="Time span with CSS and Javascript" width="800" height="123"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;External CSS and JavaScript files increase our waterfall by two requests, which the browser sends out all at around the same time. However, observe that the interval between the domContentLoaded and onload events is now considerably shorter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is that?
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In contrast to our example of plain HTML, we also need to fetch and parse the CSS file in order to create the CSSOM, and the DOM and CSSOM are both required in order to create the render tree.&lt;/li&gt;
&lt;li&gt;The domContentLoaded event is delayed until the CSS file has downloaded and been parsed because the page also contains a parser-blocking JavaScript file. Because JavaScript may query the CSSOM, we must delay JavaScript execution until the CSS file has downloaded.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lets discuss what happens if an inline script is used in place of our external script in the next article.&lt;/p&gt;

</description>
      <category>browser</category>
      <category>rendering</category>
      <category>html</category>
    </item>
    <item>
      <title>SSH configuration on UBUNTU</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Thu, 01 Sep 2022 08:24:29 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/ssh-configuration-on-ubuntu-pbf</link>
      <guid>https://dev.to/bhargavmantha/ssh-configuration-on-ubuntu-pbf</guid>
      <description>&lt;p&gt;Prerequisites:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;&lt;em&gt;~/.ssh exists&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;access to root user&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Step 1 — Creating the Key Pair
&lt;/h3&gt;

&lt;p&gt;The first step is to create a key pair on the client machine (usually your computer):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-keygen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, recent versions of  &lt;code&gt;ssh-keygen&lt;/code&gt;  will create a 3072-bit RSA key pair, which is secure enough for most use cases (you may optionally pass in the  &lt;code&gt;-b 4096&lt;/code&gt;  flag to create a larger 4096-bit key).&lt;/p&gt;

&lt;p&gt;After entering the command, you should see the following output:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c4ourm89p1wyft3va0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7c4ourm89p1wyft3va0c.png" alt="Image description" width="654" height="86"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;when asked for a file name please enter a name of your choice followed by the enter key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25p557sv60bz7vofqe5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F25p557sv60bz7vofqe5d.png" alt="Image description" width="459" height="42"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press enter to save the key pair into the  &lt;code&gt;.ssh/&lt;/code&gt;  subdirectory in your home directory, or specify an alternate path.&lt;/p&gt;

&lt;p&gt;If you had previously generated an SSH key pair, you may see the following prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje92wi9c4donpg80w47v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje92wi9c4donpg80w47v.png" alt="Image description" width="288" height="67"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you choose to overwrite the key on disk, you will  &lt;strong&gt;not&lt;/strong&gt;  be able to authenticate using the previous key anymore. Be very careful when selecting yes, as this is a destructive process that cannot be reversed.&lt;/p&gt;

&lt;p&gt;You should then see the following prompt:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8stbmxtwzpgdhstb4vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk8stbmxtwzpgdhstb4vo.png" alt="Image description" width="691" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here can enter a secure passphrase, which is highly recommended. A passphrase adds a layer of security to prevent unauthorized users from logging in.&lt;/p&gt;

&lt;p&gt;You should then see the output similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fola0d6ekf3lmrkz00sss.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fola0d6ekf3lmrkz00sss.png" alt="Image description" width="673" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a public and private key that you can use to authenticate. The next step is to place the public key on your server so that you can use SSH-key-based authentication to log in.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2:
&lt;/h3&gt;

&lt;p&gt;Copying the Public Key The Ubuntu Server&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh-copy-id username@remote_host
&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;Output
The authenticity of host '103.0.113.132 (103.0.113.132)' can't be established.
ECDSA key fingerprint is fd:fd:d4:f9:77:fe:73:84:e1:55:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, the utility will scan your local account for the bhargavTest.pub key that we created earlier. When it finds the key, it will prompt you for the password of the remote user’s account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
bhargav@103.0.113.132's password:

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

&lt;/div&gt;



&lt;p&gt;Type in the password (your typing will not be displayed, for security purposes) and press ENTER. The utility will connect to the account on the remote host using the password you provided. It will then copy the contents of your ~/.ssh/id_rsa.pub key into a file in the remote account’s home ~/.ssh directory called authorized_keys.&lt;/p&gt;

&lt;p&gt;You should see the following output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'bhargav@103.0.113.132'"
and check to make sure that only the key(s) you wanted were added.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3 — Authenticating Your Ubuntu Server Using SSH Keys
&lt;/h3&gt;

&lt;p&gt;If you have completed one of the procedures above, you should be able to log into the remote host without providing the remote account’s password.&lt;/p&gt;

&lt;p&gt;The basic process is the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ssh username@remote_host
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in my case&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bhargav@103.0.113.132
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this is your first time connecting to this host (if you used the last method above), you may see something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output
The authenticity of host '103.0.113.132 (103.0.113.132)' can't be established.
ECDSA key fingerprint is rd:rd:r4:g7:77:fe:73:84:e1:65:00:ad:d6:6d:22:fe.
Are you sure you want to continue connecting (yes/no)? yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means that your local computer does not recognize the remote host. Type “yes” and then press ENTER to continue.&lt;/p&gt;

&lt;p&gt;If you did not supply a passphrase for your private key, you will be logged in immediately. If you supplied a passphrase for the private key when you created the key, you will be prompted to enter it now (note that your keystrokes will not display in the terminal session for security). After authenticating, a new shell session should open for you with the configured account on the Ubuntu server.&lt;/p&gt;

&lt;p&gt;If key-based authentication was successful, continue to learn how to further secure your system by disabling password authentication.&lt;/p&gt;

&lt;p&gt;At this point, if you can log in to the server without a password you have successfully configured ssh. &lt;/p&gt;

&lt;h3&gt;
  
  
  Step - 4
&lt;/h3&gt;

&lt;p&gt;confirm that your remote account has administrative privileges, log into your remote server with SSH keys, either as root or with an account with sudo privileges. Then, open up the SSH daemon’s configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/ssh/sshd_config
Inside the file, search for a directive called PasswordAuthentication. This line may be commented out with a # at the beginning of the line. Uncomment the line by removing the #, and set the value to no. This will disable your ability to log in via SSH using account passwords:

/etc/ssh/sshd_config
&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;PasswordAuthentication no
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save and close the file when you are finished by pressing CTRL+X, then Y to confirm saving the file, and finally ENTER to exit nano. To activate these changes, we need to restart the sshd service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl restart ssh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As a precaution, open up a new terminal window and test that the SSH service is functioning correctly before closing your current session:&lt;/p&gt;

&lt;p&gt;ssh username@remote_host&lt;br&gt;
Once you have verified your SSH service is functioning properly, you can safely close all current server sessions.&lt;/p&gt;

&lt;p&gt;The SSH daemon on your Ubuntu server now only responds to SSH-key-based authentication. Password-based logins have been disabled.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Design Pattern in TypeScript: Command Pattern</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Tue, 03 May 2022 09:24:30 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/design-pattern-in-typescript-command-pattern-3fg5</link>
      <guid>https://dev.to/bhargavmantha/design-pattern-in-typescript-command-pattern-3fg5</guid>
      <description>&lt;p&gt;## Pattern Sub-class&lt;/p&gt;

&lt;p&gt;Behavioral Design Patterns-&lt;br&gt;
&lt;strong&gt;&lt;em&gt;Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Defination
&lt;/h2&gt;

&lt;p&gt;Encapsulate a request as an object, thereby letting you parametrize clients with different requests, and support undoable operations.&lt;/p&gt;

&lt;p&gt;It turns a request into a stand-alone object that contains all the information about the request. This transformation lets you pass requests as a method arguments, delay or queue a request’s execution, and support undoable operations.&lt;/p&gt;
&lt;h3&gt;
  
  
  Psudo Names
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Actions, Transaction&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Why
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Consider you are building a text-editor app. You want to create a user interface toolkit that includes objects like buttons and menus that &lt;strong&gt;&lt;em&gt;carry out a request in response to user input&lt;/em&gt;&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Only applications that use the tool kit know what should be done on which object.&lt;/li&gt;
&lt;li&gt;As toolkit designers we have no way of knowing the receiver of the request or the operation that it will carry out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You have a generic Button class that can be used on the toolbar, as well as for generic buttons in various toolbars.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Though all these buttons look similar they perform different things.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;&lt;strong&gt;&lt;em&gt;THE SIMPLEST SOLUTION IS TO CREATE TONS OF SUB-CLASSES FOR EACH PLACE THE BOTTON IS USED. THE SUBCLASSES WOULD HAVE TO CONTAIN CODE TO BE EXECUTED ON A BUTTON CLICK&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69b3ybl1k2si5bnkz0vj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F69b3ybl1k2si5bnkz0vj.png" alt="sub classing"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  So what is wrong with this approach
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;You have an enormous number of subclasses&lt;/li&gt;
&lt;li&gt;code will break in a subclass in case of modification of base &lt;strong&gt;&lt;em&gt;Button&lt;/em&gt;&lt;/strong&gt; class&lt;/li&gt;
&lt;li&gt;some operation logic such as &lt;strong&gt;&lt;em&gt;copying/pasting&lt;/em&gt;&lt;/strong&gt; in this case of text editor would need to be invoked from multiple places:&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;User clicks the copy button on the toolbar or copies something using &lt;strong&gt;&lt;em&gt;CTRL+C&lt;/em&gt;&lt;/strong&gt; or &lt;strong&gt;&lt;em&gt;CMD+C&lt;/em&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivdd0u9kz0lg2uie7o4s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fivdd0u9kz0lg2uie7o4s.png" alt="Why not worth the hassle of subc-lassing"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Solution&lt;/em&gt;&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Separation of Concerns&lt;/li&gt;
&lt;li&gt;break the app into multiple layers&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;The command pattern intuitively says that send the request by extracting all the requirements for making the decision such as the object being called the name of the method and the list of arguments into a single command class with the single method that triggers the request.&lt;/p&gt;
&lt;h4&gt;
  
  
  The command architucture:
&lt;/h4&gt;

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

&lt;p&gt;The next step is to make your commands implement the same interface. Usually, it has just a single execution method that takes no parameters. This interface lets you use various commands with the same request sender, without coupling it to concrete classes of commands. As a bonus, now you can switch command objects linked to the sender, effectively changing the sender’s behavior at runtime.&lt;/p&gt;

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

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

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/typescript-jpvccs?embed=1&amp;amp;file=index.ts" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In case the above does not load :&lt;br&gt;
&lt;a href="https://stackblitz.com/edit/typescript-jpvccs?file=index.ts" rel="noopener noreferrer"&gt;Stack Blits editor url&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://typescript-jpvccs.stackblitz.io" rel="noopener noreferrer"&gt;Stack Blits application url&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>designpattern</category>
    </item>
    <item>
      <title>Linked List in TS</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Thu, 21 Apr 2022 09:11:26 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/linked-list-in-ts-g50</link>
      <guid>https://dev.to/bhargavmantha/linked-list-in-ts-g50</guid>
      <description>&lt;h2&gt;
  
  
  What are Linked Lists
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Linear dynamic Data Structure&lt;/li&gt;
&lt;li&gt;Expensive to maintain in comparison to arrays in terms of insertion and deletion&lt;/li&gt;
&lt;li&gt;comprises nodes&lt;/li&gt;
&lt;li&gt;last element points to null&lt;/li&gt;
&lt;li&gt;can grow and shrink on demand&lt;/li&gt;
&lt;li&gt;made of 2 items of data and reference to the next node &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;MAJOR DISADVANTAGE OF LINKED LIST&lt;/em&gt;&lt;/strong&gt; - O(n) for access to an element in the worst case.&lt;/p&gt;

&lt;p&gt;Basic Operations&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;traverse linked list&lt;/li&gt;
&lt;li&gt;push&lt;/li&gt;
&lt;li&gt;pop&lt;/li&gt;
&lt;li&gt;insertAtFirst&lt;/li&gt;
&lt;li&gt;deleteByIndex&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/typescript-tmtmgm?embed=1&amp;amp;file=linked-list/linked-list.class.ts&amp;amp;view=editor" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>datastructures</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Design Pattern in TypeScript: Strategy Pattern</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Wed, 13 Apr 2022 03:01:09 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/design-pattern-in-typescript-strategy-pattern-4i5d</link>
      <guid>https://dev.to/bhargavmantha/design-pattern-in-typescript-strategy-pattern-4i5d</guid>
      <description>&lt;h3&gt;
  
  
  Definition - Design Patterns
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;According to &lt;a href="https://en.wikipedia.org/wiki/Christopher_Alexander" rel="noopener noreferrer"&gt;Christopher Alexander&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;- &lt;em&gt;Each Pattern describes a problem that occurs over and over again in our environments, and then describes the core solution to that problem, in such a way that you can use this solution as a million times over without doing it the same way twice&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The only &lt;em&gt;difference&lt;/em&gt; between the patterns described by Christopher Alexander and the patterns in the case of computer language is that he expresses solutions in terms of &lt;em&gt;&lt;strong&gt;Walls and doors&lt;/strong&gt;&lt;/em&gt; Whereas we express them in terms of &lt;em&gt;&lt;strong&gt;Objects and Interfaces&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A pattern has 4 essential elements:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Pattern Name&lt;/li&gt;
&lt;li&gt;The problem&lt;/li&gt;
&lt;li&gt;The Solution&lt;/li&gt;
&lt;li&gt;The Consequence&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;What Design Patterns are not:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;designs that are encoded or added into the classes and reused as is like Trees, Stacks ...&lt;/li&gt;
&lt;li&gt;Nor are they complex,domain-specific designs for an entire applications or subsystems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;WHAT DESIGN PATTERNS DO SOLVE ON THE OTHER HAND ARE COMMUNICATION BETWEEN OBJECTS AND CLASSES THAT ARE CUSTOMIZED TO SOLVE A GENERAL DESIGN PROBLEM IN A PARTICULAR CONTEXT&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It names, abstracts, and identifies the key aspects of a common design structure that makes it useful for creating a reusable object-oriented design&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The first design pattern we are going to discuss is the &lt;strong&gt;&lt;em&gt;&lt;a href="https://en.wikipedia.org/wiki/Strategy_pattern" rel="noopener noreferrer"&gt;strategy Pattern&lt;/a&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Defination - STRATEGY
&lt;/h4&gt;

&lt;p&gt;Define a family of algorithms, encapsulate each one and make them interchangeable. Strategy lets the algorithm vary independently from the client that uses it.&lt;/p&gt;

&lt;p&gt;THE STRATEGY PATTERN COMES UNDER THE CLASS OF BEHAVIORAL PATTERN - Behavioral design patterns are concerned with algorithms and the assignment of responsibilities between objects.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;&lt;em&gt;Also know as Policy&lt;/em&gt;&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Many algorithms exist for breaking a stream of text into lines&lt;/p&gt;

&lt;p&gt;How to identify Strategy patterns:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;there are multiple algorithms that will be needed at different times we do not want to support multiple algorithms using line breaking/conditionals&lt;/li&gt;
&lt;li&gt;it is difficult to accommodate change when implemented using line breaks and conditionals&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When to use Strategy pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;many related classes differ only in their behavior. Strategies provide a way to configure a class with one of many behaviors.&lt;/li&gt;
&lt;li&gt;you need different variants of an algorithm&lt;/li&gt;
&lt;li&gt;an algorithm uses data that clients should not know about&lt;/li&gt;
&lt;li&gt;a class defines such behavior and these appear as multiple conditional statements in an operations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Different actors in strategy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Strategy
declares an interface common to all supported algorithms. Context uses the interface to call the algorithm defined by a ConcreteStrategy&lt;/li&gt;
&lt;li&gt;ConcreteStrategy
implementation of the algorithm using the Strategy interface&lt;/li&gt;
&lt;li&gt;Context
maintains a reference to the strategy object&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Refer to the following for the code:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/typescript-uhdd8n?embed=1&amp;amp;file=index.ts" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>designpattens</category>
    </item>
    <item>
      <title>Errors</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Wed, 03 Nov 2021 04:14:52 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/errors-555e</link>
      <guid>https://dev.to/bhargavmantha/errors-555e</guid>
      <description>&lt;h2&gt;
  
  
  It seems that perfection is attained not when there is nothing more to add but when there is nothing more to take away — Antoin de Saint-Exupery
&lt;/h2&gt;

&lt;p&gt;There is a lot that can be inferred/taken by the above statement. Errors only occur in programs if they are not perfect in every way. Antoin also gives us the insight that anything can be made perfect by taking things away from it not adding things to it.&lt;br&gt;
Douglas Crockford in his book JS the Good parts says if a feature is sometimes useful and some times dangerous. and you have a better option always use the better option.&lt;/p&gt;
&lt;h3&gt;
  
  
  WE ARE NOT PAID TO WRITE PROGRAMS THAT USE ALL THE FEATURES OF THE LANGUAGE. INSTEAD, WE ARE PAID TO WRITE PROGRAMS THAT ARE ERROR-FREE AND WORK WELL.
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;My thoughts/take-aways on the above idea&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Always Always Always(I know I am stressing this out too much but it’s a fact), Remember to know how, why, and when to use the specific concept of the language.&lt;br&gt;
here is a very simple example, we all use &amp;gt;, &amp;lt; operators in JS right for instance consider the following example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Number(true);//1
Number(false);//0
1 &amp;lt; 2;//true
2 &amp;lt; 3;//true
1 &amp;lt; 2 &amp;lt; 3;//true
( 1 &amp;lt; 2 ) &amp;lt; 3
( true ) &amp;lt; 3//Auto Coercion by js
1 &amp;lt; 3//true
But (Wait for it)
3 &amp;gt; 2 &amp;gt; 1
( 3 &amp;gt; 2 ) &amp;gt; 1
(true) &amp;gt; 1
1 &amp;gt; 1 //false
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;what!!! but we know that thats not true, this is one of the corner cases in js with auto conversion from boolean to number :’( .&lt;/p&gt;

&lt;p&gt;My point being that if we knew about this corner case this could easily be prevented.&lt;/p&gt;

&lt;p&gt;By this, I don't mean that we should go to extremes and follow&lt;/p&gt;

&lt;p&gt;Type Rigidity or Static Types or Type Soundness.&lt;br&gt;
People say that JS’s dynamic typing is its biggest weakness. I feel that its one of its greatest strengths. I mean, I couldn't imagine js without its dynamic typing. We would have been deprived of so many paradigms if we didn't have dynamic typing.&lt;/p&gt;

&lt;p&gt;So what I mean to say is people. Nothing in a language is magic, everything happens to cause its either meant to be that way or because of historical reasons(in order to not break the older functionality ). Please ppl, remember to understand why questioning the same at every point(there is no stupid question remember). Always understand why before applying.&lt;/p&gt;

&lt;p&gt;ERRORS occur usually (not including the corner cases :) because we do not understand the language and because of our own stupidity, Not the other way round&lt;/p&gt;

&lt;p&gt;REFERENCES -&lt;br&gt;
The Better Parts. Douglas Crockford.&lt;br&gt;
Kyle Sympson — Javascript Foundation(You don't know Javascript).&lt;/p&gt;

&lt;p&gt;Do not agree with me, Change my view ❤&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Running the stored procedure from NestJs</title>
      <dc:creator>BhargavMantha</dc:creator>
      <pubDate>Sun, 25 Jul 2021 14:43:40 +0000</pubDate>
      <link>https://dev.to/bhargavmantha/running-the-stored-procedure-from-nestjs-gj0</link>
      <guid>https://dev.to/bhargavmantha/running-the-stored-procedure-from-nestjs-gj0</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;using the repository that was created,
for instance you want to interact with the table users
and say you have the repository UserRepository. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;dependency inject the user repository into the current service
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;InjectRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Users&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="kr"&gt;private&lt;/span&gt;  &lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="nx"&gt;Repository&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UserRepository&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;now use the  created userReposotory to run the command to invoke the stored procedure
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;call dev_db.listUsers(?)&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,[&lt;/span&gt;&lt;span class="nx"&gt;the_input_paramenters_required&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;--the above query returns a promise with result of stored Procedure or error&lt;br&gt;
So make sure you add await to  function having the above line&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>node</category>
      <category>typeorm</category>
    </item>
  </channel>
</rss>
