<?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" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ server - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ server - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Fri, 24 Jul 2026 09:05:22 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/server/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ How Clients and Servers Communicate: Full Handbook on HTTP/1.1, HTTP/2, REST, WebSockets, GraphQL, gRPC, and Protocol Buffers ]]>
                </title>
                <description>
                    <![CDATA[ You've built and consumed APIs. You know what a GET request is, what a JSON response looks like, and how to add an Authorization header. You've used REST, maybe tried GraphQL, and perhaps heard of gRP ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-clients-and-servers-communicate-handbook-http-rest-websockets-graphql-grpc-protobuf/</link>
                <guid isPermaLink="false">6a62a069f97a6bd65ce3cd8f</guid>
                
                    <category>
                        <![CDATA[ server ]]>
                    </category>
                
                    <category>
                        <![CDATA[ clients ]]>
                    </category>
                
                    <category>
                        <![CDATA[ networking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software ]]>
                    </category>
                
                    <category>
                        <![CDATA[ engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ gRPC ]]>
                    </category>
                
                    <category>
                        <![CDATA[ http ]]>
                    </category>
                
                    <category>
                        <![CDATA[ http2 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ protobuf ]]>
                    </category>
                
                    <category>
                        <![CDATA[ handbook ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Oluwaseyi Fatunmole ]]>
                </dc:creator>
                <pubDate>Thu, 23 Jul 2026 23:14:49 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/uploads/covers/5e1e335a7a1d3fcc59028c64/b44f7067-5398-492a-b1f7-789f73673c34.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You've built and consumed APIs. You know what a GET request is, what a JSON response looks like, and how to add an Authorization header. You've used REST, maybe tried GraphQL, and perhaps heard of gRPC.</p>
<p>But do you know what actually happens when your application sends a request? What travels through the wire? Why does HTTP/2 make things faster? Why do WebSockets exist when HTTP already works? What makes Protocol Buffers different from JSON at a fundamental level?</p>
<p>And when you're designing a system, how do you decide which communication approach to use?</p>
<p>These are the questions this handbook answers.</p>
<p>This isn't a beginner's guide to APIs. This is a deep dive into how clients and servers actually communicate: the protocols, the trade-offs, the history of why each approach was built, and the engineering thinking behind choosing one over another.</p>
<p>By the end, you won't just know what these technologies are. You'll understand why they exist, how they work at a level that makes you a better engineer, and how to make deliberate architectural decisions about communication in your systems.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a href="#the-foundation-how-two-machines-talk-to-each-other">The Foundation: How Two Machines Talk to Each Other</a></p>
</li>
<li><p><a href="#http11-the-protocol-that-built-the-web">HTTP/1.1: The Protocol That Built the Web</a></p>
</li>
<li><p><a href="#the-problems-http11-could-not-solve">The Problems HTTP/1.1 Could Not Solve</a></p>
</li>
<li><p><a href="#http2-rebuilding-the-foundation">HTTP/2: Rebuilding the Foundation</a></p>
</li>
<li><p><a href="#http3-and-quic-the-next-evolution">HTTP/3 and QUIC: The Next Evolution</a></p>
</li>
<li><p><a href="#data-formats-how-information-is-encoded">Data Formats: How Information Is Encoded</a></p>
</li>
<li><p><a href="#rest-the-architecture-that-took-over-the-world">REST: The Architecture That Took Over the World</a></p>
</li>
<li><p><a href="#the-limits-of-rest">The Limits of REST</a></p>
</li>
<li><p><a href="#graphql-letting-the-client-decide">GraphQL: Letting the Client Decide</a></p>
</li>
<li><p><a href="#websockets-when-http-is-not-enough">WebSockets: When HTTP Is Not Enough</a></p>
</li>
<li><p><a href="#server-sent-events-the-simpler-real-time-option">Server-Sent Events: The Simpler Real-Time Option</a></p>
</li>
<li><p><a href="#protocol-buffers-a-new-language-for-data">Protocol Buffers: A New Language for Data</a></p>
</li>
<li><p><a href="#grpc-remote-procedure-calls-at-scale">gRPC: Remote Procedure Calls at Scale</a></p>
</li>
<li><p><a href="#the-complete-comparison">The Complete Comparison</a></p>
</li>
<li><p><a href="#how-to-choose-the-engineering-decision-framework">How to Choose: The Engineering Decision Framework</a></p>
</li>
<li><p><a href="#conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-the-foundation-how-two-machines-talk-to-each-other">The Foundation: How Two Machines Talk to Each Other</h2>
<p>Before any protocol, data format, or architectural style enters the picture, two machines need to establish a connection. Understanding this foundation makes everything else click.</p>
<h3 id="heading-ip-addresses-and-ports">IP Addresses and Ports</h3>
<p>Every device on a network has an IP address: a unique identifier that works like a postal address. When your application sends a request to <code>api.example.com</code>, the first thing that happens is a DNS lookup, which translates that human-readable name into an IP address like <code>93.184.216.34</code>. That IP address is where the packet is going.</p>
<p>But an IP address alone isn't enough. A single server might be running dozens of different services simultaneously: a web server, a database, an email server, an SSH daemon.</p>
<p>Ports tell the operating system which service should handle the incoming connection. Port 80 is the conventional port for HTTP. Port 443 is for HTTPS. Port 5432 is for PostgreSQL. Port 22 is for SSH. When you call <code>api.example.com/users</code>, you are actually calling <code>api.example.com:443/users</code>. The browser fills in the port automatically.</p>
<h3 id="heading-tcp-the-reliable-foundation">TCP: The Reliable Foundation</h3>
<p>Most web communication runs over TCP (Transmission Control Protocol). TCP is a connection-oriented protocol, which means before any data is exchanged, both parties go through a handshake to establish a connection.</p>
<p>The TCP handshake works in three steps, which is why it's called the three-way handshake:</p>
<pre><code class="language-plaintext">Client                    Server
  |                          |
  |-------- SYN -----------&gt;|   "I want to connect"
  |                          |
  |&lt;------- SYN-ACK --------|   "Okay, I acknowledge. Ready?"
  |                          |
  |-------- ACK -----------&gt;|   "Great, let's go"
  |                          |
  [Connection established]
</code></pre>
<p>SYN stands for synchronize. ACK stands for acknowledge. After these three packets, the connection exists and data can flow.</p>
<p>TCP guarantees three things that make it the foundation of reliable communication:</p>
<ol>
<li><p><strong>Delivery</strong>: if a packet is lost in transit, TCP detects this and retransmits it automatically. The application layer never has to worry about lost packets.</p>
</li>
<li><p><strong>Order</strong>: packets arrive in the same order they were sent. If packets arrive out of order (which happens frequently on real networks), TCP reorders them before delivering them to the application.</p>
</li>
<li><p><strong>Error detection</strong>: every TCP packet includes a checksum. If the data is corrupted in transit, TCP detects and discards the corrupted packet, then requests a retransmission.</p>
</li>
</ol>
<p>This reliability comes at a cost: the overhead of the handshake, the acknowledgment packets, and the retransmission logic.</p>
<p>For many use cases, this cost is worth it. For some (live video streaming, online gaming, DNS lookups), UDP (User Datagram Protocol) is preferred because it sends packets without any of this overhead, accepting some loss in exchange for speed. HTTP/3, which we'll cover later, is built on a protocol that brings reliability to UDP.</p>
<h3 id="heading-tls-encrypting-the-connection">TLS: Encrypting the Connection</h3>
<p>On the modern web, most connections use HTTPS rather than plain HTTP. The S stands for Secure, and the security is provided by TLS (Transport Layer Security), the successor to SSL.</p>
<p>TLS adds an additional handshake on top of the TCP connection. During the TLS handshake:</p>
<ol>
<li><p>The client and the server agree on which version of TLS to use and which encryption algorithms to support</p>
</li>
<li><p>The server presents its digital certificate (issued by a trusted Certificate Authority)</p>
</li>
<li><p>The client verifies the certificate is valid and belongs to the server it intended to reach</p>
</li>
<li><p>They exchange encryption keys using asymmetric cryptography</p>
</li>
<li><p>From that point forward, all communication is encrypted with symmetric encryption</p>
</li>
</ol>
<p>The TLS handshake adds latency. In TLS 1.2, it takes two round trips before any application data can flow. TLS 1.3, released in 2018, reduced this to one round trip, and even supports zero round-trip resumption for returning connections.</p>
<p>Understanding TCP and TLS matters because every protocol we discuss runs on top of them (until HTTP/3, which changes the underlying transport). When people talk about the "overhead" of HTTPS or the "cost" of establishing a connection, they're talking about the time and packets spent on these handshakes before a single byte of your actual request travels.</p>
<h2 id="heading-http11-the-protocol-that-built-the-web">HTTP/1.1: The Protocol That Built the Web</h2>
<p>HTTP (HyperText Transfer Protocol) was invented by Tim Berners-Lee in 1991 to transfer HTML documents between computers. HTTP/1.0 was simple: one request per connection, then the connection closes.</p>
<p>HTTP/1.1, standardized in 1997, brought significant improvements and became the dominant version of HTTP for nearly two decades. It introduced persistent connections (keep connections open across multiple requests), chunked transfer encoding, and more sophisticated caching mechanisms.</p>
<h3 id="heading-how-an-http11-request-works">How an HTTP/1.1 Request Works</h3>
<p>An HTTP request is a text message with a specific structure:</p>
<pre><code class="language-plaintext">POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...
Accept: application/json
Content-Length: 45
User-Agent: MyApp/2.0

{"name": "John Smith", "email": "john@example.com"}
</code></pre>
<p>The first line is the request line: the HTTP method (POST), the path (/api/users), and the protocol version.</p>
<p>Below that are the headers: key-value pairs that provide metadata about the request. The host, the content type, the authorization token, what format the client accepts, and how large the body is.</p>
<p>After a blank line comes the body: the actual data being sent.</p>
<p>The server processes this and responds:</p>
<pre><code class="language-plaintext">HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/users/usr_789
Date: Mon, 21 Jul 2026 09:15:00 GMT
Content-Length: 89

{"id": "usr_789", "name": "John Smith", "email": "john@example.com", "created_at": "..."}
</code></pre>
<p>The response has a status line (the protocol version, the status code, and a reason phrase), headers, and a body.</p>
<h3 id="heading-http-methods-and-their-semantics">HTTP Methods and Their Semantics</h3>
<p>HTTP/1.1 defines several methods, each with specific semantics:</p>
<ul>
<li><p><strong>GET</strong> retrieves a resource. A GET request should have no side effects. It shouldn't create or modify anything. It's safe and idempotent, meaning calling it multiple times has the same effect as calling it once.</p>
</li>
<li><p><strong>POST</strong> submits data to create a new resource or trigger an action. It's neither safe nor idempotent: calling POST twice typically creates two resources.</p>
</li>
<li><p><strong>PUT</strong> replaces a resource entirely with the provided data. It's idempotent: calling PUT twice with the same data has the same effect as calling it once.</p>
</li>
<li><p><strong>PATCH</strong> partially updates a resource. Only the fields provided are changed.</p>
</li>
<li><p><strong>DELETE</strong> removes a resource. It's idempotent: deleting something that doesn't exist is still considered successful.</p>
</li>
<li><p><strong>HEAD</strong> is identical to GET but the server only returns headers, not the body. It's used to check if a resource exists or has been modified without downloading the full content.</p>
</li>
<li><p><strong>OPTIONS</strong> asks the server what methods are allowed for a resource. It's used in CORS preflight requests.</p>
</li>
</ul>
<h3 id="heading-status-codes">Status Codes</h3>
<p>HTTP status codes are three-digit numbers grouped into five categories:</p>
<p><strong>1xx Informational</strong> — the server has received the request and is continuing to process it. These are rarely seen in practice outside of specific use cases like HTTP upgrade (used to establish WebSocket connections).</p>
<p><strong>2xx Success</strong> — the request was received, understood, and accepted.</p>
<ul>
<li><p>200 OK: standard success response</p>
</li>
<li><p>201 Created: a new resource was created</p>
</li>
<li><p>204 No Content: success but nothing to return (common for DELETE)</p>
</li>
</ul>
<p><strong>3xx Redirection</strong> — further action is required to complete the request.</p>
<ul>
<li><p>301 Moved Permanently: the resource has a new URL forever</p>
</li>
<li><p>302 Found: temporary redirect</p>
</li>
<li><p>304 Not Modified: the cached version is still valid (used with ETags)</p>
</li>
</ul>
<p><strong>4xx Client Error</strong> — the request contains bad syntax or can't be fulfilled.</p>
<ul>
<li><p>400 Bad Request: the request is malformed</p>
</li>
<li><p>401 Unauthorized: authentication is required (despite the name, it means unauthenticated)</p>
</li>
<li><p>403 Forbidden: authenticated but not authorized to access this resource</p>
</li>
<li><p>404 Not Found: the resource doesn't exist</p>
</li>
<li><p>422 Unprocessable Entity: the request is syntactically valid but semantically wrong (common for validation errors)</p>
</li>
<li><p>429 Too Many Requests: rate limit exceeded</p>
</li>
</ul>
<p><strong>5xx Server Error</strong> — the server failed to fulfill a valid request.</p>
<ul>
<li><p>500 Internal Server Error: something went wrong on the server</p>
</li>
<li><p>502 Bad Gateway: the server received an invalid response from an upstream server</p>
</li>
<li><p>503 Service Unavailable: the server is temporarily unavailable</p>
</li>
<li><p>504 Gateway Timeout: the upstream server did not respond in time</p>
</li>
</ul>
<h3 id="heading-caching-in-http11">Caching in HTTP/1.1</h3>
<p>One of HTTP/1.1's most powerful features is its built-in caching model. Responses can include headers that tell clients and intermediate caches how long to store a response and when to revalidate it.</p>
<ul>
<li><p><code>Cache-Control: max-age=3600</code> tells the client to cache this response for one hour.</p>
</li>
<li><p><code>Cache-Control: no-cache</code> tells the client to always revalidate with the server before using a cached response.</p>
</li>
<li><p><code>Cache-Control: no-store</code> tells the client never to cache this response.</p>
</li>
</ul>
<p><code>ETag</code> is a fingerprint of the response content. When the client makes a subsequent request, it sends the ETag back in an <code>If-None-Match</code> header. If the content hasn't changed, the server responds with 304 Not Modified and no body, saving bandwidth.</p>
<p><code>Last-Modified</code> works similarly: the client sends <code>If-Modified-Since</code> and the server confirms whether the content has changed.</p>
<p>Caching is one of the key reasons REST over HTTP became dominant. GET requests to well-designed REST APIs can be cached at the CDN level, meaning the same response is served to thousands of users without the request ever reaching your origin server.</p>
<h2 id="heading-the-problems-http11-could-not-solve">The Problems HTTP/1.1 Could Not Solve</h2>
<p>HTTP/1.1 served the web well for two decades. But as the web grew more complex, applications more dynamic, and user expectations higher, its architectural limitations became significant performance bottlenecks.</p>
<h3 id="heading-head-of-line-blocking">Head-of-Line Blocking</h3>
<p>HTTP/1.1 processes requests sequentially on a single connection. The server must finish responding to one request before the next one on the same connection begins.</p>
<pre><code class="language-plaintext">Connection 1:
Request 1 (slow database query) -----&gt; [3 seconds] -----&gt; Response 1
Request 2 (fast in-memory read) -----&gt; [waits 3 seconds] -----&gt; Response 2
Request 3 (static file) -----------&gt; [waits 3+ seconds] -----&gt; Response 3
</code></pre>
<p>Request 2 and Request 3 are fast operations. But they're stuck waiting for Request 1 to complete. This is head-of-line blocking: the head of the queue blocks everything behind it.</p>
<p>Browsers worked around this by opening multiple parallel TCP connections to the same server, typically six. But each connection requires its own TCP handshake and TLS negotiation, consuming resources on both the client and server.</p>
<h3 id="heading-verbose-headers-on-every-request">Verbose Headers on Every Request</h3>
<p>Every HTTP/1.1 request sends its complete headers as plain text. Consider a mobile application making fifty requests during a session. On every single request, the following headers are sent in full:</p>
<pre><code class="language-plaintext">Host: api.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3JfMTIzIn0...
Content-Type: application/json
Accept: application/json
Accept-Language: en-US,en;q=0.9
Accept-Encoding: gzip, deflate, br
User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X)...
</code></pre>
<p>The Authorization header alone, carrying a JWT, can be 400 to 600 bytes. Multiplied by fifty requests, that is 20 to 30 kilobytes of data carrying nothing but headers that haven't changed between requests.</p>
<p>On a 4G mobile connection with limited bandwidth, this is waste. On a 2G connection in a network-constrained environment, it's a significant performance penalty.</p>
<h3 id="heading-no-server-push">No Server Push</h3>
<p>HTTP/1.1 is strictly request-response. The server can't send data until the client asks for it. This fundamental limitation means the server can never proactively inform the client of changes.</p>
<p>For applications requiring real-time updates, short polling became a common workaround: the client sends a request every few seconds asking "has anything changed?" This is inefficient because most polling requests receive a "no, nothing has changed" response, consuming bandwidth and server resources for no purpose.</p>
<p>Long polling was a refinement: the client sends a request and the server holds it open until something changes or a timeout occurs. This reduces unnecessary responses but keeps connections open indefinitely, consuming server resources.</p>
<p>Both are workarounds for a fundamental limitation of HTTP/1.1's request-response model.</p>
<h3 id="heading-inefficient-use-of-connections">Inefficient Use of Connections</h3>
<p>Opening a new TCP connection requires the three-way handshake plus the TLS handshake: a process that can take 200 to 500 milliseconds on a mobile connection.</p>
<p>HTTP/1.1 introduced keep-alive connections to reuse connections across multiple requests, but head-of-line blocking made this only partially effective. Browsers opened multiple connections to compensate, but six parallel connections per domain is both a client limitation and a server resource concern at scale.</p>
<h2 id="heading-http2-rebuilding-the-foundation">HTTP/2: Rebuilding the Foundation</h2>
<p>Google published a protocol called SPDY (pronounced "speedy") in 2009, designed to address HTTP/1.1's performance limitations. SPDY demonstrated that significant improvements were possible without changing the fundamental HTTP semantics. HTTP/2, standardized by the IETF in 2015, was heavily based on SPDY and became the successor to HTTP/1.1.</p>
<p>HTTP/2 doesn't change what you send. From the application developer's perspective, requests still have methods, paths, headers, and bodies. Responses still have status codes, headers, and bodies. What HTTP/2 changes is how all of this is transmitted.</p>
<h3 id="heading-binary-framing-the-core-change">Binary Framing: The Core Change</h3>
<p>HTTP/1.1 is a text protocol. Headers, status lines, and method names are all ASCII text. Machines must parse this text character by character to interpret it.</p>
<p>HTTP/2 is a binary protocol. Every piece of information is encoded as binary frames rather than text. Binary is more compact and significantly faster for machines to parse. Instead of tokenizing a string looking for colons and newlines to separate header names from values, a binary parser reads fixed-length fields directly from memory.</p>
<p>The binary framing layer is the foundation everything else in HTTP/2 is built upon.</p>
<h3 id="heading-multiplexing-many-streams-one-connection">Multiplexing: Many Streams, One Connection</h3>
<p>HTTP/2 introduces the concept of streams. A stream is an independent, bidirectional sequence of frames within a single TCP connection. Multiple streams can exist simultaneously on the same connection.</p>
<pre><code class="language-plaintext">Single TCP connection to api.example.com

Stream 1: GET /user/profile ---------&gt; Response arrives
Stream 2: GET /user/balance ---------&gt; Response arrives
Stream 3: POST /transactions --------&gt; Response arrives
Stream 4: GET /notifications --------&gt; Response arrives

All four streams active simultaneously
No stream waits for any other stream
</code></pre>
<p>This is multiplexing: many independent requests and responses interleaved on the same connection. Head-of-line blocking at the HTTP level is eliminated. A slow request on Stream 1 doesn't prevent Stream 2, 3, or 4 from receiving their responses.</p>
<p>One connection replaces six parallel connections. The TCP handshake and TLS negotiation happen once. Connection overhead drops dramatically.</p>
<h3 id="heading-header-compression-with-hpack">Header Compression with HPACK</h3>
<p>HTTP/2 compresses headers using an algorithm called HPACK specifically designed for HTTP headers.</p>
<p>HPACK works in two ways. First, it maintains a table of previously seen headers. Instead of retransmitting a header that was sent on the previous request, it sends a reference to the table entry: a single integer instead of hundreds of bytes of text.</p>
<p>Second, HPACK uses Huffman encoding for new header values, reducing the size of strings that can't be referenced from the table.</p>
<p>The result: a mobile application sending the same Authorization header on every request transmits it in full on the first request, then sends a one-byte or two-byte reference on every subsequent request. What was 500 bytes of overhead becomes 2 bytes.</p>
<p>Across fifty requests in a session, this eliminates thousands of bytes of redundant header transmission.</p>
<h3 id="heading-stream-prioritization">Stream Prioritization</h3>
<p>HTTP/2 allows clients to assign priority to streams. A browser loading a web page can signal that the CSS file (needed to render anything) is higher priority than the analytics script (not needed for initial render). The server can use these priorities to decide the order in which it sends frames when multiple streams are active.</p>
<p>In practice, stream prioritization has been inconsistently implemented and is being redesigned in HTTP/3.</p>
<h3 id="heading-server-push">Server Push</h3>
<p>HTTP/2 allows the server to proactively send resources to the client without waiting for a request. When a browser requests an HTML file, the server can immediately push the CSS and JavaScript files it knows the browser will need next, before the browser has even parsed the HTML to discover it needs them.</p>
<pre><code class="language-plaintext">Client: GET /index.html
Server: Here is index.html
Server: (push) Here is styles.css — you will need this
Server: (push) Here is app.js — you will need this too
</code></pre>
<p>In practice, server push has had mixed adoption due to implementation complexity and the risk of pushing resources the client already has cached. HTTP/3 is reconsidering how push should work.</p>
<h3 id="heading-http2-and-grpc">HTTP/2 and gRPC</h3>
<p>HTTP/2's multiplexing and persistent connections make it the ideal transport for gRPC. A single HTTP/2 connection can carry many concurrent gRPC calls, including long-running streaming calls that push data continuously. This is why gRPC requires HTTP/2: the features that make gRPC efficient are provided by the transport layer.</p>
<h2 id="heading-http3-and-quic-the-next-evolution">HTTP/3 and QUIC: The Next Evolution</h2>
<p>Even with HTTP/2's improvements, one fundamental problem remained: TCP head-of-line blocking.</p>
<p>HTTP/2 eliminated head-of-line blocking at the HTTP level. Multiple HTTP/2 streams can proceed independently. But all of those streams share a single TCP connection. TCP guarantees ordered delivery of all bytes in a connection. If a single TCP packet is lost, the entire connection stalls while TCP retransmits that packet, even for streams that have nothing to do with the lost packet.</p>
<pre><code class="language-plaintext">HTTP/2 over TCP — packet loss scenario:

Stream 1: data in flight...
Stream 2: data in flight...
Stream 3: packet LOST — TCP retransmission required

Stream 1: STALLED (waiting for TCP retransmission)
Stream 2: STALLED (waiting for TCP retransmission)
Stream 3: retransmission in progress...
</code></pre>
<p>Both streams 1 and 2 are blocked by a packet loss that affected only stream 3. This is TCP head-of-line blocking, and HTTP/2 can't eliminate it because it operates above the TCP layer.</p>
<h3 id="heading-quic-a-new-transport-protocol">QUIC: A New Transport Protocol</h3>
<p>Google developed QUIC (Quick UDP Internet Connections) to solve this problem. QUIC is a new transport protocol built on UDP instead of TCP, designed to provide some very helpful new features:</p>
<ol>
<li><p><strong>Multiplexing without head-of-line blocking:</strong> QUIC understands streams natively. A packet loss in one QUIC stream only stalls that stream. Other streams on the same connection continue flowing freely.</p>
</li>
<li><p><strong>Built-in encryption:</strong> Unlike TLS which runs on top of TCP, QUIC has TLS 1.3 built into the protocol itself. The transport and security layers are integrated, reducing the number of round trips required before data can flow.</p>
</li>
<li><p><strong>Faster connection establishment:</strong> A new QUIC connection requires one round trip before data can flow. For returning connections where a session ticket exists, QUIC can send data in zero round trips (0-RTT).</p>
</li>
<li><p><strong>Connection migration:</strong> A TCP connection is identified by the four-tuple of source IP, source port, destination IP, and destination port. If any of these change (say, a mobile device switches from WiFi to cellular), the TCP connection breaks and must be re-established. QUIC connections are identified by a connection ID that survives network changes, enabling seamless handoff.</p>
</li>
</ol>
<h3 id="heading-http3">HTTP/3</h3>
<p>HTTP/3 is HTTP semantics over QUIC. The request and response model remains the same. Headers, status codes, and methods are all identical. The transport underneath is QUIC instead of TCP.</p>
<p>HTTP/3 is particularly impactful for:</p>
<ol>
<li><p><strong>Mobile networks</strong> where packet loss is more common and devices frequently switch between networks.</p>
</li>
<li><p><strong>High-latency connections</strong> where the reduced handshake round trips save meaningful time.</p>
</li>
<li><p><strong>Applications with many concurrent streams</strong> where TCP head-of-line blocking was a real bottleneck.</p>
</li>
</ol>
<p>As of 2026, HTTP/3 is supported by major browsers, CDNs, and an increasing number of backend servers. Adoption continues to grow.</p>
<h2 id="heading-data-formats-how-information-is-encoded">Data Formats: How Information Is Encoded</h2>
<p>Independent of which protocol carries data, systems need to agree on how data is encoded. The most important formats for API communication are JSON and Protocol Buffers.</p>
<h3 id="heading-json-the-universal-language">JSON: The Universal Language</h3>
<p>JSON (JavaScript Object Notation) was derived from JavaScript syntax and formalized as a standalone data format. Its design philosophy is human readability and simplicity.</p>
<p>A JSON object is a collection of key-value pairs enclosed in curly braces. Keys are always strings. Values can be strings, numbers, booleans, null, arrays, or other objects.</p>
<pre><code class="language-plaintext">{
  "id": "usr_001",
  "name": "John Smith",
  "age": 28,
  "is_verified": true,
  "scores": [98, 87, 92],
  "address": {
    "city": "Lagos",
    "country": "Nigeria"
  }
}
</code></pre>
<p>JSON became the dominant API data format for several reasons. It's human-readable: a developer can look at a JSON response in a browser's developer tools and immediately understand it. It maps naturally to data structures in virtually every programming language. It requires no special tooling or schema definition. And it's flexible: fields can be added or removed without necessarily breaking existing clients.</p>
<h3 id="heading-the-structural-cost-of-json">The Structural Cost of JSON</h3>
<p>JSON's human-readable design comes with a structural cost that becomes significant at scale.</p>
<p>Every field name is a string that travels over the network on every single response. In the example above, the strings <code>"is_verified"</code>, <code>"address"</code>, <code>"country"</code> aren't data. They're labels for data. They consume bytes, they must be tokenized and parsed, and they're repeated on every response for every user.</p>
<p>JSON is a text format, which means it must be parsed from text into the application's native data structures. This parsing isn't free: it requires allocating memory for strings, walking the text byte by byte to find delimiters, and constructing objects from the parsed values.</p>
<p>For a fintech platform with an internal API that returns a 1000-field response and is called by dozens of internal services millions of times per day, the cumulative cost of JSON's verbosity and parsing overhead becomes measurable in bandwidth bills and server CPU time.</p>
<p>JSON also has no formal schema at the network level. There's nothing in the JSON format itself that prevents a backend from changing <code>"account_balance"</code> to <code>"balance"</code>. The change compiles fine. The server deploys. Clients that depend on <code>"account_balance"</code> break silently at runtime.</p>
<h3 id="heading-xml-the-predecessor">XML: The Predecessor</h3>
<p>Before JSON, XML (eXtensible Markup Language) was the dominant data format for web services (used in SOAP, the predecessor to REST). XML is more verbose than JSON, wrapping every value in opening and closing tags:</p>
<pre><code class="language-plaintext">&lt;user&gt;
  &lt;id&gt;usr_001&lt;/id&gt;
  &lt;name&gt;John Smith&lt;/name&gt;
  &lt;age&gt;28&lt;/age&gt;
  &lt;is_verified&gt;true&lt;/is_verified&gt;
&lt;/user&gt;
</code></pre>
<p>XML has advantages: it supports schemas (XSD), namespaces, and complex document structures. It's still used in enterprise systems, document formats (DOCX, SVG, RSS), and configuration files. But for API communication, JSON's simplicity won.</p>
<h2 id="heading-rest-the-architecture-that-took-over-the-world">REST: The Architecture That Took Over the World</h2>
<p>REST (Representational State Transfer) was defined by Roy Fielding in his doctoral dissertation in 2000. Fielding was one of the principal authors of the HTTP specification, and REST emerged from his analysis of what made HTTP architecturally successful.</p>
<p>REST isn't a protocol. It's an architectural style: a set of constraints that, when applied to a distributed system, produce desired properties including scalability, simplicity, and modifiability.</p>
<h3 id="heading-the-six-rest-constraints">The Six REST Constraints</h3>
<p>Fielding defined six constraints that define a RESTful architecture. Most APIs described as "REST" implement a subset of these, which is why the term "RESTful" covers a wide spectrum.</p>
<p><strong>1. Client-Server:</strong> The client and server are separate concerns. The client manages the user interface. The server manages data storage and business logic. They evolve independently. This separation allows each to scale and change without affecting the other.</p>
<p><strong>2. Stateless:</strong> Each request from the client to the server must contain all the information needed to understand and process the request. The server doesn't store any session state between requests. If a client needs to be authenticated, the authentication information (typically a token) travels with every request.</p>
<p>Statelessness is what makes REST APIs horizontally scalable. Any server instance can handle any request because no session state needs to be co-located with the request. Load balancers can route requests freely.</p>
<p><strong>3. Cacheable:</strong> Responses must define themselves as cacheable or non-cacheable. If a response is cacheable, clients and intermediate layers (CDN, reverse proxies) can store and reuse the response without hitting the server.</p>
<p>Caching is one of the most powerful properties of REST. A well-designed REST API can serve millions of identical GET requests from CDN cache, with only a fraction ever reaching the origin server.</p>
<p><strong>4. Uniform Interface:</strong> The interface between client and server is standardized. Resources are identified by URIs. Resources are manipulated through representations. Messages are self-descriptive. This uniformity is what makes REST APIs universally accessible: a developer in any language can call a REST API using standard HTTP tooling.</p>
<p><strong>5. Layered System:</strong> The client doesn't need to know whether it's connected directly to the server or to an intermediary (load balancer, CDN, API gateway, caching proxy). Each layer only sees the layer it is interacting with. This enables transparent scaling and security.</p>
<p><strong>6. Code on Demand (Optional):</strong> Servers can extend client functionality by sending executable code (JavaScript). This is the only optional constraint and is the basis for how browsers work, but rarely relevant to API design.</p>
<h3 id="heading-resources-and-uris">Resources and URIs</h3>
<p>The central concept in REST is the resource. A resource is any piece of information that can be named, like a user, an order, a product, or a collection of transactions.</p>
<p>Resources are identified by URIs (Uniform Resource Identifiers). The URI identifies what the resource is, not what to do with it. The HTTP method expresses the operation.</p>
<pre><code class="language-plaintext">GET    /users           — retrieve all users
GET    /users/123       — retrieve user 123
POST   /users           — create a new user
PUT    /users/123       — replace user 123 entirely
PATCH  /users/123       — partially update user 123
DELETE /users/123       — delete user 123

GET    /users/123/orders        — orders belonging to user 123
POST   /users/123/orders        — create an order for user 123
GET    /users/123/orders/456    — order 456 belonging to user 123
</code></pre>
<p>The URI structure forms a hierarchy that reflects the relationships between resources. This makes APIs predictable: a developer who understands the resource model can guess the correct URIs.</p>
<h3 id="heading-why-rest-won">Why REST Won</h3>
<p>REST became the dominant architectural style for web APIs for reasons that go beyond technical merit:</p>
<p><strong>Universal accessibility:</strong> Any device, any language, any framework that can make an HTTP request can call a REST API. There's no special client library needed.</p>
<p><strong>HTTP alignment:</strong> REST leverages HTTP's existing infrastructure. CDN caching works for free. Load balancers understand HTTP. Monitoring tools speak HTTP. The entire ecosystem is built around HTTP semantics.</p>
<p><strong>Simplicity:</strong> A REST API can be designed, documented, and consumed with minimal tooling. A developer can test endpoints in a browser or with <code>curl</code> immediately.</p>
<p><strong>Developer experience:</strong> JSON over HTTP is something every web developer already understands. The learning curve is essentially zero.</p>
<p><strong>Ecosystem maturity:</strong> OpenAPI/Swagger provides standardized documentation. Postman provides testing. Every programming language has robust HTTP client libraries.</p>
<h3 id="heading-the-limits-of-rest">The Limits of REST</h3>
<p>REST's success is real. But so are its limitations, and understanding them is essential to knowing when to reach for something else.</p>
<h4 id="heading-overfetching-getting-more-than-you-need">Overfetching: Getting More Than You Need</h4>
<p>A REST endpoint returns a fixed shape of data. The <code>/users/123</code> endpoint returns the full user object: name, email, phone, address, preferences, account status, and thirty other fields.</p>
<p>A mobile screen that displays only the user's name and avatar must receive all of those fields to use two of them. The rest is waste: wasted bandwidth, serialization on the server, and deserialization on the client.</p>
<p>On a constrained mobile connection, this overfetching isn't just inefficient. It's a measurable degradation of user experience.</p>
<h4 id="heading-underfetching-not-getting-enough-at-once">Underfetching: Not Getting Enough at Once</h4>
<p>The opposite problem is equally common. A screen needs data from multiple resources: the user's profile, their recent orders, their notification count, and their account balance.</p>
<p>A REST API typically models these as separate endpoints. Loading this screen requires four separate HTTP requests, each with its own round-trip latency.</p>
<pre><code class="language-plaintext">GET /users/123         → profile data
GET /users/123/orders  → orders data
GET /notifications?user=123 → notification count
GET /accounts/123/balance   → balance data
</code></pre>
<p>Four sequential round trips. On a 200ms latency connection, that's 800ms of network time before the screen can render completely.</p>
<h4 id="heading-the-n1-problem">The N+1 Problem</h4>
<p>A common variant of underfetching: you fetch a list of resources, then must fetch additional data for each item in the list.</p>
<pre><code class="language-plaintext">GET /orders            → returns 20 orders (each with a user_id)
GET /users/1           → user for order 1
GET /users/2           → user for order 2
...
GET /users/20          → user for order 20
</code></pre>
<p>21 requests to load one screen. This pattern appears constantly in REST APIs and is addressed in various ways: including nested data in responses, adding query parameters to expand related resources, or creating purpose-built endpoints for specific screens.</p>
<p>All of these workarounds create tension: the API becomes less general as it's optimized for specific client needs.</p>
<h4 id="heading-no-native-real-time-support">No Native Real-Time Support</h4>
<p>REST is request-response. The client initiates every interaction. The server can never proactively push data.</p>
<p>Real-time features like live notifications, collaborative editing, and streaming data require either polling (inefficient), long-polling (complex), or a separate real-time technology bolted alongside the REST API.</p>
<h4 id="heading-the-documentation-drift-problem">The Documentation Drift Problem</h4>
<p>A REST API contract lives in documentation. Nothing in the HTTP protocol enforces that the documentation accurately reflects the API's actual behavior. As APIs evolve, documentation falls behind. Fields are renamed, types change, endpoints are deprecated. Clients built against outdated documentation break.</p>
<p>This isn't a theoretical problem. It's a daily reality in engineering teams where the backend and frontend evolve at different speeds.</p>
<h2 id="heading-graphql-letting-the-client-decide">GraphQL: Letting the Client Decide</h2>
<p>GraphQL was developed at Facebook starting in 2012 and open-sourced in 2015. Facebook built it to solve a specific problem: their mobile app needed to fetch complex, interconnected social data from a REST API, and the resulting overfetching and multiple round trips were degrading performance on mobile devices.</p>
<p>GraphQL's core insight is simple and radical: instead of the server deciding what data to return, let the client specify exactly what it needs.</p>
<h3 id="heading-the-query-language">The Query Language</h3>
<p>GraphQL is both a query language for APIs and a runtime for executing those queries. Rather than calling different endpoints for different data, all GraphQL requests go to a single endpoint (typically <code>/graphql</code>) and include a query that describes precisely what data is needed.</p>
<p>A GraphQL query for a user profile screen:</p>
<pre><code class="language-plaintext">query UserProfile {
  user(id: "usr_123") {
    name
    avatarUrl
    recentOrders(limit: 3) {
      id
      total
      status
      createdAt
    }
    notificationCount
  }
}
</code></pre>
<p>The response contains exactly and only the fields requested. Nothing more. If the client needs only <code>name</code> and <code>avatarUrl</code>, it requests only those two fields. The response contains only two fields.</p>
<h3 id="heading-mutations-and-subscriptions">Mutations and Subscriptions</h3>
<p>GraphQL has three operation types:</p>
<ol>
<li><p><strong>Queries</strong> fetch data. They're the GraphQL equivalent of GET requests.</p>
</li>
<li><p><strong>Mutations</strong> modify data: creating, updating, or deleting resources. They're the GraphQL equivalent of POST, PUT, PATCH, and DELETE.</p>
</li>
<li><p><strong>Subscriptions</strong> establish a persistent connection and push data in real-time when specified events occur. A subscription to <code>orderStatusChanged</code> receives a push every time any order's status changes. This is GraphQL's real-time capability, typically implemented over WebSockets.</p>
</li>
</ol>
<h3 id="heading-the-schema">The Schema</h3>
<p>Every GraphQL API is defined by a schema written in the Schema Definition Language (SDL). The schema declares every type, query, mutation, and subscription the API supports.</p>
<pre><code class="language-plaintext">type User {
  id: ID!
  name: String!
  email: String!
  orders: [Order!]!
  notificationCount: Int!
}

type Order {
  id: ID!
  total: Float!
  status: OrderStatus!
  createdAt: String!
}

enum OrderStatus {
  PENDING
  PROCESSING
  SHIPPED
  DELIVERED
}

type Query {
  user(id: ID!): User
  orders(userId: ID!, limit: Int): [Order!]!
}

type Mutation {
  createOrder(userId: ID!, items: [OrderItemInput!]!): Order!
}
</code></pre>
<p>The schema is introspectable: clients can query the schema itself to discover what types and operations are available. This enables powerful tooling: GraphQL IDEs can autocomplete queries, validate them against the schema before sending, and display documentation inline.</p>
<h3 id="heading-where-graphql-wins">Where GraphQL Wins</h3>
<p><strong>Precise data fetching:</strong> Clients request exactly what they need. Overfetching is eliminated by design.</p>
<p><strong>Single round trip for complex data:</strong> Data from multiple resources is fetched in a single request. The N+1 problem is solved at the query level rather than requiring the client to make multiple requests.</p>
<p><strong>Strongly typed schema:</strong> The schema is the contract. Clients can validate their queries against it at build time. Type mismatches are caught before deployment.</p>
<p><strong>Frontend agility:</strong> Frontend teams can evolve their data requirements without asking backend teams to create new endpoints. New screens, data combinations, and features are all handled by writing a new query.</p>
<p><strong>Excellent tooling:</strong> GraphiQL and Apollo Studio provide interactive schema exploration, query building, and performance analysis.</p>
<h3 id="heading-where-graphql-struggles">Where GraphQL Struggles</h3>
<p><strong>Query complexity:</strong> A malicious or poorly written query can request enormous amounts of nested data. A query that fetches every user, each user's orders, each order's items, and each item's product details can bring a server to its knees.</p>
<p>REST endpoints can be individually optimized. GraphQL requires query complexity analysis, depth limiting, and rate limiting to protect the server.</p>
<p><strong>Caching is harder:</strong> REST GET requests are cacheable at the HTTP level by default. GraphQL queries all go through POST requests to a single endpoint, breaking standard HTTP caching. Clients must implement their own caching (Apollo Client does this), but CDN-level caching is essentially unavailable for dynamic queries.</p>
<p><strong>Over-engineering simple APIs:</strong> If your API is straightforward CRUD operations with no complex data relationships and no mobile clients with aggressive data constraints, GraphQL's added setup cost exceeds its benefit.</p>
<p><strong>Real-time at scale is complex:</strong> GraphQL subscriptions work, but scaling WebSocket connections for thousands of concurrent subscribers is infrastructure-intensive and requires careful architecture.</p>
<p><strong>Error handling is non-standard:</strong> A GraphQL request can partially succeed: some fields resolve successfully while others fail. The response includes both data and errors simultaneously. Handling this gracefully requires more nuanced error handling logic than a simple HTTP status code.</p>
<h2 id="heading-websockets-when-http-is-not-enough">WebSockets: When HTTP Is Not Enough</h2>
<p>HTTP, in all its versions, is fundamentally request-response. The client speaks first. The server responds. The conversation ends. Even with HTTP/2's server push, the client initiates every new exchange.</p>
<p>But some applications genuinely need both sides to be able to speak at any moment, without waiting for the other to ask first. For example, a chat application where both parties send messages freely. A live collaborative document where every keystroke is broadcast to co-editors. An online game where the server pushes state updates as they happen and the client sends actions continuously.</p>
<p>For these cases, WebSockets provide a fundamentally different communication model.</p>
<h3 id="heading-the-websocket-handshake">The WebSocket Handshake</h3>
<p>A WebSocket connection starts as an HTTP request and then upgrades to a WebSocket connection. This upgrade mechanism means WebSockets work through existing HTTP infrastructure (firewalls, proxies, load balancers) without requiring special configuration.</p>
<p>The upgrade request:</p>
<pre><code class="language-plaintext">GET /chat HTTP/1.1
Host: api.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
</code></pre>
<p>The server confirms the upgrade:</p>
<pre><code class="language-plaintext">HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
</code></pre>
<p>Status code 101 means "Switching Protocols." From this point forward, the HTTP connection is replaced by a WebSocket connection. The protocol has changed. HTTP headers, status codes, and methods no longer apply.</p>
<h3 id="heading-full-duplex-persistent-communication">Full-Duplex, Persistent Communication</h3>
<p>The WebSocket connection is:</p>
<ul>
<li><p><strong>Full-duplex:</strong> both the client and server can send messages at any time, simultaneously, without waiting for the other to finish.</p>
</li>
<li><p><strong>Persistent:</strong> the connection stays open until explicitly closed by either party or until a network interruption occurs.</p>
</li>
<li><p><strong>Low overhead:</strong> once established, WebSocket messages have minimal framing overhead compared to HTTP. A small WebSocket message may have only 2 to 10 bytes of overhead, versus potentially hundreds of bytes of HTTP headers.</p>
</li>
</ul>
<pre><code class="language-plaintext">WebSocket connection open

Client: "Hello, I'm user 123"
Server: "Welcome, user 123"
Server: "User 456 just sent you a message: Hey!"
Client: "Thanks, here's my reply: Hi there!"
Server: "New notification: your payment was confirmed"
Client: "Great, show me my balance"
Server: "Your balance is NGN 500,000"
Server: "Another notification: transfer from user 789 received"

[Both sides communicate freely, at any time, simultaneously]
</code></pre>
<h3 id="heading-where-websockets-win">Where WebSockets Win</h3>
<p><strong>True real-time bidirectional communication</strong>: Applications where both client and server need to send messages at unpredictable times and at high frequency. For example, chat, live collaboration, multiplayer games, financial trading terminals.</p>
<p><strong>Low-latency messaging:</strong> Once the connection is established, message round-trip times can be in the single-digit milliseconds, limited only by network latency rather than connection setup overhead.</p>
<p><strong>Native browser support:</strong> The WebSocket API is built into every modern browser. No libraries are needed for the fundamental connection.</p>
<p><strong>Event-driven architecture on the client:</strong> WebSocket events (message, close, error) map naturally to event-driven client code.</p>
<h3 id="heading-where-websockets-struggle">Where WebSockets Struggle</h3>
<p><strong>Stateful connections:</strong> Each WebSocket connection must be maintained by a specific server instance. When scaling horizontally, a client connected to Server A can't receive messages from Server B without a shared pub/sub layer (like Redis) that all server instances publish to and subscribe from. This adds infrastructure complexity.</p>
<p><strong>No built-in request-response correlation:</strong> WebSockets are a message stream. If you send a message and expect a response, there's no built-in mechanism to correlate which response corresponds to which request. You have to build this yourself.</p>
<p><strong>No schema or contract:</strong> WebSockets send raw text or binary. The format of messages is defined entirely by the application. Two systems communicating over WebSockets must agree on message format out of band, in documentation, and there's nothing to enforce it at the connection level.</p>
<p><strong>Firewall and proxy complications:</strong> Some corporate networks and older proxies don't support the HTTP upgrade mechanism correctly, breaking WebSocket connections. This is less common than it was but still occurs in enterprise environments.</p>
<p><strong>Reconnection must be handled manually:</strong> WebSocket connections can drop due to network instability. Applications must implement reconnection logic, including managing state across reconnections.</p>
<h2 id="heading-server-sent-events-the-simpler-real-time-option">Server-Sent Events: The Simpler Real-Time Option</h2>
<p>Between REST's pure request-response and WebSocket's full bidirectional communication lies a middle option that most developers overlook: Server-Sent Events (SSE).</p>
<p>SSE establishes a one-directional persistent connection: the server pushes data to the client over a regular HTTP connection, and the client listens. The client can't send data back through the same connection.</p>
<h3 id="heading-how-sse-works">How SSE Works</h3>
<p>The client makes a standard HTTP GET request with an <code>Accept: text/event-stream</code> header:</p>
<pre><code class="language-plaintext">GET /notifications HTTP/1.1
Host: api.example.com
Accept: text/event-stream
Authorization: Bearer token123
</code></pre>
<p>The server responds with a 200 OK and keeps the connection open, periodically sending events:</p>
<pre><code class="language-plaintext">HTTP/1.1 200 OK
Content-Type: text/event-stream
Cache-Control: no-cache

data: {"type": "balance_update", "balance": 500000}

data: {"type": "transaction", "id": "txn_001", "amount": -5000}

event: notification
data: {"message": "Your transfer has been confirmed"}

id: 42
data: {"type": "order_status", "status": "shipped"}
</code></pre>
<p>Each event is separated by a blank line. Events can include a <code>data</code> field, an optional <code>event</code> type, and an optional <code>id</code> for resumability.</p>
<h3 id="heading-automatic-reconnection">Automatic Reconnection</h3>
<p>One of SSE's most practical features is automatic reconnection. If the connection drops, the browser automatically reconnects, sending the last received event ID in a <code>Last-Event-ID</code> header. The server can resume from that point, ensuring no events are missed.</p>
<h3 id="heading-where-sse-wins">Where SSE Wins</h3>
<p><strong>Simplicity:</strong> SSE works over plain HTTP. There's no protocol upgrade needed, and no special infrastructure. It works through every HTTP/2 connection, load balancer, and CDN that supports streaming.</p>
<p><strong>Native browser support:</strong> The <code>EventSource</code> API is built into every modern browser. Automatic reconnection is built in.</p>
<p><strong>Perfect for one-directional feeds:</strong> Live dashboards, notification streams, news feeds, real-time analytics, server logs: any scenario where the server pushes a continuous stream of updates and the client only reads.</p>
<p><strong>HTTP/2 multiplexing:</strong> Over HTTP/2, multiple SSE connections can share a single TCP connection. The browser connection limit that affected SSE over HTTP/1.1 doesn't apply.</p>
<p><strong>Natural fit for existing infrastructure:</strong> SSE responses are just HTTP responses. Existing load balancers, authentication middleware, and monitoring tools work without modification.</p>
<h3 id="heading-where-sse-struggles">Where SSE Struggles</h3>
<p><strong>One direction only:</strong> The client can't send data back through the SSE connection. For bidirectional scenarios, SSE isn't sufficient on its own.</p>
<p><strong>Text only (natively):</strong> SSE events are text. Binary data must be base64-encoded, adding overhead.</p>
<p><strong>No native support in all environments.</strong> SSE is a browser API. In other environments (mobile apps, server-to-server), it requires an HTTP client configured to handle streaming responses.</p>
<h3 id="heading-sse-vs-websockets-the-decision">SSE vs WebSockets: The Decision</h3>
<p>Choose SSE when the server pushes data and the client only reads: notifications, live feeds, dashboards, or streaming responses from an AI model. SSE is simpler, works over plain HTTP, and has automatic reconnection built in.</p>
<p>Choose WebSockets when both the client and server need to send messages freely and simultaneously: chat, collaborative editing, and games. The added complexity of WebSockets is justified when you genuinely need bidirectional communication.</p>
<h2 id="heading-protocol-buffers-a-new-language-for-data">Protocol Buffers: A New Language for Data</h2>
<p>Protocol Buffers (protobuf) is a binary serialization format developed by Google. Where JSON encodes data as human-readable text, protobuf encodes data as compact binary. This single difference has cascading implications for payload size, parsing speed, type safety, and schema enforcement.</p>
<h3 id="heading-the-schema-first-approach">The Schema-First Approach</h3>
<p>Unlike JSON, where you simply start writing key-value pairs, protobuf requires defining a schema first. You describe your data structures in a <code>.proto</code> file using Protocol Buffer Language, a language-agnostic schema definition language.</p>
<p>The schema definition:</p>
<pre><code class="language-plaintext">syntax = "proto3";

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  double balance = 4;
  bool is_verified = 5;
  int32 kyc_level = 6;
}

