<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Saravana Raja's Blog]]></title><description><![CDATA[Hi there! 👋 I'm a software developer who loves building things for the web. I write about what I learn along the way. When not coding, I explore music production and read tech blogs.]]></description><link>https://blog.saravanaraja.in</link><generator>RSS for Node</generator><lastBuildDate>Tue, 07 Apr 2026 11:04:00 GMT</lastBuildDate><atom:link href="https://blog.saravanaraja.in/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[🚀 Introduction to Real-Time Web]]></title><description><![CDATA[For those of us after years into this dev life:

💻 "The weekend is for upskilling!" (then promptly opens Netflix)

☕ Filter coffee - the actual backbone of my productivity

🌙 Midnight message: “Available for Quick Call?”

👥 Catching up with friend...]]></description><link>https://blog.saravanaraja.in/introduction-to-real-time-web</link><guid isPermaLink="true">https://blog.saravanaraja.in/introduction-to-real-time-web</guid><category><![CDATA[realtime]]></category><category><![CDATA[SocketIO]]></category><category><![CDATA[socket]]></category><category><![CDATA[websockets]]></category><category><![CDATA[short polling]]></category><category><![CDATA[longpolling]]></category><dc:creator><![CDATA[Saravana Raja]]></dc:creator><pubDate>Sun, 27 Oct 2024 14:46:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1730046394157/13de1102-9159-4123-a822-ee2d12cd1e28.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>For those of us after years into this dev life:</p>
<ul>
<li><p>💻 "The weekend is for upskilling!" (then promptly opens Netflix)</p>
</li>
<li><p>☕ Filter coffee - the actual backbone of my productivity</p>
</li>
<li><p>🌙 Midnight message: “Available for Quick Call?”</p>
</li>
<li><p>👥 Catching up with friends who switched jobs… because of <em>career inspiration</em></p>
</li>
<li><p>📚 A growing list of “absolutely starting soon” courses (any day now)</p>
</li>
<li><p>💪 Consistent gym attendance (hey, one routine we stick to)</p>
</li>
</ul>
<p>Building real-time applications is supposed to add excitement to the dev life—but let's be real, some parts are more like glorified waiting rooms. Here’s the rundown on the methods available, the reality, and a sprinkle of sarcasm.</p>
<hr />
<h2 id="heading-real-time-techs-the-honestly-real-rundown">Real-Time Techs: The Honestly Real Rundown</h2>
<h3 id="heading-1-short-polling"><strong>1. Short Polling</strong></h3>
<p><em>The "refresh-until-something-happens" approach.</em></p>
<p>Short polling is like constantly checking to see if you've made progress on your "to-learn" list… every weekend. It’s simple but resource-hungry. The client keeps asking, “Anything new?” until the server finally has something to say.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Client</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StatusChecker</span> </span>{
  <span class="hljs-keyword">constructor</span>(url, interval = 5000) {
    <span class="hljs-built_in">this</span>.url = url;
    <span class="hljs-built_in">this</span>.interval = interval;
  }

  start() {
    <span class="hljs-built_in">setInterval</span>(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-built_in">this</span>.url);
        <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
        <span class="hljs-built_in">this</span>.handleUpdate(data);
      } <span class="hljs-keyword">catch</span> (error) {
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Update failed:"</span>, error);
      }
    }, <span class="hljs-built_in">this</span>.interval);
  }
}