message Order {
  string id = 1;
  string user_id = 2;
  double total = 3;
  string status = 4;
  int64 created_at = 5;
}
</code></pre>
<p>Each field has a name and a type, as in any structured data format. But it also has a field number: the small integer after the equals sign. This field number is the key to protobuf's efficiency.</p>
<h3 id="heading-binary-encoding-why-field-numbers-matter">Binary Encoding: Why Field Numbers Matter</h3>
<p>When protobuf encodes data to binary, field names don't appear in the output. Instead, only the field number and the encoded value are written. Field 1 (id) becomes a tag byte indicating "field 1, type string" followed by the string's length and bytes. Field 4 (balance) becomes a tag byte indicating "field 4, type 64-bit float" followed by eight bytes of IEEE 754 double-precision float.</p>
<p>No <code>"id":</code> string, <code>"balance":</code> string, quotation marks, colons, or braces. Just field tags and values in a compact binary stream.</p>
<p>The same user object that occupies approximately 100 bytes in JSON occupies approximately 35 bytes in protobuf. For a 1000-field enterprise API response called millions of times per day, this difference translates directly to reduced bandwidth consumption and infrastructure cost.</p>
<p>Parsing binary is also fundamentally faster than parsing text. A binary parser reads a fixed-length tag, determines the type and length of the following value, reads that value, and moves to the next field. A JSON parser must tokenize a text stream character by character, handle escape sequences, infer types from value format, and construct a dynamic object from parsed key-value pairs.</p>
<p>On constrained devices or in high-throughput server-to-server communication, this parsing speed difference is meaningful.</p>
<h3 id="heading-code-generation-the-contract-comes-alive">Code Generation: The Contract Comes Alive</h3>
<p>The <code>.proto</code> schema file is the input to the <code>protoc</code> compiler. This compiler generates data classes in any supported language from the same schema definition.</p>
<p>The same <code>user.proto</code> file generates:</p>
<ul>
<li><p>A <code>User</code> class in Go for the backend server</p>
</li>
<li><p>A <code>User</code> class in Dart for the Flutter client</p>
</li>
<li><p>A <code>User</code> class in Python for the data processing service</p>
</li>
<li><p>A <code>User</code> class in TypeScript for the web frontend</p>
</li>
</ul>
<p>Every generated class has typed fields, serialization/deserialization methods, and equality comparison. There's no manual JSON parsing, type casting, or risk of field name typos. The compiler guarantees that every language's representation of a <code>User</code> is identical.</p>
<p>When the schema changes — a new field is added or a field is removed, for example — every team regenerates their classes. If the change is breaking (a required field removed or a type changed in an incompatible way), the compiler reports errors in every affected codebase. The problem is caught before any code reaches production.</p>
<h3 id="heading-schema-evolution-rules">Schema Evolution Rules</h3>
<p>Protobuf's field number system enables backward-compatible schema evolution. Because fields are identified by number rather than name, the following changes are safe:</p>
<ul>
<li><p>Adding a new field with a new number is always safe. Existing clients ignore fields they don't recognize. New clients receive the new field.</p>
</li>
<li><p>Removing a field by marking it as reserved is safe. Existing encoded data that contains the removed field is simply ignored when decoded. The field number must be marked reserved to prevent its reuse.</p>
</li>
<li><p>Renaming a field is safe. Names aren't encoded. Only the number matters at the binary level.</p>
</li>
<li><p>Changing a field's type in incompatible ways is unsafe and breaks existing encoded data.</p>
</li>
</ul>
<p>This evolution model means protobuf schemas can grow over time without coordinated updates across all clients and servers.</p>
<h3 id="heading-trade-offs">Trade-offs</h3>
<p>Protobuf's efficiency comes with costs that make it inappropriate for all contexts.</p>
<p>Binary data isn't human-readable. You can't open a protobuf response in a browser's developer tools and see what it contains. Debugging requires either decoding the binary with the schema or using specialized tools.</p>
<p>Protobuf also requires tooling. Every consumer of a protobuf-encoded API needs the schema and a protobuf library to decode it. For public APIs consumed by unknown third parties, this is a significant barrier. JSON requires nothing: every programming environment can parse it with built-in libraries.</p>
<p>Schema changes require coordination. When a schema changes, every consumer must update. For internal systems where you control all consumers, this is manageable. For public APIs, it requires versioning and migration strategies.</p>
<h2 id="heading-grpc-remote-procedure-calls-at-scale">gRPC: Remote Procedure Calls at Scale</h2>
<p>gRPC combines Protocol Buffers with HTTP/2 and Remote Procedure Call semantics to produce a framework for service-to-service communication that is faster, more structured, and more powerful than REST for specific use cases.</p>
<h3 id="heading-remote-procedure-calls-the-core-concept">Remote Procedure Calls: The Core Concept</h3>
<p>A Remote Procedure Call (RPC) framework makes calling a function on a remote server feel like calling a local function. Instead of constructing an HTTP request, serializing a body, parsing a response, and handling status codes, you call a function with typed arguments and receive a typed return value. The network communication is abstracted away.</p>
<pre><code class="language-plaintext">// Without RPC (manual REST)
const response = await http.post('/users', headers: {...}, body: json.encode(data));
const user = User.fromJson(json.decode(response.body));

// With RPC (gRPC)
final user = await userService.createUser(CreateUserRequest(name: "John", email: "john@example.com"));
</code></pre>
<p>The second form is simpler, type-safe, and requires no knowledge of HTTP methods, endpoints, or serialization formats.</p>
<h3 id="heading-the-four-communication-patterns">The Four Communication Patterns</h3>
<p>gRPC's most significant advantage over REST is its support for four distinct communication patterns, all defined in the same <code>.proto</code> schema and accessible through the same generated client.</p>
<p><strong>Unary RPC</strong> is the familiar request-response pattern. One request and one response. It's equivalent to a REST API call.</p>
<pre><code class="language-plaintext">Client ——— LoginRequest ——→ Server
Client ←—— LoginResponse —— Server
</code></pre>
<p><strong>Server Streaming RPC</strong> sends one request and receives a continuous stream of responses. The server pushes messages as they become available without the client needing to request each one.</p>
<pre><code class="language-plaintext">Client ——— WatchBalanceRequest ——→ Server
Client ←— BalanceResponse ———————— Server (balance: 500,000)
Client ←— BalanceResponse ———————— Server (balance: 495,000)
Client ←— BalanceResponse ———————— Server (balance: 1,000,000)
[Stream stays open, server pushes on every change]
</code></pre>
<p><strong>Client Streaming RPC</strong> sends a stream of messages to the server and receives one response at the end. The server processes all received messages and responds once.</p>
<pre><code class="language-plaintext">Client ——— DocumentChunk 1 ——→ Server
Client ——— DocumentChunk 2 ——→ Server
Client ——— DocumentChunk 3 ——→ Server
Client ←————— UploadResponse —— Server (all chunks processed)
</code></pre>
<p><strong>Bidirectional Streaming RPC</strong> allows both client and server to send streams of messages simultaneously, in any order.</p>
<pre><code class="language-plaintext">Client ——— ChatMessage ——→ Server
Server ←— ChatMessage ——— Client
Client ——— ChatMessage ——→ Server
Server ←— ChatMessage ——— Client  (server-initiated)
[Both sides communicate freely and simultaneously]
</code></pre>
<h3 id="heading-why-http2-and-protobuf-make-grpc-efficient">Why HTTP/2 and Protobuf Make gRPC Efficient</h3>
<p>gRPC's efficiency comes from the combination of its two underlying technologies working together.</p>
<p>HTTP/2's multiplexed persistent connections mean many concurrent gRPC calls, including long-running streaming calls, share a single connection. There's no connection setup overhead per call. Multiple streams proceed in parallel without blocking each other.</p>
<p>Protocol Buffer's binary encoding means payloads are compact and parsing is fast. A high-frequency service-to-service call that would transmit 100 bytes of JSON transmits 35 bytes of protobuf. At thousands of calls per second between microservices, this difference is significant.</p>
<p>The generated clients eliminate all serialization and deserialization code. The schema enforces that client and server agree on the contract. Breaking changes are caught by the compiler.</p>
<h3 id="heading-the-organizational-contract">The Organizational Contract</h3>
<p>In organizations using gRPC at scale, <code>.proto</code> files live in a dedicated repository separate from any individual service. This repository is the single source of truth for every service contract.</p>
<p>When an engineer wants to add a new field to an API, they open a pull request in the proto repository. Engineers from every affected team review it. The change is discussed, refined, and approved before any implementation begins. When it merges, every team regenerates their clients. Changes that break existing behavior are caught in code review, not in production.</p>
<p>This governance model transforms API evolution from a coordination problem into a code review process.</p>
<h3 id="heading-grpcs-limitations">gRPC's Limitations</h3>
<p>gRPC doesn't work natively in web browsers. Browsers can't directly make HTTP/2 requests with the necessary control required for gRPC. A proxy layer (gRPC-Web) is required to translate between gRPC-Web's browser-compatible format and standard gRPC. This adds infrastructure complexity and limits gRPC's applicability for browser-based clients.</p>
<p>gRPC also requires HTTP/2. Environments that don't support HTTP/2 can't use gRPC.</p>
<p>Binary encoding makes debugging harder as well. Inspecting gRPC traffic requires specialized tools and access to the proto schema.</p>
<p>For public APIs consumed by third-party developers, gRPC's tooling requirements are a higher barrier than REST's universally accessible JSON over HTTP.</p>
<h2 id="heading-the-complete-comparison">The Complete Comparison</h2>
<table>
<thead>
<tr>
<th></th>
<th>HTTP/1.1</th>
<th>HTTP/2</th>
<th>REST</th>
<th>GraphQL</th>
<th>WebSockets</th>
<th>SSE</th>
<th>gRPC</th>
</tr>
</thead>
<tbody><tr>
<td>Protocol</td>
<td>HTTP/1.1</td>
<td>HTTP/2</td>
<td>HTTP/1.1 or 2</td>
<td>HTTP/1.1 or 2</td>
<td>WebSocket</td>
<td>HTTP</td>
<td>HTTP/2</td>
</tr>
<tr>
<td>Data format</td>
<td>Any</td>
<td>Any</td>
<td>JSON (typical)</td>
<td>JSON</td>
<td>Any</td>
<td>Text</td>
<td>Protobuf (binary)</td>
</tr>
<tr>
<td>Communication</td>
<td>Request-Response</td>
<td>Request-Response</td>
<td>Request-Response</td>
<td>Request-Response + Subscriptions</td>
<td>Bidirectional</td>
<td>Server to Client</td>
<td>All four patterns</td>
</tr>
<tr>
<td>Contract</td>
<td>None</td>
<td>None</td>
<td>Documentation</td>
<td>Schema (SDL)</td>
<td>None</td>
<td>None</td>
<td>.proto file</td>
</tr>
<tr>
<td>Code generation</td>
<td>No</td>
<td>No</td>
<td>Optional</td>
<td>Optional</td>
<td>No</td>
<td>No</td>
<td>Mandatory</td>
</tr>
<tr>
<td>Real-time</td>
<td>No</td>
<td>Limited (push)</td>
<td>No (polling)</td>
<td>Subscriptions</td>
<td>Yes</td>
<td>Yes (one-way)</td>
<td>Yes (built-in)</td>
</tr>
<tr>
<td>Browser native</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No (needs proxy)</td>
</tr>
<tr>
<td>Caching</td>
<td>Excellent</td>
<td>Excellent</td>
<td>Excellent</td>
<td>Difficult</td>
<td>Not applicable</td>
<td>Not applicable</td>
<td>Not applicable</td>
</tr>
<tr>
<td>Payload size</td>
<td>Medium</td>
<td>Medium</td>
<td>Medium (JSON)</td>
<td>Medium (JSON)</td>
<td>Low overhead</td>
<td>Low overhead</td>
<td>Small (binary)</td>
</tr>
<tr>
<td>Human readable</td>
<td>Yes</td>
<td>No (binary frames)</td>
<td>Yes</td>
<td>Yes</td>
<td>Depends</td>
<td>Yes</td>
<td>No</td>
</tr>
<tr>
<td>Schema enforcement</td>
<td>None</td>
<td>None</td>
<td>None</td>
<td>Compile-time</td>
<td>None</td>
<td>None</td>
<td>Compile-time</td>
</tr>
</tbody></table>
<hr>
<h2 id="heading-how-to-choose-the-engineering-decision-framework">How to Choose: The Engineering Decision Framework</h2>
<p>No single communication approach is universally best. Each exists because it solves specific problems better than the alternatives. The engineering decision involves matching the tool to your requirements.</p>
<h3 id="heading-when-to-use-rest">When to Use REST</h3>
<p>Use REST when the API is public or consumed by third parties. REST's universal accessibility makes it the only reasonable choice for public APIs. Any developer in any language can call a REST API with standard HTTP tools. There are no schema files, generated clients, or special libraries.</p>
<p>REST is also a good fit when caching is a priority. REST GET responses can be cached at every layer: CDN, reverse proxy, and browser. For content that doesn't change frequently, REST with proper cache headers can serve millions of requests without hitting the origin server.</p>
<p>It's also solid when the operation is simple request-response. If you're building straightforward CRUD operations with no streaming requirements and no complex data relationships, REST is simpler to implement, document, and debug than any alternative.</p>
<p>And finally use REST when developer experience for the consumer matters. REST APIs are immediately accessible in a browser. They can be tested with <code>curl</code>. Every developer already understands them.</p>
<h3 id="heading-when-to-use-graphql">When to Use GraphQL</h3>
<p>Use GraphQL when multiple client types have significantly different data needs. A mobile app that needs minimal data for a list view and richer data for a detail view, alongside a desktop app that needs comprehensive data, are ideal GraphQL consumers. Each queries exactly what it needs.</p>
<p>GraphQL also works well for complex interconnected data with many relationships. Social graphs, product catalogs with deeply nested attributes, or content management systems with rich content relationships: GraphQL's ability to traverse relationships in a single query is a genuine advantage.</p>
<p>It's also a good choice for frontend teams that need to iterate quickly. When the frontend can evolve its data requirements without backend changes, development velocity increases. New screens, new data combinations, no new endpoints needed.</p>
<p>And finally, GraphQL works well if you're comfortable with the operational complexity. GraphQL requires query complexity protection, custom caching strategies, and more sophisticated error handling. These are worth the effort when the data fetching advantages are real.</p>
<h3 id="heading-when-to-use-websockets">When to Use WebSockets</h3>
<p>Use WebSockets when both the client and server need to send messages at any time. Genuine bidirectional real-time communication where either party can initiate a message at any moment.</p>
<p>WebSockets also work great for chat, collaboration, and games. Live chat applications, collaborative document editing, multiplayer real-time games are the canonical WebSocket use cases.</p>
<p>And WebSockets is a solid choice when low-latency messaging is critical. The minimal framing overhead and persistent connection make WebSockets the lowest-latency option for frequent message exchange.</p>
<h3 id="heading-when-to-use-server-sent-events">When to Use Server-Sent Events</h3>
<p>Use SSE when the server needs to push updates but the client only reads. Notification feeds, live dashboards, streaming AI responses, real-time analytics, or any scenario where the server has a continuous stream of data to deliver and the client only consumes.</p>
<p>SSE also works well when you value simplicity over full bidirectionality. SSE is significantly simpler to implement and operate than WebSockets for one-directional use cases. Automatic reconnection is built in. It works over plain HTTP.</p>
<h3 id="heading-when-to-use-grpc">When to Use gRPC</h3>
<p>Use gRPC when multiple internal services share the same contract. When several teams build services that call each other, a <code>.proto</code> schema enforced by the compiler prevents contract drift. Everyone generates their clients from the same source of truth.</p>
<p>gRPC also works well for high-frequency service-to-service communication. Two microservices exchanging thousands of calls per second benefit from protobuf's compact binary encoding and HTTP/2's persistent multiplexed connections.</p>
<p>It's also a solid choice for large payloads that are consumed by many internal systems. An internal enterprise API with hundreds of fields called by dozens of internal applications benefits enormously from protobuf's size reduction. Less bandwidth, less parsing overhead, and compiled contract enforcement.</p>
<p>gRPC also works great when low-bandwidth networks matter. For mobile applications in markets where network conditions are variable or constrained, protobuf's binary encoding reduces payload size by 3 to 10 times compared to JSON. The difference between a 15 kilobyte response and a 3 kilobyte response is the difference between a 3-second load and a sub-second load on a 2G connection.</p>
<p>And finally, use gRPC when streaming is a core requirement and you want one framework. gRPC's four communication patterns (unary, server streaming, client streaming, and bidirectional) cover every scenario without requiring separate WebSocket infrastructure alongside your API.</p>
<h3 id="heading-the-hybrid-reality">The Hybrid Reality</h3>
<p>Most sophisticated systems use multiple approaches, each where it genuinely wins:</p>
<pre><code class="language-plaintext">A Large Engineering Organization