<span class="hljs-comment">// Server (Express)</span>
app.get(<span class="hljs-string">"/status"</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.json({
    <span class="hljs-attr">timestamp</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
    <span class="hljs-attr">data</span>: getCurrentData(),
  });
});
</code></pre>
<p>Pros: 🟢 Quick to set up</p>
<p>Cons: 🔴 Wastes resources. Every request is a bit like "refreshing Netflix recommendations."</p>
<h3 id="heading-2-long-polling">2. Long Polling</h3>
<p>"I'll just wait here until motivation hits" (and it might be a while).</p>
<p>In long polling, the client sends a request and waits… and waits... until the server finally sends an update. It's like sitting down to work on that online course, only to sit there wondering what else you could be doing.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Client</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LongPoller</span> </span>{
  <span class="hljs-keyword">async</span> startPolling() {
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">'/updates'</span>);
      <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();
      <span class="hljs-built_in">this</span>.handleData(data);
      <span class="hljs-built_in">this</span>.startPolling();
    } <span class="hljs-keyword">catch</span> {
      <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.startPolling(), <span class="hljs-number">3000</span>);
    }
  }
}

<span class="hljs-comment">// Server</span>
app.get(<span class="hljs-string">'/updates'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> update = <span class="hljs-keyword">await</span> waitForNewData();
    res.json(update);
  } <span class="hljs-keyword">catch</span> (error) {
    res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">'Error occurred'</span>);
  }
});
</code></pre>
<p>Pros: 🟢 Fewer requests than short polling</p>
<p>Cons: 🔴 Holds connections open, so scaling gets tricky</p>
<h3 id="heading-3-server-sent-events-sse">3. Server-Sent Events (SSE)</h3>
<p>The friend who only talks about themselves.</p>
<p>SSE is perfect for one-way notifications where the server does all the talking and the client listens (whether they want to or not). Think of it like that friend who only likes to talk about their day and never asks about yours. It's ideal for notifications and one-way updates.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Client</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">EventSourceHandler</span> </span>{
  <span class="hljs-keyword">constructor</span>(url) {
    <span class="hljs-built_in">this</span>.eventSource = <span class="hljs-keyword">new</span> EventSource(url);
    <span class="hljs-built_in">this</span>.setup();
  }

  setup() {
    <span class="hljs-built_in">this</span>.eventSource.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-keyword">const</span> data = <span class="hljs-built_in">JSON</span>.parse(event.data);
      <span class="hljs-built_in">this</span>.handleUpdate(data);
    };

    <span class="hljs-built_in">this</span>.eventSource.onerror = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">this</span>.eventSource.close();
      <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.reconnect(), <span class="hljs-number">3000</span>);
    };
  }
}

<span class="hljs-comment">// Server</span>
app.get(<span class="hljs-string">'/events'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.setHeader(<span class="hljs-string">'Content-Type'</span>, <span class="hljs-string">'text/event-stream'</span>);
  res.setHeader(<span class="hljs-string">'Cache-Control'</span>, <span class="hljs-string">'no-cache'</span>);
  res.setHeader(<span class="hljs-string">'Connection'</span>, <span class="hljs-string">'keep-alive'</span>);

  <span class="hljs-keyword">const</span> interval = <span class="hljs-built_in">setInterval</span>(<span class="hljs-function">() =&gt;</span> {
    res.write(<span class="hljs-string">`data: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify({
      time: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>(),
      data: getLatestData()
    }</span>)}\n\n`</span>);
  }, <span class="hljs-number">1000</span>);

  req.on(<span class="hljs-string">'close'</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">clearInterval</span>(interval));
});
</code></pre>
<p>Pros: 🟢 Real-time updates without repetitive requests</p>
<p>Cons: 🔴 One-way communication only, so the client doesn't get to "talk back."</p>
<h3 id="heading-4-websocket">4. WebSocket</h3>
<p>The reliable, low-latency solution for night-owl coders.</p>
<p>WebSockets allow true, two-way communication, making it ideal for live applications like multiplayer games or chat. Think of it as having a direct line open at all times, even at 2 a.m., when inspiration strikes.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Client</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WebSocketClient</span> </span>{
  <span class="hljs-keyword">constructor</span>(url) {
    <span class="hljs-built_in">this</span>.connect(url);
  }

  connect(url) {
    <span class="hljs-built_in">this</span>.ws = <span class="hljs-keyword">new</span> WebSocket(url);

    <span class="hljs-built_in">this</span>.ws.onopen = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Connected'</span>);
      <span class="hljs-built_in">this</span>.startHeartbeat();
    };

    <span class="hljs-built_in">this</span>.ws.onmessage = <span class="hljs-function">(<span class="hljs-params">event</span>) =&gt;</span> {
      <span class="hljs-built_in">this</span>.handleMessage(<span class="hljs-built_in">JSON</span>.parse(event.data));
    };

    <span class="hljs-built_in">this</span>.ws.onclose = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">this</span>.connect(url), <span class="hljs-number">3000</span>);
    };
  }

  send(data) {
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.ws.readyState === WebSocket.OPEN) {
      <span class="hljs-built_in">this</span>.ws.send(<span class="hljs-built_in">JSON</span>.stringify(data));
    }
  }
}