Public REST API
  External developers, partners, open integrations
  JSON over HTTPS. OpenAPI documentation.
  CDN caching for frequently accessed resources.

Internal gRPC Network
  Service-to-service communication
  Auth service, payment service, notification service,
  fraud detection: all communicating with typed contracts
  over efficient binary protobuf on HTTP/2.

Real-Time Layer
  WebSockets for bidirectional features (live chat, collaboration)
  SSE for one-directional feeds (notifications, live dashboards)
  gRPC streaming for real-time data with typed contracts

Mobile API
  REST for standard operations (profile, settings, history)
  gRPC for high-frequency or large payload calls
  SSE for notification streaming
</code></pre>
<p>There's no architectural purity requirement. Each layer uses what fits its requirements. The discipline is in making these choices deliberately rather than by habit or default.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The history of how clients and servers communicate is the history of engineers discovering the limitations of existing tools and building better ones.</p>
<p>HTTP/1.1 gave us a universal request-response protocol that built the web. Its text-based format and sequential connection model worked well for the web of the 1990s and 2000s. As applications became more complex and performance expectations rose, its limitations became bottlenecks.</p>
<p>HTTP/2 rebuilt the transport layer with binary framing and multiplexing, eliminating head-of-line blocking at the HTTP level, compressing headers, and enabling server push. HTTP/3 took this further by replacing TCP with QUIC, addressing the remaining head-of-line blocking at the transport level and making connection establishment faster.</p>
<p>JSON became the dominant data format because of its human readability and universal support. Protocol Buffers emerged as an alternative for contexts where JSON's verbosity and lack of schema enforcement create real problems: internal services, high-frequency communication, constrained networks, and teams needing compile-time contract enforcement.</p>
<p>REST codified HTTP's architectural strengths into a style that made APIs universally accessible and HTTP-native. Its success wasn't purely technical: it aligned with what developers already understood and what the HTTP ecosystem already supported. Its limitations in data fetching efficiency and real-time communication opened the door for GraphQL and streaming alternatives.</p>
<p>GraphQL solved REST's overfetching and underfetching problems by inverting control: the client specifies exactly what it needs. WebSockets solved REST's inability to support genuine bidirectional real-time communication. Server-Sent Events provided a simpler real-time option for one-directional streaming. gRPC combined Protocol Buffers, HTTP/2, and RPC semantics into a framework that excels at typed service-to-service communication at scale.</p>
<p>Understanding all of these tools, along with why each was built, what problem it solves, and where it struggles, is what enables you to make deliberate architectural decisions rather than defaulting to whatever is most familiar.</p>
<p>The right communication approach is always the one that fits the specific requirements of the system you're building: the clients consuming it, the data being exchanged, the network conditions it operates in, the teams building and maintaining it, and the operational complexity you are prepared to manage.</p>
<p>That clarity of fit is what engineering judgment looks like in practice.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A Developer’s Guide to Proxy Servers ]]>
                </title>
                <description>
                    <![CDATA[ Every time you open a website, your device talks directly to another server on the internet.  Your IP address, location, and basic network details are visible to that server.  In many cases, this is fine. But there are situations where you may want m... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/a-developers-guide-to-proxy-servers/</link>
                <guid isPermaLink="false">695db23365ab0e59d902fa64</guid>
                
                    <category>
                        <![CDATA[ proxy ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Security ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server ]]>
                    </category>
                
                    <category>
                        <![CDATA[ computer networking ]]>
                    </category>
                
                    <category>
                        <![CDATA[ networking ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Wed, 07 Jan 2026 01:09:07 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767748085260/ef495b53-f484-4f55-af29-57432aaf1dba.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Every time you open a website, your device talks directly to another server on the internet. </p>
<p>Your IP address, location, and basic network details are visible to that server. </p>
<p>In many cases, this is fine. But there are situations where you may want more control over how your requests travel across the internet. This is where proxies come in.</p>
<p>A <a target="_blank" href="https://www.geeksforgeeks.org/computer-networks/what-is-proxy-server/">proxy</a> acts as an intermediary between you and the internet. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1767634042506/560a0ace-c42e-4810-b5d1-fbb9a1a6a246.png" alt="How Proxy Works" class="image--center mx-auto" width="1000" height="600" loading="lazy"></p>
<p>Instead of your device connecting directly to a website, it sends the request to a proxy server. The proxy then forwards the request on your behalf and sends the response back to you. </p>
<p>From the website’s point of view, it’s the proxy that is making the request, not you.</p>
<p>Proxies are used for privacy, security, performance, testing, automation, and access control. They are common in companies, data centers, scraping systems, and even home networks. </p>
<p>To understand why proxies matter, it helps to first understand how internet requests normally work.</p>
<h2 id="heading-what-well-cover"><strong>What We’ll Cover</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-how-internet-requests-work-without-a-proxy">How internet requests work without a proxy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-types-of-proxies">Types of proxies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-proxies-vs-vpns">Proxies vs VPNs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-using-a-proxy-in-python">Using a proxy in Python</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-proxy-use-cases">Proxy Use Cases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-proxies-affect-performance-and-reliability">How proxies affect performance and reliability</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-proxies-are-detected-and-blocked">How proxies are detected and blocked</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security-considerations-when-using-proxies">Security considerations when using proxies</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-how-internet-requests-work-without-a-proxy"><strong>How Internet Requests Work Without a Proxy</strong></h2>
<p>When you type a website address into your browser, your computer resolves the domain name to an IP address using DNS. It then opens a connection directly to that server. </p>
<p>Your IP address is included as part of the network connection so the server knows where to send the response.</p>
<p>The server can log your IP address, infer your location, detect your network provider, and apply rules based on that information. Some websites restrict access by country. </p>
<p>Others rate-limit or block traffic from specific IP ranges. In automated systems, repeated requests from the same IP are often flagged as suspicious.</p>
<p>Without a proxy, all of this traffic is directly tied to your device or server. There is no separation layer.</p>
<h2 id="heading-types-of-proxies"><strong>Types of Proxies</strong></h2>
<p>Proxies come in several forms, each designed for different scenarios.</p>
<p><a target="_blank" href="https://www.zscaler.com/resources/security-terms-glossary/what-is-forward-proxy">Forward proxies</a> are the most common. These are used by clients to access external resources. Corporate networks often use forward proxies to control employee internet access.</p>
<p><a target="_blank" href="https://www.cloudflare.com/learning/cdn/glossary/reverse-proxy/">Reverse proxies</a> work in the opposite direction. They sit in front of servers rather than clients. Websites use reverse proxies to load balance traffic, terminate TLS, and protect backend systems.</p>
<p>Transparent proxies operate without explicit client configuration. They intercept traffic at the network level. These are often used by ISPs or enterprise networks.</p>
<p>Residential, datacenter, and mobile proxies differ based on where their IP addresses come from. Residential and mobile proxies appear like real user devices, while datacenter proxies come from cloud providers.</p>
<h2 id="heading-proxies-vs-vpns"><strong>Proxies vs VPNs</strong></h2>
<p>Proxies and VPNs are often confused, but they solve different problems. A proxy usually works at the application level. You configure a browser, script, or tool to use a proxy, and only that traffic goes through it.</p>
<p>A VPN works at the operating system or network level. Once connected, all traffic from your device is routed through the <a target="_blank" href="https://www.paloaltonetworks.com/cyberpedia/what-is-a-vpn-tunnel">VPN tunnel</a> by default. This includes browsers, apps, and background services.</p>
<p>Another difference is encryption. Most VPNs encrypt traffic between your device and the VPN server. Many proxies don’t, unless you’re using HTTPS or a secure proxy protocol.</p>
<p>People sometimes compare proxies to a <a target="_blank" href="https://nordvpn.com/">free VPN</a>, especially when the goal is hiding an IP address. While both can change your apparent location, a proxy is usually more lightweight and task-specific. A VPN is better when you want system-wide privacy, but it comes with more overhead and less fine-grained control.</p>
<p>For developers and automation systems, proxies are often preferred because they are easier to rotate, cheaper at scale, and simpler to integrate into code.</p>
<h2 id="heading-using-a-proxy-in-python"><strong>Using a Proxy in Python</strong></h2>
<p>Using a proxy in Python is straightforward, especially with popular libraries like <code>requests</code>. Below is a simple example that sends an HTTP request through a proxy.</p>
<p>To get a proxy URL, you can either build your own proxy using open-source solutions like <a target="_blank" href="https://www.manageengine.com/products/firewall/tech-topics/what-is-squid-proxy.html">SquidProxy</a> or buy a third-party service that charges per GB of traffic. Here is a list of <a target="_blank" href="https://www.geeksforgeeks.org/websites-apps/best-residential-proxy-providers/">popular proxy providers</a>. </p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> requests  <span class="hljs-comment"># Import the requests library to make HTTP requests</span>

<span class="hljs-comment"># Proxy URL with authentication details</span>
<span class="hljs-comment"># Format: protocol://username:password@host:port</span>
proxy_url = <span class="hljs-string">"http://username:password@proxy_host:proxy_port"</span>


<span class="hljs-comment"># Define proxy settings for both HTTP and HTTPS traffic</span>
<span class="hljs-comment"># Requests will route all outgoing traffic through this proxy</span>
proxies = {
   <span class="hljs-string">"http"</span>: proxy_url,
   <span class="hljs-string">"https"</span>: proxy_url
}

<span class="hljs-comment"># Make a GET request to httpbin.org, which returns the IP address</span>
<span class="hljs-comment"># This helps verify whether the request is going through the proxy</span>
response = requests.get(
   <span class="hljs-string">"https://httpbin.org/ip"</span>,  <span class="hljs-comment"># Test endpoint that echoes the client IP</span>
   proxies=proxies,          <span class="hljs-comment"># Apply the proxy configuration</span>
   timeout=<span class="hljs-number">10</span>                <span class="hljs-comment"># Fail the request if it takes more than 10 seconds</span>
)

<span class="hljs-comment"># Print the response body</span>
<span class="hljs-comment"># If the proxy is working, the IP shown here will be the proxy's IP, not yours</span>
print(response.text)
</code></pre>
<p>In this example, the requests library sends the outbound request to the proxy instead of directly to the website. The website sees the proxy’s IP address. The response shows which IP was used, making it easy to verify that the proxy is working.</p>
<p>This same pattern applies to APIs, scrapers, and internal tools. More advanced setups rotate proxies per request or per session.</p>
<h2 id="heading-proxy-use-cases"><strong>Proxy Use Cases</strong></h2>
<p>One of the most common reasons to use a proxy is IP masking. By routing traffic through a proxy, your real IP address is hidden from the destination server. This is useful for privacy, security testing, and bypassing IP-based restrictions.</p>
<p>Proxies are also used for geographic routing. If a service behaves differently in different countries, a proxy located in a specific region lets you see what users there experience.</p>
<p>In automation and scraping systems, proxies are essential. Sending thousands of requests from a single IP is a fast way to get blocked. Rotating proxies distribute traffic across many IPs, reducing detection.</p>
<p>Companies use proxies to monitor, filter, and log outbound traffic. This helps with compliance, security, and performance optimisation.</p>
<h2 id="heading-how-proxies-affect-performance-and-reliability"><strong>How Proxies Affect Performance and Reliability</strong></h2>
<p>Adding a proxy introduces an extra network hop, which can increase latency. A well-located, high-quality proxy can still be fast, but performance depends heavily on proxy capacity and distance.</p>
<p>Proxies can also improve performance in some cases. Caching proxies store responses and serve them locally for repeated requests. This reduces load on upstream servers and speeds up access.</p>
<p>Reliability depends on proxy health. If a proxy goes down, all traffic routed through it fails. This is why production systems often use proxy pools and health checks to automatically switch between proxies.</p>
<h2 id="heading-how-proxies-are-detected-and-blocked"><strong>How Proxies Are Detected and Blocked</strong></h2>
<p>Websites often try to detect proxy usage. They analyse IP reputation, request patterns, headers, and behavioural signals. Datacenter proxies are easier to detect because their IP ranges are well-known.</p>
<p>Some proxies leak information through headers that reveal the original client IP. Poorly configured proxies are especially easy to spot.</p>
<p>To reduce detection, systems rotate IPs, randomise headers, simulate real browser behaviour, and use residential or mobile proxies. Detection and evasion is an ongoing arms race between websites and proxy users.</p>
<h2 id="heading-security-considerations-when-using-proxies"><strong>Security Considerations When Using Proxies</strong></h2>
<p>Not all proxies are trustworthy. When you route traffic through a proxy, that proxy can see your requests and responses. This means sensitive data should only be sent over encrypted connections.</p>
<p>Public or free proxies often log traffic, inject ads, or behave unpredictably. For serious use cases, dedicated or private proxies are safer.</p>
<p>In corporate environments, proxies are part of the security model. They enforce policies, block malicious destinations, and provide audit logs. In these cases, the proxy is a defensive tool rather than a privacy tool.</p>
<h2 id="heading-conclusion"><strong>Conclusion</strong></h2>
<p>A proxy is a simple but powerful concept. By inserting an intermediary between a client and the internet, proxies change how requests appear, how traffic is controlled, and how systems scale.</p>
<p>They are used for privacy, testing, automation, compliance, and performance. While they are often mentioned alongside VPNs, proxies offer more targeted control and flexibility, especially for developers and infrastructure teams.</p>
<p>Understanding how proxies work at a request level helps you decide when to use them, how to configure them safely, and how to design systems that rely on them. Whether you are building a scraper, testing geo-specific behavior, or managing outbound traffic, proxies remain a core building block of the modern internet.</p>
<p><em>Hope you enjoyed this article. Find me on</em> <a target="_blank" href="https://linkedin.com/in/manishmshiva"><em>Linkedin</em></a> <em>or</em> <a target="_blank" href="https://manishshivanandhan.com/"><em>visit my website</em></a><em>.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ VPS vs PaaS: How to Choose a Hosting Solution ]]>
                </title>
                <description>
                    <![CDATA[ If you’ve ever stared at a dozen hosting plans, not sure which one to choose, you’re not alone. Hosting isn’t one-size-fits-all, and knowing the difference between a VPS (Virtual Private Server) and a PaaS (Platform as a Service) can help you pick so... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/vps-vs-paas-how-to-choose-a-hosting-solution/</link>
                <guid isPermaLink="false">687fca00b102539f23984a03</guid>
                
                    <category>
                        <![CDATA[ hosting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server ]]>
                    </category>
                
                    <category>
                        <![CDATA[ PaaS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ vps ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud Computing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Manish Shivanandhan ]]>
                </dc:creator>
                <pubDate>Tue, 22 Jul 2025 17:27:28 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1753205132683/65ed718f-a68e-4e31-8db3-cf9265e50817.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you’ve ever stared at a dozen hosting plans, not sure which one to choose, you’re not alone. Hosting isn’t one-size-fits-all, and knowing the difference between a VPS (Virtual Private Server) and a PaaS (Platform as a Service) can help you pick something that works for your project.</p>
<p>Let’s break them down clearly. We’ll go through VPS and PaaS in detail in terms of scaling, pricing, control, and so on. Each handles hosting very differently, and by the end of this guide, you’ll know exactly which solution fits your workflow better.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-vps">What is a VPS?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-a-paas">What is a PaaS?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-control-and-customization">Control and Customisation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-setup-and-deployment">Setup and Deployment</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-scaling">Scaling</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-maintenance-and-updates">Maintenance and Updates</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-performance">Performance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security">Security</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-pricing">Pricing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-when-to-use-each">When to Use Each</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-summary">Summary</a></p>
</li>
</ul>
<h2 id="heading-what-is-a-vps">What is a VPS?</h2>
<p>VPS stands for <a target="_blank" href="https://cloud.google.com/learn/what-is-a-virtual-private-server">Virtual Private Server</a>. Think of it as your own slice of a physical server.</p>
<p>Unlike shared hosting, where you compete for resources, a VPS gives you isolated computing power, dedicated RAM, CPU, and storage that’s all yours.</p>
<p>It acts like a mini datacenter. You gain root access, allowing you to install any OS (such as Ubuntu or CentOS), run custom applications, set up cron jobs, configure firewall rules, and essentially shape the environment as you see fit. It’s flexible, affordable, and powerful, and ideal for developers who want control without the complexity of managing bare-metal hardware.</p>
<h2 id="heading-what-is-a-paas">What is a PaaS?</h2>
<p>PaaS stands for <a target="_blank" href="https://azure.microsoft.com/en-us/resources/cloud-computing-dictionary/what-is-paas">Platform as a Service</a>. It’s a cloud-based environment that lets you build, deploy, and scale applications without worrying about infrastructure.</p>
<p>Instead of provisioning servers or managing software stacks, you simply write your code, connect your Git repository, and hit deploy. The platform takes care of everything from building your app, routing traffic, provisioning SSL, scaling services, and monitoring health. It’s DevOps on autopilot.</p>
<p>PaaS solutions are built for speed and simplicity. They support modern languages and frameworks out of the box and offer smart features like auto-scaling, built-in CI/CD, and usage-based pricing.</p>
<p>Now let’s look at the main differences between the two options so you can decide which is best for your use case.</p>
<h2 id="heading-control-and-customisation"><strong>Control and Customisation</strong></h2>
<p>A VPS gives you full control. It’s your server, your rules. </p>
<p>You get root access, pick your OS, install whatever software you need, and tweak system settings to your liking. VPS solutions makes this easy by letting you deploy clean server images quickly like Ubuntu, Debian, Redhat or whatever suits you. Then it’s all in your hands.</p>
<p>PaaS, on the other hand, limits a bit of that flexibility in exchange for convenience. PaaS abstracts the system layer away completely and often comes with support which is handy if you need help. </p>
<p>You write code, push to a Git repo, and it takes care of the rest. It supports popular languages and frameworks, but if you need a very specific runtime or library, you might hit a wall.</p>
<p>If you like being in control, VPS wins here. If you’d rather avoid infrastructure altogether, PaaS is your solution. </p>
<h2 id="heading-setup-and-deployment"><strong>Setup and Deployment</strong></h2>
<p>Getting a VPS up and running takes more effort. You’ll start by provisioning a server, then SSH in to install packages, configure firewalls, set up your web server, and deploy your code manually or via tools like <a target="_blank" href="https://www.freecodecamp.org/news/the-docker-handbook/">Docker</a>.</p>
<p>With PaaS, setup is nearly instant. You connect your GitHub or GitLab account, select your repo, and click deploy. It handles building, routing, SSL certificates, and launching the app, all within minutes. No SSH, no terminal commands, no surprises.</p>
<p>So if you want fast and repeatable deployments, PaaS is the smoother ride. If you’re okay spending more time upfront to craft your ideal setup, VPS gives you the flexibility.</p>
<h2 id="heading-scaling"><strong>Scaling</strong></h2>
<p>Scaling is one of the biggest advantages of PaaS. When your app traffic increases, it can spin up more containers or instances automatically. </p>
<p>You don’t have to predict resource needs ahead of time. Your app scales with demand and scales back down to save money when things quiet down.</p>
<p>With a VPS, scaling is more manual. You have to monitor usage and upgrade your server or configure load balancers yourself. Some developers enjoy this level of control, especially when optimising resource use. But it can be a headache during unexpected traffic spikes.</p>
<p>If your app is likely to grow or experience unpredictable load, PaaS gives you peace of mind. If your traffic is steady and predictable, VPS can handle it just fine, especially if you’re comfortable managing the growth yourself.</p>
<h2 id="heading-maintenance-and-updates"><strong>Maintenance and Updates</strong></h2>
<p>VPS means you’re in charge of everything under the hood. That includes system updates, security patches, disk usage, and log rotation. You also need to manage backups, monitoring, and anything else that keeps your app healthy and online.</p>
<p>PaaS removes that burden. The platform takes care of OS-level updates, security patches, and even restarts or auto-heals when something goes wrong. You get built-in monitoring and automatic backups, and logs are available right from the dashboard.</p>
<p>If maintenance isn’t your strong suit, or just not how you want to spend your valuable time, PaaS clearly comes out ahead.</p>
<h2 id="heading-performance"><strong>Performance</strong></h2>
<p>With a VPS, you get guaranteed resources. They offers dedicated CPU cores and RAM that only your apps use. You can fine-tune performance at every level, from <a target="_blank" href="https://www.freecodecamp.org/news/the-nginx-handbook/">Nginx</a> config files to memory usage. But I would recommend that you read the provider’s fine print and service terms as dedicated resources are not always fully dedicated.</p>
<p>PaaS solutions often run apps in shared or containerised environments. They manage performance for you and isolate workloads, but you might not have the same raw consistency as with a dedicated VPS, especially under heavy compute loads.</p>
<p>For apps that demand consistent high performance, like an online streaming service, a VPS is often the better choice. For most typical web apps, PaaS delivers more than enough speed and stability.</p>
<h2 id="heading-security"><strong>Security</strong></h2>
<p>In a VPS, security is your responsibility. That includes setting up firewalls, securing SSH access, managing user roles, and keeping the OS up to date. VPS gives you the tools, but it’s up to you to use them correctly.</p>
<p>PaaS handles most security concerns automatically, including <a target="_blank" href="https://www.freecodecamp.org/news/protect-against-ddos-attacks/">DDoS protection</a>. It provides HTTPS out of the box, isolates apps from each other, and keeps the platform patched and hardened. While you’re still responsible for securing your app code, you don’t have to worry about the infrastructure.</p>
<p>If security isn’t your strong point, or you want to reduce risk, PaaS adds a safety net. For experienced sysadmins, VPS offers the flexibility to build your own defenses.</p>
<h2 id="heading-pricing"><strong>Pricing</strong></h2>
<p>VPS pricing may appear more affordable at first glance. A VPS server with 4 GB RAM and 80 GB SSD might only set you back $10-15 per month. But that price is fixed, whether your app is serving ten users or ten thousand. And when you outgrow that plan, scaling means resizing the server or juggling additional machines.</p>
<p>PaaS platforms take a different approach. Instead of paying for fixed resources you may or may not use, you pay for what you actually consume. If your app gets minimal traffic, your costs stay low. But if usage spikes, PaaS scales your resources to match, without downtime or manual effort. You’re billed based on activity, not guesswork.</p>
<p>This makes PaaS a better long-term deal for most modern apps. You’re not locked into static hardware. You don’t have to overpay just to be “safe.” And as your app scales, your infrastructure scales with it automatically. </p>
<p>But keep in mind that since PaaS platforms scale automatically based on demand, a sudden spike in traffic can lead to unexpectedly high costs. To avoid surprise bills, make sure to set up pricing alerts and usage thresholds. Most PaaS providers offer these features to help you stay in control of your budget.</p>
<h2 id="heading-when-to-use-each"><strong>When to Use Each</strong></h2>
<p>Use a VPS if you need complete control, want to host multiple apps on one server, or have special requirements around software, performance, or system-level configuration. </p>
<p><a target="_blank" href="https://www.hetzner.com/">Hetzner</a> is a great choice when you want a solid server at a good price and are comfortable managing it yourself. It offers powerful virtual servers with full root access, making it a favorite among developers who want total control. If you’re comfortable managing your own infrastructure, Hetzner gives you the tools and flexibility to build exactly what you need.</p>
<p>Choose PaaS if you want to move fast, avoid infrastructure headaches, and focus purely on coding. PaaS lets you deploy and scale apps with minimal effort, which makes it ideal for teams that want to spend more time building and growing their business than managing. </p>
<p><a target="_blank" href="https://sevalla.com/">Sevalla</a> is a modern PaaS built for speed and simplicity. It handles everything from deployments to scaling, so you can focus entirely on writing code. With smart usage-based pricing and built-in automation, Sevalla is ideal for developers who want to move fast without managing servers or infrastructure.</p>
<h2 id="heading-summary"><strong>Summary</strong></h2>
<p>There’s no one-size-fits-all answer when choosing between VPS and PaaS. It depends on your priorities, whether you care more about control or convenience, price or speed, flexibility or simplicity.</p>
<p>A VPS gives you a clean slate and full power under the hood. It’s ideal for experienced developers and sysadmins who want to build their environment from the ground up.</p>
<p>A PaaS offering gives you the tools to deploy fast, scale effortlessly, and skip the DevOps. It’s perfect if you’d rather write code than manage servers.</p>
<p>Hope you enjoyed this article. <a target="_blank" href="https://linkedin.com/in/manishmshiva">Connect with me</a> on LinkedIn or <a target="_blank" href="https://manishshivanandhan.com/">visit my website</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Connect Your AWS EC2 Instance to VS Code ]]>
                </title>
                <description>
                    <![CDATA[ As a DevOps engineer, it is crucial to master at least one cloud provider. Cloud services simplify storage, data migration, and CI/CD workflows and help make these tasks easier and more efficient. If you need a basic introduction to cloud computing, ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-connect-your-aws-ec2-instance-to-vs-code/</link>
                <guid isPermaLink="false">67e2ec52cd467794ee79d63e</guid>
                
                    <category>
                        <![CDATA[ ec2 ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AWS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ software development ]]>
                    </category>
                
                    <category>
                        <![CDATA[ ssh ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Cloud ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Ijeoma Igboagu ]]>
                </dc:creator>
                <pubDate>Tue, 25 Mar 2025 17:48:02 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1742397603245/c1ca0496-dbab-4570-8b6b-cb4bac5f72c1.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>As a DevOps engineer, it is crucial to master at least one cloud provider. Cloud services simplify storage, data migration, and CI/CD workflows and help make these tasks easier and more efficient.</p>
<p>If you need a basic introduction to cloud computing, here’s a beginner-friendly tutorial for you: <a target="_blank" href="https://www.freecodecamp.org/news/cloud-computing-guide-for-beginners/"><strong>What is Cloud Computing? A Guide for Beginners.</strong></a></p>
<p>In this guide, I’ll show you how to create an AWS EC2 instance. This is one of AWS’s top services for building applications. By the end of this guide, you'll know how to launch an AWS EC2 instance and connect it to VS Code.</p>
<h2 id="heading-table-of-contents"><strong>Table of Contents</strong></h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-what-is-an-aws-ec2-instance">What is an AWS EC2 Instance?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-why-connect-your-aws-ec2-instance-to-vs-code">Why Connect Your AWS EC2 Instance to VS Code?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-launch-and-connect-your-aws-ec2-instance-to-vs-code">How to Launch and Connect Your AWS EC2 Instance to VS Code</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-step-1-create-an-aws-ec2-instance">Step 1: Create an AWS EC2 Instance</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-2-connect-the-aws-ec2-instance-to-your-code-editor">Step 2: Connect the AWS EC2 Instance to Your Code Editor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-3-install-the-programming-language">Step 3: Install the Programming Language</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-open-a-remote-window">Step 4: Open a Remote Window</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-step-5-access-your-project-folder">Step 5: Access Your Project Folder</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before you start, make sure you have:</p>
<ul>
<li><p>An AWS account. If you do not have one, <a target="_blank" href="https://aws.amazon.com/free/?gclid=Cj0KCQiAvvO7BhC-ARIsAGFyToVguvjmSCa99VkB7XsHepginSELSYCCYnVzZXeZSKFpRRTC8DKyh98aAkZkEALw_wcB&amp;trk=2d3e6bee-b4a1-42e0-8600-6f2bb4fcb10c&amp;sc_channel=ps&amp;ef_id=Cj0KCQiAvvO7BhC-ARIsAGFyToVguvjmSCa99VkB7XsHepginSELSYCCYnVzZXeZSKFpRRTC8DKyh98aAkZkEALw_wcB:G:s&amp;s_kwcid=AL!4422!3!645125273261!e!!g!!aws!19574556887!145779846712&amp;all-free-tier.sort-by=item.additionalFields.SortRank&amp;all-free-tier.sort-order=asc&amp;awsf.Free%20Tier%20Types=*all&amp;awsf.Free%20Tier%20Categories=*all">sign up here</a>.</p>
</li>
<li><p>A GitHub repository with your source code. If you don’t have a GitHub account, <a target="_blank" href="https://github.com/">sign up here</a>.</p>
</li>
<li><p>Basic knowledge of web development and version control.</p>
</li>
<li><p>A code editor. For this tutorial, I’m using VS Code.</p>
</li>
</ul>
<p>Let’s jump right in!</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1735997217784/fdb3b399-7a07-4cf2-8577-10859bf5542d.gif" alt="fdb3b399-7a07-4cf2-8577-10859bf5542d" class="image--center mx-auto" width="220" height="220" loading="lazy"></p>
<h2 id="heading-what-is-an-aws-ec2-instance">What is an AWS EC2 Instance?</h2>
<p>AWS EC2 (Elastic Compute Cloud) allows you to run virtual machines in the cloud. These computers allow you to run your applications without needing physical hardware.</p>
<p>There are a number of things you can you do with AWS EC2, such as hosting websites or apps, running big data or machine-learning tasks, creating testing environments, and handling tasks that need flexible, scalable computing power.</p>
<h2 id="heading-why-connect-your-aws-ec2-instance-to-vs-code">Why Connect Your AWS EC2 Instance to VS Code?</h2>
<p>Connecting your AWS EC2 instance to VS Code is helpful for several reasons. Before we start the setup process, it’s important to learn why it’s beneficial.</p>
<ol>
<li><p>Using VS Code provides a familiar and efficient development space. It feels like coding on your own machine.</p>
</li>
<li><p>You don’t have to log into your AWS EC2 instance each time. You can edit files, run commands, and debug code from a distance.</p>
</li>
<li><p>You can streamline your workflow with built-in terminal access and extensions. This way, you won't have to switch between SSH clients all the time.</p>
</li>
<li><p>You can push changes to GitHub. This makes working together and deploying much smoother.</p>
</li>
<li><p>VS Code works well with Java, Node.js, and Python. It supports many languages and frameworks, so it's great for cloud development.</p>
</li>
</ol>
<p>Now that you understand the benefits, let’s move on to setting up the connection.</p>
<h2 id="heading-how-to-launch-and-connect-your-aws-ec2-instance-to-vs-code"><strong>How to Launch and Connect Your AWS EC2 Instance to VS Code</strong></h2>
<p>To launch an EC2 instance on AWS, just follow these steps:</p>
<h3 id="heading-step-1-create-an-aws-ec2-instance"><strong>Step 1: Create an AWS EC2 Instance</strong></h3>
<p>First, log into your AWS account. Then, use the search bar to find EC2 and select it.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736016609765/f784db8e-46cc-4e03-abc0-7bdea9b1c668.png" alt="Searching for EC2 on AWS Console" class="image--center mx-auto" width="1920" height="970" loading="lazy"></p>
<p>Click EC2 and follow the on-screen instructions to create a new instance.</p>
<ol>
<li><p><strong>Choose an AMI (Amazon Machine Image):</strong> This is a pre-configured template that includes an operating system and may come with additional software.</p>
</li>
<li><p><strong>Select an instance type:</strong> Pick the right size for your needs. For example, <code>t2.micro</code> is a good option for beginners and small workloads.</p>
</li>
<li><p><strong>Configure Your EC2 Instance:</strong> Set up networking, storage, security groups, and other options based on your requirements.</p>
</li>
<li><p><strong>Launch Your Instance:</strong> Start your virtual server and access it remotely to begin using it.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736174305817/e8d9d8dd-f09d-4bca-a838-42ee55607fa5.gif" alt="creating an EC2 instance" class="image--center mx-auto" width="1920" height="971" loading="lazy"></p>
<p>Launched instance running:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736174700999/b729de98-bd8f-496f-9486-3079d87fb4de.png" alt="Launched Instance" class="image--center mx-auto" width="1553" height="209" loading="lazy"></p>
<p>So what’s happening in Step 1?</p>
<p>By launching an AWS EC2 instance, you are setting up a remote server in the cloud. AWS offers different AMIs that serve as pre-configured environments.</p>
<h3 id="heading-step-2-connect-the-aws-ec2-instance-to-your-code-editor">Step 2: <strong>Connect the AWS EC2 Instance to Your Code Editor</strong></h3>
<p>To connect your EC2 instance created in AWS to your VS Code, you need SSH.</p>
<h4 id="heading-what-is-ssh">What is SSH?</h4>
<p>SSH (Secure Shell) is a secure way to connect and communicate with other devices. It keeps your connection safe. This is important when you access servers or repositories. In Git, you can use SSH instead of HTTPS to clone repositories with a secure connection.</p>
<h4 id="heading-why-is-ssh-important-here">Why is SSH important here?</h4>
<p>With SSH, you can link your local code editor (like VS Code) to your AWS EC2 instance. This allows you to work on files stored on the EC2 instance directly from your editor as if on your local computer.</p>
<p><strong>To connect your AWS EC2 instance to your local editor using SSH, follow these steps:</strong></p>
<ul>
<li><p>Open your terminal.</p>
</li>
<li><p>Go to the folder where your <code>.pem</code> key file is. The key file (.pem) downloads automatically when you create your EC2 instance (usually in the Downloads folder).</p>
</li>
<li><p>Update the file permissions to keep your key secure and ensure proper authentication.</p>
</li>
</ul>
<p>For Linux users, use this command to update the file permissions:</p>
<pre><code class="lang-bash">chmod 400 codebuild-keypair.pem
</code></pre>
<p>For Windows users, first you’ll need to find the username of your laptop, as you’ll need it to update the file permissions.</p>
<p>To do this, open your terminal and type:</p>
<pre><code class="lang-powershell">whoami
</code></pre>
<p>This will display your current username.</p>
<p>Once you have your username, use the following command to update the file permissions:</p>
<pre><code class="lang-powershell">icacls <span class="hljs-string">"codebuild-keypair.pem"</span> /reset
icacls <span class="hljs-string">"codbuild-keypair.pem"</span> /grant:<span class="hljs-built_in">r</span> <span class="hljs-string">"%USERNAME%:R"</span>
icacls <span class="hljs-string">"codebuld-keypair.pem"</span> /inheritance:<span class="hljs-built_in">r</span>
</code></pre>
<p>Here's what I mean: My username is <strong>ijeon</strong>, so you should replace it with <strong>your laptop's username</strong> and <strong>own</strong> key, which ends with <code>.pem</code> extension.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736021541861/048a9411-2348-48dc-8a6e-04d51dbd347d.png" alt="pasting the command on the terminal" class="image--center mx-auto" width="1096" height="102" loading="lazy"></p>
<p>Running this command above updates the file permissions. So with this, you can work with your remote server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736021649692/118c75cf-30b4-474c-b726-142c2b4326e9.png" alt="the output of the command pasted" width="722" height="153" loading="lazy"></p>
<p>Now that you have set the correct file permissions, you can use the SSH command along with the IPv4 address to connect to our EC2 instance. Type the following command:</p>
<pre><code class="lang-powershell">ssh <span class="hljs-literal">-i</span> [<span class="hljs-type">PATH</span> <span class="hljs-type">TO</span> <span class="hljs-type">YOUR</span> <span class="hljs-type">.PEM</span> <span class="hljs-type">FILE</span>] ec2<span class="hljs-literal">-user</span><span class="hljs-selector-tag">@</span>[<span class="hljs-type">YOUR</span> <span class="hljs-type">PUBLIC</span> <span class="hljs-type">IPV4</span> <span class="hljs-type">DNS</span>]
</code></pre>
<p>Example:</p>
<pre><code class="lang-powershell">ssh <span class="hljs-literal">-i</span> <span class="hljs-string">"C:\Users\ijeon\OneDrive\Desktop\devops-series-nextwork\codebuild-keypair.pem"</span> ec2<span class="hljs-literal">-user</span>@ec2<span class="hljs-literal">-35</span><span class="hljs-literal">-178</span><span class="hljs-literal">-142</span><span class="hljs-literal">-201</span>.eu<span class="hljs-literal">-west</span><span class="hljs-literal">-2</span>.compute.amazonaws.
</code></pre>
<p>Breaking it down:</p>
<ol>
<li><p><code>ssh</code>: This starts a secure remote connection.</p>
</li>
<li><p><code>-i "C:\Users\ijeon\...\codebuild-keypair.pem"</code>: This tells SSH to use the <code>.pem</code> key file for secure access.</p>
</li>
<li><p><a target="_blank" href="mailto:ec2-user@ec2-35-178-142-201.eu-west-2.compute.amazonaws.com"><code>ec2-user@ec2-35-178-142-201.eu-west-2.compute.amazonaws.com</code></a>:</p>
<ul>
<li><p><code>ec2-user</code> is the default username for EC2 instances.</p>
</li>
<li><p><code>@ec2-35-178-142-201...</code> is the public address of your EC2 instance.</p>
</li>
</ul>
</li>
</ol>
<p>This command logs you into your EC2 instance remotely from your computer. It then uses the key (<code>.pem</code> file) instead of a password for security. It also lets you control the EC2 instance from your terminal as if you were using it directly.</p>
<p>If everything is set up correctly, a “success message” will appear. This confirms that you've logged in and can access the remote server.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742153348953/a68f32fc-7578-4904-9b2e-e63a353e84a0.gif" alt="connecting via ssh" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<h3 id="heading-step-3-install-the-programming-language"><strong>Step 3: Install the Programming Language</strong></h3>
<p>Now that you’ve linked your instance to the editor, you can install the packages needed to build your web app. You can use any programming language you're comfortable with, but we’ll use Java for this tutorial. This will be a simple web application – we don’t need to go into advanced details.</p>
<h4 id="heading-1-install-java"><strong>1. Install Java</strong></h4>
<p>In your terminal, run the following commands to install <strong>Java</strong>:</p>
<pre><code class="lang-powershell">sudo dnf install <span class="hljs-literal">-y</span> java<span class="hljs-literal">-1</span>.<span class="hljs-number">8.0</span><span class="hljs-literal">-amazon</span><span class="hljs-literal">-corretto</span><span class="hljs-literal">-devel</span>

export JAVA_HOME=/usr/lib/jvm/java<span class="hljs-literal">-1</span>.<span class="hljs-number">8.0</span><span class="hljs-literal">-amazon</span><span class="hljs-literal">-corretto</span>.x86_64

export PATH=/usr/lib/jvm/java<span class="hljs-literal">-1</span>.<span class="hljs-number">8.0</span><span class="hljs-literal">-amazon</span><span class="hljs-literal">-corretto</span>.x86_64/jre/bin/:<span class="hljs-variable">$PATH</span>
</code></pre>
<p>This installs Java on your system. You also need Maven. It helps manage Java projects and create templates for web applications.</p>
<h4 id="heading-2-install-maven"><strong>2. Install Maven</strong></h4>
<p>Maven helps you organize Java projects. It also lets you create templates for web applications. Run these commands to install Maven:</p>
<pre><code class="lang-powershell"><span class="hljs-built_in">wget</span> https://archive.apache.org/dist/maven/maven<span class="hljs-literal">-3</span>/<span class="hljs-number">3.5</span>.<span class="hljs-number">2</span>/binaries/apache<span class="hljs-literal">-maven</span><span class="hljs-literal">-3</span>.<span class="hljs-number">5.2</span><span class="hljs-literal">-bin</span>.tar.gz

sudo tar <span class="hljs-literal">-xzf</span> apache<span class="hljs-literal">-maven</span><span class="hljs-literal">-3</span>.<span class="hljs-number">5.2</span><span class="hljs-literal">-bin</span>.tar.gz <span class="hljs-literal">-C</span> /opt

<span class="hljs-built_in">echo</span> <span class="hljs-string">"export PATH=/opt/apache-maven-3.5.2/bin:<span class="hljs-variable">$PATH</span>"</span> &gt;&gt; ~/.bashrc

source ~/.bashrc
</code></pre>
<p>To confirm Maven's correct installation, run this command:</p>
<pre><code class="lang-powershell">mvn <span class="hljs-literal">-v</span>
</code></pre>
<p>Also, run the following command to check whether you have Java installed:</p>
<pre><code class="lang-powershell">java <span class="hljs-literal">-version</span>
</code></pre>
<p>Now that you have installed Maven, you can use it to create a Java web app with the following command:</p>
<pre><code class="lang-powershell">mvn archetype:generate \
  <span class="hljs-literal">-DgroupId</span>=com.nextwork.app \
  <span class="hljs-literal">-DartifactId</span>=nextwork<span class="hljs-literal">-web</span><span class="hljs-literal">-project</span> \
  <span class="hljs-literal">-Dpackage</span>=com.nextwork.app \
  <span class="hljs-literal">-DarchetypeArtifactId</span>=maven<span class="hljs-literal">-archetype</span><span class="hljs-literal">-webapp</span> \
  <span class="hljs-literal">-DarchetypeVersion</span>=<span class="hljs-number">1.4</span> \
  <span class="hljs-literal">-DinteractiveMode</span>=false
</code></pre>
<p>Running the command above generates a template for your application. In the terminal, it should show a "Build Success" message. This means the setup worked.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742122446716/7c51b3a2-6a8c-463d-817c-9630488a803d.png" alt="Installing the template" class="image--center mx-auto" width="1410" height="854" loading="lazy"></p>
<h3 id="heading-step-4-open-a-remote-window"><strong>Step 4:</strong> Open a Remote Window</h3>
<p>Now that you’ve installed the necessary packages and set up your app template, you need to open your IDE or code editor. This will let you access the folders on your remote server.</p>
<p>In your terminal, click the double arrow icon at the bottom left.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736073016500/cb3a4d44-3ae5-4ccb-9006-c592c0be30f7.png" alt="double arrow at the left" class="image--center mx-auto" width="155" height="119" loading="lazy"></p>
<p>When you click on it, it opens a modal window for you.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736073334686/a24d115c-9da3-4b46-80be-a75d73a189ab.gif" alt="connect to the host" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<p>A window will appear. Click "Connect to Host," which will open another window.</p>
<p>Then choose "Add New SSH Host" to open the SSH connection terminal.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736073802080/45dbc209-0b4c-41a2-83eb-3fa05a8eff20.gif" alt="adding ssh host" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<p>Input your SSH command to configure the host.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736078262849/b09d017e-cbd3-476e-9641-63dc41e34d83.png" alt="image of SSH connection command" class="image--center mx-auto" width="928" height="146" loading="lazy"></p>
<p>After pressing "Enter," a configuration file will open. In this file, ensure that the <code>.pem</code> file and the <code>IP4v DNS</code> addresses from your EC2 instance are correct.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736083806867/e158ee79-67d3-41c8-bb63-870caab0033b.png" alt="place to press for the configuration file" class="image--center mx-auto" width="890" height="207" loading="lazy"></p>
<p>Here’s a GIF view of the image above:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736083586490/7520a325-376d-42a8-905d-2e22770498de.gif" alt="a gif view of how to open your configuration file" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<p>Here’s the configuration file:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736084278100/6e71324f-6b47-4a2a-b7a1-89c1be10c39b.png" alt="config file" class="image--center mx-auto" width="1348" height="349" loading="lazy"></p>
<p>Go back to your editor and click on that double arrow again. This will automatically open a new window.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736086002267/53e4edd8-afe2-4652-90ab-56bc90f80405.gif" alt="Re-opening a new window" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<p>If your editor displays the IPv4 DNS address, your VS Code is successfully connected to the EC2 instance.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736086479299/e399f86c-e236-4efc-8d4d-a7055139d01e.png" alt="connection to the remote server" width="683" height="209" loading="lazy"></p>
<p>Now that you’re connected and a new window has opened, let’s access the folder stored in the cloud.</p>
<h3 id="heading-step-5-access-your-project-folder">Step 5: Access Your Project Folder</h3>
<p>In step 3, remember when you installed Maven? It created a template for your web app. Now, you’ll access the folder where you created this.</p>
<ol>
<li><p>Go to the Explorer panel in the window.</p>
</li>
<li><p>Click the <strong>“</strong>Open Folder<strong>”</strong> button.</p>
</li>
</ol>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1736087503207/7fb21fcb-939e-4f17-83d2-93a6e0e3ee68.png" alt="access remote folder" class="image--center mx-auto" width="219" height="171" loading="lazy"></p>
<p>Clicking on this button opens a modal box for you to select your folder, which was created by the Maven template:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742134089654/77104e69-4c7a-4b59-812d-423167079f24.gif" alt="accessing the folder" class="image--center mx-auto" width="1920" height="1079" loading="lazy"></p>
<p>To access the template file, click the “src” folder. This takes you to the <code>index.jsp</code> file.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1742135158716/4cfedc15-1c2e-4d60-b9f6-fe04c300dfa0.png" alt="template automatically created for you" width="1920" height="1080" loading="lazy"></p>
<p>With this template created, you can decide to tweak it and send it to your Git repository for storage.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>Great job! You’ve set up an AWS EC2 instance, linked it to your code editor, and installed the tools needed for your web app. In this tutorial, we used Java, but you can also choose other languages like Node.js or Python.</p>
<p>If you found this article helpful, please share it with others who may find it interesting.</p>
<p>Stay updated with my projects by following me on <a target="_blank" href="https://twitter.com/ijaydimples">Twitter</a>, <a target="_blank" href="https://twitter.com/ijaydimples">LinkedIn</a> and <a target="_blank" href="https://github.com/ijayhub">GitHub</a>.</p>
<p>Thank you for reading.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Speed Up Website Loading by Removing Extra Bits and Bytes ]]>
                </title>
                <description>
                    <![CDATA[ Let’s start with an interesting fact: according to research done by Akamai, a 1-second delay in loading a website’s page can decrease the conversion rate by 7%. We are currently living in a fast-paced world, where time is money for everyone. People e... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/speed-up-website-loading/</link>
                <guid isPermaLink="false">67bca6f616cf4617f656a33f</guid>
                
                    <category>
                        <![CDATA[ code optimization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ server ]]>
                    </category>
                
                    <category>
                        <![CDATA[ hosting ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Google PageSpeed ]]>
                    </category>
                
                    <category>
                        <![CDATA[ cloudflare ]]>
                    </category>
                
                    <category>
                        <![CDATA[ performance ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Alex Tray ]]>
                </dc:creator>
                <pubDate>Mon, 24 Feb 2025 17:05:58 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1740094347867/d1097d7b-776f-4228-8088-7726b827271f.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Let’s start with an interesting fact: according to research done by <a target="_blank" href="https://www.akamai.com/newsroom/press-release/akamai-releases-spring-2017-state-of-online-retail-performance-report">Akamai</a>, a 1-second delay in loading a website’s page can decrease the conversion rate by 7%.</p>
<p>We are currently living in a fast-paced world, where time is money for everyone. People expect their favorite websites to load lightning-fast. A slow loading speed will not only make them go to the competitor but will also hurt the <a target="_blank" href="https://www.freecodecamp.org/news/how-to-use-on-page-seo-techniques-to-rank-on-the-first-page/">website's ranking</a> in the SERP.</p>
<p>But the main question is, who’s the culprit? Those extra bits and bytes that almost every site contains. These are unnecessary code files, unoptimized images, and many more. But by following the right approach, you can easily strip away these inefficiencies and achieve excellent loading speed.</p>
<p>In this article, I will be discussing that approach in detail, so stick around with me till the very end.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-why-does-loading-speed-matter">Why Does Loading Speed Matter?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-google-ranking-factor">Google Ranking Factor</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-impact-on-user-experience">Impact on User Experience</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-negative-brand-perception">Negative Brand Perception</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-retaining-mobile-users">Retaining Mobile Users</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-remove-extra-bits-amp-bytes-from-the-website-different-strategies">How to Remove Extra Bits &amp; Bytes from the Website – Different Strategies</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-perform-code-optimization">Perform Code Optimization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-image-amp-media-optimization">Image &amp; Media Optimization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-manage-plugins-amp-scripts">Manage Plugins &amp; Scripts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-server-amp-hosting-upgrades">Server &amp; Hosting Upgrades</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-that-you-can-use-to-streamline-the-process">Tools That You Can Use to Streamline the Process</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-minifierhttpswwwminifierorg">Minifier</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tinypnghttpstinypngcom">TinyPNG</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-png-to-webp-converterhttpscloudconvertcompng-to-webp">PNG to WebP Converter</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-google-pagespeed-insighthttpspagespeedwebdev">Google PageSpeed Insight</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-cloudflarehttpswwwcloudflarecom">Cloudflare</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-wrapping-up">Wrapping Up</a></p>
</li>
</ul>
<h2 id="heading-why-does-loading-speed-matter">Why Does Loading Speed Matter?</h2>
<p>There are several reasons why the loading speed of a website is considered essential. Here are some of the major ones.</p>
<ol>
<li><h3 id="heading-google-ranking-factor">Google Ranking Factor:</h3>
</li>
</ol>
<p>Website loading speed is a confirmed ranking factor. This means that search engines like Google definitely consider the loading time when evaluating a website’s quality. Usually, the <a target="_blank" href="https://sematext.com/glossary/page-load-time/">ideal loading speed</a> is between 0 and 2 seconds. However, 3 seconds is also sometimes acceptable.</p>
<p>In case your site does not fulfill this criteria, then there is a high probability that it may receive a penalty from Google. This will result in lower rankings in the targeted niche – which no webmaster or business wants.</p>
<ol start="2">
<li><h3 id="heading-impact-on-user-experience">Impact on User Experience:</h3>
</li>
</ol>
<p>A slow loading speed is capable of single-handedly destroying the entire user experience. When the website does not load quickly in front of the visitor, they may close it and move on to another site to find the required information, product, or service.</p>
<p>This will decrease the number of user engagements and increase the overall bounce rate of the site. And a high bounce rate increases the chances of facing a penalty from Google.</p>
<ol start="3">
<li><h3 id="heading-negative-brand-perception">Negative Brand Perception:</h3>
</li>
</ol>
<p>For online businesses or brands, their authority and image are everything. When their official site takes too much time to load, it ultimately damages the brand’s perception or credibility in their minds. They will think about how you can deliver a top-notch service or product when you aren’t able to properly manage a website.</p>
<p>This negative impression will not only reduce customer engagement but also conversions.</p>
<ol start="4">
<li><h3 id="heading-retaining-mobile-users">Retaining Mobile Users:</h3>
</li>
</ol>
<p>Mobile contributes to <a target="_blank" href="https://www.mobiloud.com/blog/what-percentage-of-internet-traffic-is-mobile">58% of the global internet traffic</a>. It is also true mobile networks often have slow internet speed issues as compared to Wi-Fi. This can be especially true for people living in rural areas. So, that’s why you should always prioritize loading speed to efficiently retain mobile users.</p>
<h2 id="heading-how-to-remove-extra-bits-amp-bytes-from-the-website-different-strategies">How to Remove Extra Bits &amp; Bytes from the Website – Different Strategies</h2>
<p>Here are some of the most proven strategies you can utilize to remove extra bits and bytes from your websites.</p>
<ol>
<li><h3 id="heading-perform-code-optimization">Perform Code Optimization:</h3>
</li>
</ol>
<p>Excessive HTML, CSS, and JavaScript can greatly slow down a website. Due to the large code file, the host server will have to transfer more packets to the client browser, ultimately resulting in slow loading.</p>
<p>To resolve this issue, it is always recommended to perform code optimization. The most widely known and used technique for this purpose is minification. It refers to the process of removing all the:</p>
<ul>
<li><p>Unnecessary characters</p>
</li>
<li><p>White spaces</p>
</li>
<li><p>Line breaks</p>
</li>
<li><p>Comments</p>
</li>
<li><p>Unused elements.</p>
</li>
</ul>
<p>But you’ll want to make sure that the code works as before, even after minification.</p>
<p>Optimizing code boosts application performance by reducing execution time and resource consumption. Refactor inefficient loops, minimize database queries, and leverage caching to enhance speed. You can use profiling tools to identify bottlenecks and streamline functions for smoother, faster performance.</p>
<p>To demonstrate better, below I have discussed an example:</p>
<p><strong>Unoptimized JavaScript Code:</strong></p>
<pre><code class="lang-javascript">greet(name) {
    <span class="hljs-keyword">if</span> (!name) {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, Guest!"</span>);
    } <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span> + name + <span class="hljs-string">"!"</span>);
    }
}
greet(<span class="hljs-string">"John"</span>);
</code></pre>
<p><strong>Minified Version:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">greet</span>(<span class="hljs-params">n</span>)</span>{<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello, "</span>+(n||<span class="hljs-string">"Guest"</span>)+<span class="hljs-string">"!"</span>)}greet(<span class="hljs-string">"John"</span>);
</code></pre>
<p>As you can see, I created the minified version by removing all the line breaks and whitespaces. Apart from this, I used shortened variables, like “<strong>n</strong>” instead of “<strong>Name</strong>.” Finally, I also replaced the If Else statement with a shorter n || "Guest" expression.</p>
<p>This is how you can easily condense the entire HTML, CSS, and JavaScript code of your website, and enhance the overall loading speed.</p>
<p>Just keep in mind that there are multiple downsides of code minification. For instance, it significantly impacts code readability and can cause challenges in debugging and maintenance. So use this approach judiciously.</p>
<ol start="2">
<li><h3 id="heading-image-amp-media-optimization">Image &amp; Media Optimization:</h3>
</li>
</ol>
<p>Apart from code, unoptimized images, <a target="_blank" href="https://logocreator.io/blog/logo-file-formats/">logo files</a> and other media files are often the main culprits behind the slow <a target="_blank" href="https://www.freecodecamp.org/news/developers-guide-to-website-speed-optimization/">loading speed</a> of a website. This means that you also need to optimize them as well. There are numerous things you can do in this regard.</p>
<p>First of all – you should reduce the image size in terms of storage. It is generally recommended that each <a target="_blank" href="https://www.foregroundweb.com/image-size/">picture should be less than 500 KB in size</a>. But note that this size can vary depending on the use case.</p>
<p>It’s also a good idea to choose next-generation picture formats like WebP instead of typical ones like JPEG or PNG. When it comes to video files, it’s also helpful if you go with the embedded ones from platforms like YouTube.</p>
<p><strong>Now, let us explain all this with a proper example (Before &amp; After).</strong></p>
<p>Let’s say that a website uses a 2MB JPEG image for its blog post. Its optimization process will involve the following steps:</p>
<ul>
<li><p>Resize the image first. The recommended dimensions are 1200x800.</p>
</li>
<li><p>Compress the image size using image compression tools (we’ll discuss one such tool later in this article)</p>
</li>
<li><p>Now, convert the JPEG file into WebP format.</p>
</li>
<li><p>Add alternative text before publishing</p>
</li>
</ul>
<p><strong>After optimization:</strong></p>
<ul>
<li><p>The image file size will now be reduced to KBS somewhere around 120Kb.</p>
</li>
<li><p>Your website will experience better loading speed as well as an improved user experience.</p>
</li>
</ul>
<p>One more tip that you can consider is <a target="_blank" href="https://www.freecodecamp.org/news/how-lazy-loading-works-in-web-development/">lazy loading</a>. This means only loading the images and videos when they are about to be consumed.</p>
<p>By taking care of these few things, you can efficiently optimize images and media files to achieve faster loading speeds.</p>
<ol start="3">
<li><h3 id="heading-manage-plugins-amp-scripts">Manage Plugins &amp; Scripts:</h3>
</li>
</ol>
<p>Your website may contain unused plugins and scripts that can cause bloat. So, to remove the extra bits and bytes, it is essential to perform regular check-ins.</p>
<p>First, make sure you deactivate and delete all the plugins that aren’t needed. Then, start exploring more lightweight alternatives for plugins that you are actively using. If you find any, go for them and uninstall the bulky ones to improve performance and enhance security, especially for processes like identity verification. Ensure you’re using the latest, most optimized version..</p>
<p>For example, Revolution Slider is a heavy plugin. It loads large scripts and images on every page, even when not needed. This ultimately affects the overall website speed. Some of its lightweight alternatives that you might consider for this include <a target="_blank" href="https://smartslider3.com/">Smart Slider 3</a>, or any other CSS-based slider.</p>
<p>Next comes script management. Here you should first limit any third-party scripts, such as excessive code tracking, social media widgets, and embedded content. Apart from this, don’t forget to totally disable scripts on the pages where they aren’t required.</p>
<p>One useful example here is Google Analytics which loads tracking scripts on every page, increasing the request time. To fix this issue, you can use <a target="_blank" href="https://tagmanager.google.com/">Google Tag Manager</a> to load the scripts only when they are needed.</p>
<p>Additionally, you can use <a target="_blank" href="https://www.blaze.tech/post/no-code-automation-how-to-streamline-your-business-now">no-code workflow automation tools</a> like Zapier, Make, or Uncanny Automator which help streamline processes by reducing reliance on heavy plugins and scripts.</p>
<ol start="4">
<li><h3 id="heading-server-amp-hosting-upgrades">Server &amp; Hosting Upgrades:</h3>
</li>
</ol>
<p>This is the final strategy that you can consider. Your hosting provider plays a key role in deciding the loading speed of the website. So, it’s a good idea to upgrade your hosting plan and get it from a reputable and credible service.</p>
<p>Also, do not forget to enable server-side compression. Doing so will automatically reduce the file sizes before transmission. Optimizing database performance is equally crucial, as <a target="_blank" href="https://www.liquibase.com/resources/guides/database-observability">database observability enables database pipeline analytics</a>, helping to identify inefficiencies, reduce query execution time, and enhance overall site responsiveness.</p>
<p>Also, take steps to optimize the database queries. You can do this by removing unnecessary data while also caching data mechanisms. There are also specialized plugins available for this like <a target="_blank" href="https://wordpress.org/plugins/wp-optimize/">WP-Optimize</a>. It effectively cleans up all the unnecessary data saving valuable time and effort.</p>
<p>You should also start caching queries. Store all the frequent ones in memory. This will significantly reduce database load.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> products <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">category</span> = <span class="hljs-string">'Laptops'</span> <span class="hljs-keyword">CACHE</span>;
</code></pre>
<p>This prevents the server from re-executing the same query repeatedly.</p>
<p>So, these are some of the proven strategies you can apply to eliminate additional bits &amp; bytes from the website to achieve faster loading.</p>
<h2 id="heading-tools-that-you-can-use-to-streamline-the-process">Tools That You Can Use to Streamline the Process</h2>
<p>To simplify the process of optimizing website loading speed, you can consider utilizing the following tools.</p>
<ol>
<li><h3 id="heading-minifierhttpswwwminifierorg"><a target="_blank" href="https://www.minifier.org/">Minifier</a></h3>
</li>
</ol>
<p>First of all, we have Minifier, a dedicated tool that is specifically designed to automate the code minification process with a single click. It is available for free and works for HTML, CSS, and JavaScript codes.</p>
<p>Besides this, the tool features a user-intuitive interface so that you can quickly navigate through it. The minifier is trained according to both development and minification to ensure maximum speed and accuracy in the output.</p>
<p>All you need to do is either paste or upload the code file into the tool, hit the “<strong>Minify</strong>” button, and get a condensed version. You can check out the below screenshot to get a better idea how it works.</p>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcu5gaAosAaUCZQ7oIp3J_m_CIEyAshp2Ob6rmguvQOQvxuuz6rXJ1QdO_FSD_McnO1S-fkqv38cY7B0e4s5xBtjNa78mVns2VZRe3iUemWxR-dKgct9-OJkb6YIO2fTkhB_W3If4DYj6hb2vnzknY?key=W-8S2j9mlTlf7KW39H_m9bHu" alt="Screenshot showing Minify result" width="600" height="400" loading="lazy"></p>
<p>Minify also offers a wide variety of other useful tools you can use if needed. Some notable options include JSON minifier and XML formatter, among others.</p>
<p>So now there is no need to spend time and effort on manually minifying your code for better loading speed. You can just use this tool and get the job done with a single click.</p>
<ol start="2">
<li><h3 id="heading-tinypnghttpstinypngcom"><a target="_blank" href="https://tinypng.com/">TinyPNG</a></h3>
</li>
</ol>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXckb9b-_Pfw-T4icivrTC6g_pnhjpu3BSK0s-7ussuhsRRY22qGNe8DAyUINv8GgGQ5DmY579muEPcGkCjRsbSZofP9XZ1y3xqPBYriFDyh_2vl6yWM4fNYBKaA7k5Jx05pRjjw3ShVU3tT3JjeHwM?key=W-8S2j9mlTlf7KW39H_m9bHu" alt="AD_4nXckb9b-_Pfw-T4icivrTC6g_pnhjpu3BSK0s-7ussuhsRRY22qGNe8DAyUINv8GgGQ5DmY579muEPcGkCjRsbSZofP9XZ1y3xqPBYriFDyh_2vl6yWM4fNYBKaA7k5Jx05pRjjw3ShVU3tT3JjeHwM?key=W-8S2j9mlTlf7KW39H_m9bHu" width="600" height="400" loading="lazy"></p>
<p>Many of you may have heard of or even used this tool. It is an image compression tool that will help you effectively reduce your image sizes for optimization. The good thing is that TinyPNG perfectly preserves the original quality of the picture (in terms of resolution) even after the compression.</p>
<p>All you need to do is upload the required photo from your local storage, and the tool will automatically provide a compressed version. Don’t worry about the file format, as TinyPNG supports JPG, PNG, JPEG, and many more.</p>
<p>The tool even provides the percentage of how much the uploaded image was compressed, like -51%, and so on. It also mentions the size of the compressed photo in terms of KBs. So, in case you are not satisfied with the file size, you can further compress it.</p>
<ol start="3">
<li><h3 id="heading-png-to-webp-converterhttpscloudconvertcompng-to-webp"><a target="_blank" href="https://cloudconvert.com/png-to-webp">PNG to WebP Converter</a>:</h3>
</li>
</ol>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXcSaBUNNRRqk5A4EetHdg1CK1P6F-Ro213s3DnifuZZFF24BNJZHsP_qXjVe1rn72iPH2jZd707JRsOSIUe7PzEAH7jE0ccacHXaEbqJ0YDILtM4K4gF5IYao0wOpJ13jw-xNOzrKaJiRP926kjqQ?key=W-8S2j9mlTlf7KW39H_m9bHu" alt="AD_4nXcSaBUNNRRqk5A4EetHdg1CK1P6F-Ro213s3DnifuZZFF24BNJZHsP_qXjVe1rn72iPH2jZd707JRsOSIUe7PzEAH7jE0ccacHXaEbqJ0YDILtM4K4gF5IYao0wOpJ13jw-xNOzrKaJiRP926kjqQ?key=W-8S2j9mlTlf7KW39H_m9bHu" width="600" height="400" loading="lazy"></p>
<p>As I mentioned earlier, I recommend using next-gen image formats like WebP instead of older formats when possible. Usually, the widely used format is PNG, but to seamlessly convert into WebP, you can use this PNG to WebP converter.</p>
<p>It’s available for free and does not ask for registration/signup. Simply visit the page and start performing conversions. The conversion is performed without causing any damage to the image’s quality and formatting.</p>
<p>The tool also offers many extra features. For instance, you can adjust both the image’s width and height. You can also set image quality (WebP compression level) if required. And it doesn’t stop here – you can even select the right fit for the photo from the following options:</p>
<ul>
<li><p>Max</p>
</li>
<li><p>Crop</p>
</li>
<li><p>Scale</p>
</li>
</ul>
<ol start="4">
<li><h3 id="heading-google-pagespeed-insighthttpspagespeedwebdev"><a target="_blank" href="https://pagespeed.web.dev/">Google PageSpeed Insight</a></h3>
</li>
</ol>
<p>How can you enhance the loading speed of the website when you don’t even know which elements are causing issues? For this purpose, Google PageSpeed Insight is the best solution. It is developed and managed by Google.</p>
<p>The tool effectively crawls the given page link and highlights all the issues that are causing slow loading. It even provides four different scores (0-100) for evaluation. These include:</p>
<ul>
<li><p>Performance</p>
</li>
<li><p>Accessibility</p>
</li>
<li><p>Best Practices</p>
</li>
<li><p>SEO</p>
</li>
</ul>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXet-k73bv-y0HQXbGHfrcntmms8k_nQvcrrADNI3w9cBrFKGv9CAkMSEdOCWHFVyuRQxVXaUseYQxIa_2GA9Hl7TzDGSSO_vZqZliiX32ZNdkvoQZYhCf4i3PyKtGHOzk8pwqZ6O-gZRCwPC3gzBt0?key=W-8S2j9mlTlf7KW39H_m9bHu" alt="AD_4nXet-k73bv-y0HQXbGHfrcntmms8k_nQvcrrADNI3w9cBrFKGv9CAkMSEdOCWHFVyuRQxVXaUseYQxIa_2GA9Hl7TzDGSSO_vZqZliiX32ZNdkvoQZYhCf4i3PyKtGHOzk8pwqZ6O-gZRCwPC3gzBt0?key=W-8S2j9mlTlf7KW39H_m9bHu" width="600" height="400" loading="lazy"></p>
<p>The good thing is that Google PageSpeed Insights evaluates the page for both mobile and desktop users. The results are also provided separately. The areas of improvement are highlighted in red, along with the necessary instructions you can take. The good parts are marked with green.</p>
<p>By utilizing this tool, you can easily evaluate your website and then make efforts to improve the loading speed.</p>
<ol start="5">
<li><h3 id="heading-cloudflarehttpswwwcloudflarecom"><a target="_blank" href="https://www.cloudflare.com/">Cloudflare</a></h3>
</li>
</ol>
<p><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXeKEUhCvUoLArPXA_KRMaH4ws28-YXc6OSzP9idKqis14maZynQIrYUoHaJWF1LJ20q7UcFjAhUGc7WRKpk1S37tkaanh5VRqguD2u7ICzp5eFY5e0mMNjZJU_yl-YCm2O1hdaq2gsnwpWJDbPMGGI?key=W-8S2j9mlTlf7KW39H_m9bHu" alt="AD_4nXeKEUhCvUoLArPXA_KRMaH4ws28-YXc6OSzP9idKqis14maZynQIrYUoHaJWF1LJ20q7UcFjAhUGc7WRKpk1S37tkaanh5VRqguD2u7ICzp5eFY5e0mMNjZJU_yl-YCm2O1hdaq2gsnwpWJDbPMGGI?key=W-8S2j9mlTlf7KW39H_m9bHu" width="600" height="400" loading="lazy"></p>
<p>Last but not least, Cloudflare is a good tool that helps enhance the loading speed of a website by using its global content delivery network (CDN). With this feature, it caches static content across different servers worldwide. This ultimately reduces the overall latency and improves loading speed for users in different locations.</p>
<p>Besides this, Cloudflare also offers a bunch of other features. For example, it automatically minifies HTML, CSS, and JavaScript files. It can even compress and convert images into next-gen formats, especially WebP.</p>
<p>It offers a robust DNS resolution that reduces lookup times and helps the page load faster. This feature also protects the site from DDoS attacks.</p>
<h2 id="heading-wrapping-up">Wrapping Up</h2>
<p>If you want to experience higher ranking and increased user engagement, then you need to optimize your website’s loading speed. The extra bits and bytes like code files, media, and so on can cause real hurdles – but don’t worry.</p>
<p>By using these strategies and tools, you’ll be able to speed up page loading in no time. I hope you found this article interesting and valuable.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