<span class="hljs-comment">// Server</span>
<span class="hljs-keyword">const</span> WebSocket = <span class="hljs-built_in">require</span>(<span class="hljs-string">'ws'</span>);
<span class="hljs-keyword">const</span> wss = <span class="hljs-keyword">new</span> WebSocket.Server({ <span class="hljs-attr">port</span>: <span class="hljs-number">8080</span> });

wss.on(<span class="hljs-string">'connection'</span>, <span class="hljs-function">(<span class="hljs-params">ws</span>) =&gt;</span> {
  ws.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
    wss.clients.forEach(<span class="hljs-function"><span class="hljs-params">client</span> =&gt;</span> {
      <span class="hljs-keyword">if</span> (client !== ws &amp;&amp; client.readyState === WebSocket.OPEN) {
        client.send(message);
      }
    });
  });
});
</code></pre>
<p>Pros: 🟢 True real-time, bidirectional communication</p>
<p>Cons: 🔴 Requires consistent connection management (a.k.a. babysitting)</p>
<h3 id="heading-5-socketiohttpsocketio">5. <a target="_blank" href="http://Socket.IO">Socket.IO</a></h3>
<p>For when you just want it to "work."</p>
<p><a target="_blank" href="http://Socket.IO">Socket.IO</a> is like WebSockets but adds extra features, like automatic reconnections, room-based messaging, and even some fallbacks. It's WebSockets with fewer headaches.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Client</span>
<span class="hljs-keyword">const</span> socket = io(<span class="hljs-string">'http://localhost:3000'</span>, {
  <span class="hljs-attr">reconnectionAttempts</span>: <span class="hljs-number">5</span>,
  <span class="hljs-attr">reconnectionDelay</span>: <span class="hljs-number">1000</span>
});

socket.on(<span class="hljs-string">'connect'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Connected'</span>);
  socket.emit(<span class="hljs-string">'join'</span>, { <span class="hljs-attr">room</span>: <span class="hljs-string">'main'</span> });
});

socket.on(<span class="hljs-string">'update'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
  handleUpdate(data);
});

<span class="hljs-comment">// Server</span>
<span class="hljs-keyword">const</span> io = <span class="hljs-built_in">require</span>(<span class="hljs-string">'socket.io'</span>)(server);

io.on(<span class="hljs-string">'connection'</span>, <span class="hljs-function">(<span class="hljs-params">socket</span>) =&gt;</span> {
  socket.on(<span class="hljs-string">'join'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    socket.join(data.room);
  });

  socket.on(<span class="hljs-string">'message'</span>, <span class="hljs-function">(<span class="hljs-params">data</span>) =&gt;</span> {
    io.to(data.room).emit(<span class="hljs-string">'update'</span>, {
      <span class="hljs-attr">data</span>: data,
      <span class="hljs-attr">time</span>: <span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>()
    });
  });
});
</code></pre>
<p>Pros: 🟢 Takes care of reconnection, fallbacks, and supports rooms</p>
<p>Cons: 🔴 A bit more overhead and can lead to overengineering if you're not careful</p>
<h2 id="heading-real-time-technology-choice-guide">Real-Time Technology Choice Guide</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Need</strong></td><td><strong>Choose</strong></td><td><strong>Because</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Simple updates</td><td>Short Polling</td><td>Minimal effort</td></tr>
<tr>
<td>Less server requests</td><td>Long Polling</td><td>Reduces wasteful pings</td></tr>
<tr>
<td>One-way server notifications</td><td>SSE</td><td>Quick and efficient</td></tr>
<tr>
<td>Bidirectional updates</td><td>WebSocket</td><td>Low-latency communication</td></tr>
<tr>
<td>Full-featured solution</td><td><a target="_blank" href="http://Socket.IO">Socket.IO</a></td><td>Packs everything you need</td></tr>
</tbody>
</table>
</div><hr />
<h2 id="heading-best-practices">Best Practices</h2>
<ol>
<li><p><strong>Handle disconnections</strong>: Real-time apps drop out too.</p>
<ul>
<li><p>Implement reconnection logic</p>
</li>
<li><p>Provide clear feedback to users</p>
</li>
</ul>
</li>
<li><p><strong>Implement retries</strong>: Users will be grateful for the save.</p>
<ul>
<li><p>Use exponential backoff for retries</p>
</li>
<li><p>Set a maximum retry limit</p>
</li>
</ul>
</li>
<li><p><strong>Monitor performance</strong>: Real-time sounds cool, but it's server-intensive.</p>
<ul>
<li><p>Keep an eye on server load</p>
</li>
<li><p>Implement rate limiting if necessary</p>
</li>
</ul>
</li>
<li><p><strong>Keep security in mind</strong>: Exposing more data = higher risk.</p>
<ul>
<li><p>Use secure WebSocket connections (wss://)</p>
</li>
<li><p>Implement proper authentication and authorization</p>
</li>
</ul>
</li>
<li><p><strong>Validate data</strong>: Because no one likes unexpected surprises.</p>
<ul>
<li><p>Sanitize incoming data on both client and server</p>
</li>
<li><p>Use schemas to ensure data integrity</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-real-world-considerations">Real-World Considerations</h2>
<ol>
<li><p><strong>Start Simple</strong>: Pick only what your app truly needs.</p>
<ul>
<li><p>Don't overengineer your initial implementation</p>
</li>
<li><p>You can always scale up later</p>
</li>
</ul>
</li>
<li><p><strong>Scale Carefully</strong>: Real-time's great until you have 10,000 users.</p>
<ul>
<li><p>Consider using a message queue for high-load scenarios</p>
</li>
<li><p>Look into horizontal scaling options early</p>
</li>
</ul>
</li>
<li><p><strong>Plan for Failures</strong>: Real-time is only as good as its recovery plan.</p>
<ul>
<li><p>Implement proper error handling</p>
</li>
<li><p>Have a fallback mechanism (e.g., reverting to polling if WebSocket fails)</p>
</li>
</ul>
</li>
<li><p><strong>Maintenance</strong>: Each real-time feature comes with its own upkeep.</p>
<ul>
<li><p>Regular testing of real-time features</p>
</li>
<li><p>Keep libraries and dependencies up to date</p>
</li>
</ul>
</li>
</ol>
<hr />
<h2 id="heading-conclusion">Conclusion</h2>
<p>Real-time technology can add sparkle to your app, but remember to choose the one that actually fits your needs. And, for those still working on that "upskilling" plan, simpler might just be better. So, here's to keeping it real-time, without over-complicating the weekend Netflix break!</p>
<p>And speaking of which… time for another filter coffee. ☕</p>
<hr />
<p><em>Did this guide help you navigate the world of real-time web development? Share your thoughts and experiences in the comments below!</em></p>
<p><em>Don't forget to like and share if you found this useful. Happy coding!</em> 🚀👨‍💻👩‍💻</p>
]]></content:encoded></item></channel></rss>