{
    "version": "https://jsonfeed.org/version/1",
    "title": "Pranjal Blogs",
    "home_page_url": "https://blogs.pranjalkumar.in/blog",
    "description": "Engineering deep dives on systems, security, and architecture by Pranjal Kumar",
    "items": [
        {
            "id": "https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" alt=\"Chrome Device Bound Session Credentials architecture\" src=\"https://blogs.pranjalkumar.in/assets/images/chrome-device-bound-session-credentials-explained%20by%20Pranjal%20Kumar%20-%20software%20engineer-6ef0d66599ca8cdfcf5f8915764e0b0d.png\" width=\"1448\" height=\"1086\" class=\"img_ev3q\">\nMost authentication systems are built around a comforting illusion: once a user successfully logs in, the system believes it knows who is on the other side of the connection.</p>\n<p>In reality, most web applications do not continuously know <em>who</em> is using the session. They know only that each request carries a valid cookie.</p>\n<p>That distinction is not academic. It is the reason session theft remains one of the most effective ways to bypass passwords, MFA, passkeys, risk checks, and even carefully designed identity-provider flows.</p>\n<p>Chrome's <strong>Device Bound Session Credentials</strong>, commonly called <strong>DBSC</strong>, is aimed directly at this weakness. It changes the trust model of web sessions from:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bearer session model:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">If you have the cookie, you are the session.</span><br></div></code></pre></div></div>\n<p>To:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Device-bound proof-of-possession model:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">If you have the cookie, you must also prove you are still on the original device.</span><br></div></code></pre></div></div>\n<p>That is a fundamental architectural shift.</p>\n<p>DBSC is not just another browser feature. It is part of a broader movement away from portable bearer credentials and toward credentials that are bound to context, device, and proof of possession.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-core-problem-cookies-are-bearer-credentials\">The core problem: cookies are bearer credentials<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#the-core-problem-cookies-are-bearer-credentials\" class=\"hash-link\" aria-label=\"Direct link to The core problem: cookies are bearer credentials\" title=\"Direct link to The core problem: cookies are bearer credentials\" translate=\"no\">​</a></h2>\n<p>A traditional session cookie is a <strong>bearer credential</strong>. “Bearer” means possession is enough.</p>\n<p>The server does not ask:</p>\n<ul>\n<li class=\"\">Why does this requester have the cookie?</li>\n<li class=\"\">Was this cookie copied from another machine?</li>\n<li class=\"\">Is this the same browser that originally authenticated?</li>\n<li class=\"\">Is the private device context still present?</li>\n</ul>\n<p>If the cookie is valid and unexpired, the request is generally treated as authenticated.</p>\n<p>That gives us a simple but dangerous flow:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">User logs in with password + MFA</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server issues session cookie</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Malware steals cookie</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Attacker imports cookie elsewhere</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server accepts attacker as logged-in user</span><br></div></code></pre></div></div>\n<p>This is why cookie theft can bypass MFA. MFA protects the <strong>login ceremony</strong>, but once a session has been established, the cookie often becomes the real proof of authentication.</p>\n<p>The attacker does not need to defeat cryptography. They do not need to brute-force a password. They do not need to intercept a one-time password. They only need the browser's already-issued session artifact.</p>\n<p>That is why infostealer malware is so effective. It targets browser session state, extracts cookies or tokens, and replays them elsewhere.</p>\n<p>The uncomfortable truth is this:</p>\n<blockquote>\n<p>If a credential is portable, attackers will build an economy around stealing and replaying it.</p>\n</blockquote>\n<p>DBSC exists because the web's dominant session model made authenticated sessions too easy to move from one device to another.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbscs-big-idea-make-the-session-non-portable\">DBSC's big idea: make the session non-portable<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbscs-big-idea-make-the-session-non-portable\" class=\"hash-link\" aria-label=\"Direct link to DBSC's big idea: make the session non-portable\" title=\"Direct link to DBSC's big idea: make the session non-portable\" translate=\"no\">​</a></h2>\n<p>DBSC does not try to make cookies impossible to steal. That would be unrealistic.</p>\n<p>If malware runs with sufficient access on a user's machine, it may still be able to read browser-accessible state, observe network activity, or abuse the active browser context.</p>\n<p>Instead, DBSC attacks the attacker's <em>next step</em>: replay.</p>\n<p>The goal is not:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">No attacker can ever copy a cookie.</span><br></div></code></pre></div></div>\n<p>The goal is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">A copied cookie should not be enough to continue the session from another machine.</span><br></div></code></pre></div></div>\n<p>DBSC does this by binding session continuity to a cryptographic key pair generated on the user's device.</p>\n<p>At a high level:</p>\n<ol>\n<li class=\"\">Chrome creates a public/private key pair for the session.</li>\n<li class=\"\">The private key remains protected on the device.</li>\n<li class=\"\">The server stores the public key.</li>\n<li class=\"\">The server issues short-lived cookies.</li>\n<li class=\"\">When the cookie needs renewal, Chrome proves possession of the private key.</li>\n<li class=\"\">If proof succeeds, the server issues a fresh short-lived cookie.</li>\n</ol>\n<p>So the new session equation becomes:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Valid continued session = short-lived cookie + proof of device-held private key</span><br></div></code></pre></div></div>\n<p>That is the core DBSC idea.</p>\n<p>The attacker may steal the cookie, but once that short-lived cookie expires, they cannot renew the session from another machine unless they can also prove possession of the original device-bound private key.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-dbsc-works-the-actual-flow\">How DBSC works: the actual flow<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#how-dbsc-works-the-actual-flow\" class=\"hash-link\" aria-label=\"Direct link to How DBSC works: the actual flow\" title=\"Direct link to How DBSC works: the actual flow\" translate=\"no\">​</a></h2>\n<p>DBSC introduces three important backend concepts:</p>\n<ol>\n<li class=\"\"><strong>Session registration</strong></li>\n<li class=\"\"><strong>Short-lived cookies</strong></li>\n<li class=\"\"><strong>Refresh with proof of possession</strong></li>\n</ol>\n<p>The important design choice is that DBSC is additive. Applications do not need to rewrite every endpoint to understand a brand-new authentication system. Instead, DBSC is concentrated around login, registration, and refresh.</p>\n<p>Most application endpoints can continue checking cookies as they already do.</p>\n<p><strong>Step 1: user logs in normally</strong></p>\n<p>The user authenticates using the site's existing login mechanism:</p>\n<ul>\n<li class=\"\">Password</li>\n<li class=\"\">MFA</li>\n<li class=\"\">Passkey</li>\n<li class=\"\">SSO</li>\n<li class=\"\">Enterprise identity provider</li>\n<li class=\"\">Any existing authentication flow</li>\n</ul>\n<p>DBSC does not replace initial authentication. It strengthens what happens <em>after</em> authentication.</p>\n<p>That distinction matters.</p>\n<p>Passkeys and MFA answer:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Can this user authenticate now?</span><br></div></code></pre></div></div>\n<p>DBSC answers:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Can this already-authenticated session still prove it belongs to the original device?</span><br></div></code></pre></div></div>\n<p>Those are related, but different, security questions.</p>\n<hr>\n<p><strong>Step 2: server asks Chrome to start a device-bound session</strong></p>\n<p>After login, the server sends a DBSC registration instruction using an HTTP response header such as:</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Secure-Session-Registration: ...</span><br></div></code></pre></div></div>\n<p>Conceptually, the server is telling Chrome:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">For this authenticated session, create a device-bound credential and register it with me.</span><br></div></code></pre></div></div>\n<p>This is the bootstrap step.</p>\n<hr>\n<p><strong>Step 3: Chrome generates a public/private key pair</strong></p>\n<p>Chrome generates a new asymmetric key pair for the session.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Public key  → sent to server</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Private key → protected on the device</span><br></div></code></pre></div></div>\n<p>The public key is not secret. The server stores it and later uses it to verify signatures.</p>\n<p>The private key is the important artifact. It should not be exportable like a normal file. Ideally, it is protected by hardware-backed security such as a TPM on Windows or Secure Enclave-style protection on macOS.</p>\n<hr>\n<p><strong>Step 4: Chrome registers the public key</strong></p>\n<p>Chrome calls the site's registration endpoint and sends the public key and related session material.</p>\n<p>The server may store records similar to:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">user_id</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">session_id</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">public_key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">refresh_endpoint</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">cookie_scope</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">registration_time</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">expiration_policy</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">risk_policy</span><br></div></code></pre></div></div>\n<p>The private key never leaves the device.</p>\n<hr>\n<p><strong>Step 5: server issues short-lived cookies</strong></p>\n<p>This is one of the most important parts of DBSC.</p>\n<p>The server should not continue issuing long-lived bearer cookies. Instead, it transitions to short-lived cookies.</p>\n<p>The point is not that cookies become impossible to steal. The point is that stolen cookies become much less valuable because they expire quickly and cannot be refreshed without the device-bound private key.</p>\n<p>The model changes from:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Long-lived bearer cookie</span><br></div></code></pre></div></div>\n<p>To:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Short-lived cookie + hardware-backed/session-bound renewal</span><br></div></code></pre></div></div>\n<hr>\n<p><strong>Step 6: Chrome refreshes the session with proof of possession</strong></p>\n<p>When Chrome needs to make a request and notices that the DBSC-controlled cookie is missing or expired, Chrome can pause the original request and call the configured refresh endpoint.</p>\n<p>The refresh flow looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Original request needs valid cookie</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cookie expired or missing</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Chrome calls refresh endpoint</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server returns challenge</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Chrome signs challenge using device-held private key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server verifies signature using stored public key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server issues fresh short-lived cookie</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Original request resumes</span><br></div></code></pre></div></div>\n<p>This lets the user experience remain smooth while session continuation becomes cryptographically bound to the original device.</p>\n<p>That is the beauty of DBSC: it adds a stronger trust boundary without turning every session renewal into a visible user challenge.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-dbsc-is-not-just-shorter-cookie-expiry\">Why DBSC is not just \"shorter cookie expiry\"<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#why-dbsc-is-not-just-shorter-cookie-expiry\" class=\"hash-link\" aria-label=\"Direct link to Why DBSC is not just &quot;shorter cookie expiry&quot;\" title=\"Direct link to Why DBSC is not just &quot;shorter cookie expiry&quot;\" translate=\"no\">​</a></h2>\n<p>A natural question is:</p>\n<blockquote>\n<p>Why not just make all session cookies expire every five minutes?</p>\n</blockquote>\n<p>Because short expiry alone creates a usability problem.</p>\n<p>If cookies expire too quickly, users are constantly forced to reauthenticate. To avoid that, most systems introduce a long-lived refresh token or long-lived session cookie.</p>\n<p>But then the refresh artifact becomes the new bearer credential.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Short-lived access cookie + long-lived bearer refresh token</span><br></div></code></pre></div></div>\n<p>If malware steals the refresh token, the attacker can continue minting new session cookies.</p>\n<p>DBSC changes that equation.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Traditional refresh:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Refresh token is a bearer credential.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC refresh:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Refresh requires proof of possession of a device-held private key.</span><br></div></code></pre></div></div>\n<p>This is a materially better security/usability tradeoff.</p>\n<p>Users do not need to log in repeatedly, but attackers cannot simply copy the refresh capability to another machine.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-role-of-tpm-the-hardware-root-of-trust\">The role of TPM: the hardware root of trust<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#the-role-of-tpm-the-hardware-root-of-trust\" class=\"hash-link\" aria-label=\"Direct link to The role of TPM: the hardware root of trust\" title=\"Direct link to The role of TPM: the hardware root of trust\" translate=\"no\">​</a></h2>\n<p>The TPM is one of the most important pieces of the DBSC story.</p>\n<p>A <strong>Trusted Platform Module</strong>, or <strong>TPM</strong>, is a hardware-backed cryptographic component designed to generate, protect, and use cryptographic keys. It can create keys whose private material is difficult or impossible to export through ordinary software APIs.</p>\n<p>For DBSC, the browser needs a private key with three properties:</p>\n<ol>\n<li class=\"\">It is generated on the user's device.</li>\n<li class=\"\">It is difficult to export.</li>\n<li class=\"\">It can sign server challenges when session refresh is required.</li>\n</ol>\n<p>That is exactly the kind of problem TPMs are designed to support.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-software-key-storage-is-not-enough\">Why software key storage is not enough<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#why-software-key-storage-is-not-enough\" class=\"hash-link\" aria-label=\"Direct link to Why software key storage is not enough\" title=\"Direct link to Why software key storage is not enough\" translate=\"no\">​</a></h3>\n<p>Imagine Chrome generated a DBSC private key and stored it as a normal file:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">~/Chrome/Profile/DBSC/private-key.pem</span><br></div></code></pre></div></div>\n<p>That would not meaningfully solve cookie theft.</p>\n<p>The same malware that steals cookies could steal the private key file too.</p>\n<p>Then the attacker would have:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">stolen cookie + stolen private key = replayable session</span><br></div></code></pre></div></div>\n<p>At that point, DBSC would collapse back into a bearer-like model.</p>\n<p>The key cannot merely be “local.” It must be protected in a way that makes extraction hard.</p>\n<p>This is where TPM-backed storage matters.</p>\n<p>A TPM-backed key behaves conceptually like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Application: Please sign this challenge.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">TPM:         Here is the signature.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Application: Please give me the private key.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">TPM:         No.</span><br></div></code></pre></div></div>\n<p>The browser can use the key, but it cannot casually export the raw private key material.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tpm-as-a-signing-oracle\">TPM as a signing oracle<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#tpm-as-a-signing-oracle\" class=\"hash-link\" aria-label=\"Direct link to TPM as a signing oracle\" title=\"Direct link to TPM as a signing oracle\" translate=\"no\">​</a></h3>\n<p>In DBSC, the TPM-backed key does not need to decrypt data or reveal secrets. It primarily needs to sign challenges.</p>\n<p>The flow is conceptually:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server creates challenge:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  nonce + session_id + timestamp + origin context</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Chrome asks protected key:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  sign(challenge)</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Chrome sends to server:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  challenge + signature</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server verifies:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  verify(public_key, challenge, signature)</span><br></div></code></pre></div></div>\n<p>If verification succeeds, the server knows that the client can still access the original device-bound private key.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-tpm-proves---and-what-it-does-not\">What TPM proves - and what it does not<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#what-tpm-proves---and-what-it-does-not\" class=\"hash-link\" aria-label=\"Direct link to What TPM proves - and what it does not\" title=\"Direct link to What TPM proves - and what it does not\" translate=\"no\">​</a></h3>\n<p>This nuance is critical.</p>\n<p>TPM-backed DBSC proves:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">The session can still access the original device-bound key.</span><br></div></code></pre></div></div>\n<p>It does <strong>not</strong> prove:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">The device is malware-free.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">The user is physically present.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">The browser process is uncompromised.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">The OS is fully trustworthy.</span><br></div></code></pre></div></div>\n<p>If malware is running on the same machine and can control the browser or trigger signing operations, it may still abuse the active session locally.</p>\n<p>This is sometimes called the <strong>signing oracle problem</strong>.</p>\n<p>A non-exportable TPM key prevents this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Export private key → use it anywhere</span><br></div></code></pre></div></div>\n<p>But it may not fully prevent this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Compromised local device → ask browser/TPM to sign challenge locally</span><br></div></code></pre></div></div>\n<p>So DBSC changes the attacker's path.</p>\n<p>Before DBSC:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Steal cookie → replay anywhere</span><br></div></code></pre></div></div>\n<p>After DBSC:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Steal cookie → short-term access only</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Need original device key → must compromise or operate from original device</span><br></div></code></pre></div></div>\n<p>That is still a huge improvement.</p>\n<p>It turns a scalable remote replay attack into a harder local compromise problem.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbsc-attacks-the-infostealer-business-model\">DBSC attacks the infostealer business model<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbsc-attacks-the-infostealer-business-model\" class=\"hash-link\" aria-label=\"Direct link to DBSC attacks the infostealer business model\" title=\"Direct link to DBSC attacks the infostealer business model\" translate=\"no\">​</a></h2>\n<p>DBSC should not be understood only as a browser feature. It should be understood as an economic attack against infostealer malware.</p>\n<p>Infostealers are profitable because session credentials are portable.</p>\n<p>A typical attacker workflow looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Compromise endpoint</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Extract browser cookies</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Upload cookies to attacker infrastructure</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Sell or replay sessions</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bypass MFA because login already happened</span><br></div></code></pre></div></div>\n<p>The scalability comes from portability. Once a cookie is stolen, the attacker can use it elsewhere.</p>\n<p>DBSC reduces that value.</p>\n<p>With DBSC:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cookie stolen today</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cookie works only until short-lived expiry</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Attacker cannot refresh without original device-bound private key</span><br></div></code></pre></div></div>\n<p>This does not make attacks impossible, but it damages the attacker's return on investment.</p>\n<p>That is what good security architecture often does. It does not merely block one technique; it changes the economics of the attack.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbsc-vs-dpop-same-philosophy-different-layer\">DBSC vs DPoP: same philosophy, different layer<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbsc-vs-dpop-same-philosophy-different-layer\" class=\"hash-link\" aria-label=\"Direct link to DBSC vs DPoP: same philosophy, different layer\" title=\"Direct link to DBSC vs DPoP: same philosophy, different layer\" translate=\"no\">​</a></h2>\n<p>DBSC belongs to a broader family of <strong>proof-of-possession</strong> and <strong>sender-constrained</strong> credential systems.</p>\n<p>OAuth <strong>DPoP</strong>, standardized in RFC 9449, follows a similar principle for OAuth tokens. Instead of allowing a token to be used by anyone who possesses it, DPoP binds token usage to proof that the client possesses a private key.</p>\n<p>The comparison looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bearer token:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  token alone is enough</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DPoP:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  token + proof of private key required</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  cookie + proof of device-bound private key required</span><br></div></code></pre></div></div>\n<p>The philosophy is the same: make stolen credentials harder to replay.</p>\n<p>The difference is where they operate.</p>\n<p>DPoP is primarily an OAuth/API token mechanism.</p>\n<p>DBSC is a browser/session-cookie mechanism.</p>\n<p>That makes DBSC especially relevant for traditional web applications that still rely heavily on cookies and browser-managed session state.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-earlier-token-binding-ideas-struggled\">Why earlier Token Binding ideas struggled<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#why-earlier-token-binding-ideas-struggled\" class=\"hash-link\" aria-label=\"Direct link to Why earlier Token Binding ideas struggled\" title=\"Direct link to Why earlier Token Binding ideas struggled\" translate=\"no\">​</a></h2>\n<p>DBSC is not the first attempt to bind credentials to a client.</p>\n<p>Earlier approaches, such as Token Binding, tried to bind tokens at the TLS layer. The idea was elegant: cryptographically bind tokens to the TLS connection so stolen tokens could not be replayed elsewhere.</p>\n<p>But deployment reality made this hard.</p>\n<p>Modern web infrastructure often looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Browser</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓ TLS</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">CDN / edge proxy</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓ internal routing</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Load balancer</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">API gateway</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Service mesh</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Application service</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Auth/session store</span><br></div></code></pre></div></div>\n<p>The service that owns the session may not be the component terminating the original TLS connection.</p>\n<p>If the proof is too low in the stack, application teams may not be able to reliably consume it.</p>\n<p>DBSC is more pragmatic because it operates closer to HTTP and application session semantics. The auth system that issues and refreshes cookies can also verify device proof.</p>\n<p>That is good architecture: put the security control where the ownership boundary actually exists.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbsc-and-privacy-avoiding-the-supercookie-trap\">DBSC and privacy: avoiding the supercookie trap<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbsc-and-privacy-avoiding-the-supercookie-trap\" class=\"hash-link\" aria-label=\"Direct link to DBSC and privacy: avoiding the supercookie trap\" title=\"Direct link to DBSC and privacy: avoiding the supercookie trap\" translate=\"no\">​</a></h2>\n<p>Any device-binding mechanism immediately raises a privacy concern:</p>\n<blockquote>\n<p>Are we creating a stable device identifier?</p>\n</blockquote>\n<p>If every website received the same hardware-backed public key, DBSC would become a tracking disaster.</p>\n<p>Sites could correlate users across origins and sessions.</p>\n<p>A responsible design must avoid that.</p>\n<p>DBSC's design uses session-specific keys rather than exposing a universal device identity. The goal is to bind <em>this session</em> to <em>this device</em>, not reveal a stable global hardware identity.</p>\n<p>The difference is huge.</p>\n<p>Good design:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Site A session key ≠ Site B session key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Session 1 key ≠ Session 2 key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">No global device identifier exposed</span><br></div></code></pre></div></div>\n<p>Bad design:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Same public key exposed everywhere</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Device becomes trackable across the web</span><br></div></code></pre></div></div>\n<p>Security features that create persistent tracking surfaces will face resistance from browsers, users, regulators, and privacy engineers.</p>\n<p>DBSC is interesting because it tries to improve session security without turning the browser into a device-identification oracle.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-dbsc-actually-stops\">What DBSC actually stops<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#what-dbsc-actually-stops\" class=\"hash-link\" aria-label=\"Direct link to What DBSC actually stops\" title=\"Direct link to What DBSC actually stops\" translate=\"no\">​</a></h2>\n<p>DBSC is strongest against <strong>off-device replay</strong>.</p>\n<p>It helps when the attacker flow is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Malware steals cookie</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Attacker imports cookie into another browser/device</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Attacker tries to continue the session</span><br></div></code></pre></div></div>\n<p>DBSC breaks this flow because the attacker does not have the original device-bound private key needed to refresh the session.</p>\n<p>It also improves defender visibility.</p>\n<p>If attackers can no longer replay cookies from their own infrastructure, they may be forced to act from the compromised user's device. That makes endpoint detection, enterprise device management, browser telemetry, and cleanup more relevant.</p>\n<p>In security terms, DBSC converts a portable credential problem into a device-compromise problem.</p>\n<p>That is not perfect, but it is meaningfully better.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-dbsc-does-not-stop\">What DBSC does not stop<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#what-dbsc-does-not-stop\" class=\"hash-link\" aria-label=\"Direct link to What DBSC does not stop\" title=\"Direct link to What DBSC does not stop\" translate=\"no\">​</a></h2>\n<p>A serious engineering analysis must be clear about boundaries.</p>\n<p>DBSC does <strong>not</strong> fully stop:</p>\n<ol>\n<li class=\"\">Malware actively controlling the browser on the same device.</li>\n<li class=\"\">Remote access trojans operating through the victim's browser.</li>\n<li class=\"\">Malicious browser extensions acting inside the browser context.</li>\n<li class=\"\">XSS that performs actions through the user's active session.</li>\n<li class=\"\">Phishing that causes the user to establish a fresh attacker-controlled session.</li>\n<li class=\"\">Attacks during or before DBSC registration.</li>\n<li class=\"\">Server-side session-store compromise.</li>\n<li class=\"\">Local malware using the device as a signing oracle.</li>\n</ol>\n<p>This does not make DBSC weak. It makes its threat model precise.</p>\n<p>DBSC is an <strong>anti-exfiltration and anti-replay</strong> control. It is not a complete endpoint integrity solution.</p>\n<p>The correct mental model is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC does not prove the user is safe.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC proves the session can still access the original device-bound key.</span><br></div></code></pre></div></div>\n<p>That is still extremely valuable.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbsc-and-passkeys-different-stages-of-trust\">DBSC and passkeys: different stages of trust<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbsc-and-passkeys-different-stages-of-trust\" class=\"hash-link\" aria-label=\"Direct link to DBSC and passkeys: different stages of trust\" title=\"Direct link to DBSC and passkeys: different stages of trust\" translate=\"no\">​</a></h2>\n<p>People may confuse DBSC with passkeys because both use public/private key cryptography and device-associated keys.</p>\n<p>But they solve different problems.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Passkey:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Can this user authenticate to this account?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Can this already-authenticated session still prove it belongs to the original device?</span><br></div></code></pre></div></div>\n<p>Passkeys protect the front door.</p>\n<p>DBSC protects the session after the user has entered.</p>\n<p>A strong modern authentication architecture should combine both:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Passkey login</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        +</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Device-bound session renewal</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        +</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Short-lived cookies</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        +</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Risk-based step-up authentication</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        +</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Session revocation</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        +</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Endpoint posture and detection</span><br></div></code></pre></div></div>\n<p>That is the direction web authentication is moving: fewer reusable secrets and more contextual proof.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dbsc-and-password-sharing\">DBSC and \"password sharing\"<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#dbsc-and-password-sharing\" class=\"hash-link\" aria-label=\"Direct link to DBSC and &quot;password sharing&quot;\" title=\"Direct link to DBSC and &quot;password sharing&quot;\" translate=\"no\">​</a></h2>\n<p>The YouTube video framing around DBSC and password/session sharing is understandable.</p>\n<p>If session state is no longer portable across machines, then copying a logged-in browser profile or cookie jar to another device becomes less useful.</p>\n<p>In that sense, DBSC can make casual session sharing harder.</p>\n<p>But from a security engineering perspective, password sharing is not the deepest point.</p>\n<p>The deeper point is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Attackers should not be able to cheaply replay stolen authenticated sessions at scale.</span><br></div></code></pre></div></div>\n<p>For consumer subscription services, DBSC may also help enforce that sessions remain tied to legitimate devices. But if DBSC is marketed only as anti-sharing, users may perceive it as restrictive DRM.</p>\n<p>The stronger and more accurate framing is session theft protection.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-an-enterprise-auth-team-should-implement-dbsc\">How an enterprise auth team should implement DBSC<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#how-an-enterprise-auth-team-should-implement-dbsc\" class=\"hash-link\" aria-label=\"Direct link to How an enterprise auth team should implement DBSC\" title=\"Direct link to How an enterprise auth team should implement DBSC\" translate=\"no\">​</a></h2>\n<p>If I were designing DBSC adoption for a large-scale company, I would not let every product team independently bolt it onto its own application.</p>\n<p>I would centralize it in the authentication platform.</p>\n<p>A mature architecture would look like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Identity Provider / Auth Gateway</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC registration service</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC refresh service</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Session store / public key registry</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Risk engine</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Observability + security analytics</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"registration-service-responsibilities\">Registration service responsibilities<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#registration-service-responsibilities\" class=\"hash-link\" aria-label=\"Direct link to Registration service responsibilities\" title=\"Direct link to Registration service responsibilities\" translate=\"no\">​</a></h3>\n<p>The registration service should:</p>\n<ul>\n<li class=\"\">Validate that the user recently completed legitimate authentication.</li>\n<li class=\"\">Accept and store the DBSC public key.</li>\n<li class=\"\">Bind the public key to a specific session.</li>\n<li class=\"\">Define cookie scope and refresh policy.</li>\n<li class=\"\">Transition the user from bootstrap session to short-lived bound cookies.</li>\n<li class=\"\">Emit security logs for registration events.</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"refresh-service-responsibilities\">Refresh service responsibilities<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#refresh-service-responsibilities\" class=\"hash-link\" aria-label=\"Direct link to Refresh service responsibilities\" title=\"Direct link to Refresh service responsibilities\" translate=\"no\">​</a></h3>\n<p>The refresh service is even more critical.</p>\n<p>It should:</p>\n<ul>\n<li class=\"\">Generate unpredictable challenges.</li>\n<li class=\"\">Validate signed responses.</li>\n<li class=\"\">Reject stale challenges.</li>\n<li class=\"\">Reject replayed challenges.</li>\n<li class=\"\">Rotate short-lived cookies.</li>\n<li class=\"\">Integrate with session revocation.</li>\n<li class=\"\">Feed suspicious proof failures into the risk engine.</li>\n<li class=\"\">Support controlled fallback for unsupported browsers or devices.</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"observability-requirements\">Observability requirements<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#observability-requirements\" class=\"hash-link\" aria-label=\"Direct link to Observability requirements\" title=\"Direct link to Observability requirements\" translate=\"no\">​</a></h3>\n<p>A DBSC rollout without observability is dangerous.</p>\n<p>Teams need dashboards for:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC registration success rate</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC refresh success rate</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Refresh latency</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Proof validation failures</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Fallback frequency</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Unsupported browser/device percentage</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Sessions still using long-lived bearer cookies</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Suspicious repeated refresh failures</span><br></div></code></pre></div></div>\n<p>DBSC turns the refresh path into part of the authentication control plane. It must be designed with the same seriousness as login infrastructure.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"backend-architecture-pattern\">Backend architecture pattern<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#backend-architecture-pattern\" class=\"hash-link\" aria-label=\"Direct link to Backend architecture pattern\" title=\"Direct link to Backend architecture pattern\" translate=\"no\">​</a></h2>\n<p>A clean backend design treats DBSC as a session-hardening layer.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                ┌────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                │ User authenticates  │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                └─────────┬──────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                          │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                          ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              ┌───────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ Auth service issues   │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ registration header   │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              └─────────┬─────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              ┌───────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ Browser creates key   │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ TPM/Secure Enclave    │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              └─────────┬─────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              ┌───────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ Registration endpoint │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ stores public key     │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              └─────────┬─────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              ┌───────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ Short-lived cookie    │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ issued                │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              └─────────┬─────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              ┌───────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ Refresh endpoint      │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              │ verifies signed proof │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              └───────────────────────┘</span><br></div></code></pre></div></div>\n<p>For high-scale systems, the refresh endpoint must be:</p>\n<ul>\n<li class=\"\">Multi-region</li>\n<li class=\"\">Low latency</li>\n<li class=\"\">Highly available</li>\n<li class=\"\">Rate limited</li>\n<li class=\"\">Replay resistant</li>\n<li class=\"\">Audited</li>\n<li class=\"\">Compatible with CDNs and reverse proxies</li>\n<li class=\"\">Integrated with risk scoring</li>\n<li class=\"\">Integrated with session revocation</li>\n</ul>\n<p>If the refresh service goes down, users may appear logged out even if the main application is healthy.</p>\n<p>That makes DBSC infrastructure part of the critical path.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"risk-based-policy-decisions\">Risk-based policy decisions<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#risk-based-policy-decisions\" class=\"hash-link\" aria-label=\"Direct link to Risk-based policy decisions\" title=\"Direct link to Risk-based policy decisions\" translate=\"no\">​</a></h2>\n<p>DBSC creates new security signals. The question is what the server should do with them.</p>\n<p>For example:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC proof succeeds:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Continue session normally.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC proof fails once:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Retry or gracefully degrade.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC proof repeatedly fails:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Trigger step-up authentication.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC proof fails from suspicious context:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Revoke session and alert.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DBSC unavailable on device:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Use shorter session lifetime and stronger risk checks.</span><br></div></code></pre></div></div>\n<p>This is where DBSC becomes more than protocol plumbing. It becomes part of adaptive access control.</p>\n<p>A mature system should not treat every failure identically. Some failures are benign: browser updates, device migration, corrupted profile state, unsupported hardware, enterprise policy restrictions.</p>\n<p>Other failures may be suspicious: repeated refresh attempts, impossible travel, mismatched device posture, or refresh attempts after known compromise.</p>\n<p>The policy layer matters as much as the cryptography.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-real-architectural-insight\">The real architectural insight<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#the-real-architectural-insight\" class=\"hash-link\" aria-label=\"Direct link to The real architectural insight\" title=\"Direct link to The real architectural insight\" translate=\"no\">​</a></h2>\n<p>The real lesson from DBSC is bigger than Chrome.</p>\n<p>For decades, web security has over-weighted the login moment and under-weighted the session lifetime.</p>\n<p>Most systems ask:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Did the user authenticate correctly at time T0?</span><br></div></code></pre></div></div>\n<p>Attackers increasingly operate after T0.</p>\n<p>They wait until the user is already authenticated, steal the resulting session, and bypass the expensive login security controls.</p>\n<p>Modern security needs to ask better questions:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Should this session still be trusted now?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Is it still on the original device?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Has the risk posture changed?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Can the client prove possession of the original key?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Should this action require step-up authentication?</span><br></div></code></pre></div></div>\n<p>DBSC is valuable because it moves web sessions toward <strong>continuous trust validation</strong> without constantly annoying the user.</p>\n<p>That is the future of authentication: not more prompts, but stronger invisible guarantees.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"final-takeaway\">Final takeaway<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#final-takeaway\" class=\"hash-link\" aria-label=\"Direct link to Final takeaway\" title=\"Direct link to Final takeaway\" translate=\"no\">​</a></h2>\n<p>DBSC is not the death of cookies.</p>\n<p>It is the hardening of cookies.</p>\n<p>It does not replace MFA. It does not replace passkeys. It does not replace endpoint security. It does not prove the device is uncompromised.</p>\n<p>But it fixes one of the worst properties of web sessions:</p>\n<blockquote>\n<p>A stolen cookie should not be a portable identity.</p>\n</blockquote>\n<p>By using device-bound cryptographic keys, ideally protected by TPM or similar hardware-backed mechanisms, DBSC makes session renewal depend on proof from the original device.</p>\n<p>The old model was:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Trust follows the cookie.</span><br></div></code></pre></div></div>\n<p>The DBSC model is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Trust follows the cookie only while the original device can prove possession.</span><br></div></code></pre></div></div>\n<p>That is not a small implementation detail. That is a better trust boundary.</p>\n<p>And in security architecture, better trust boundaries are how the game actually changes.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"references\">References<a href=\"https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials#references\" class=\"hash-link\" aria-label=\"Direct link to References\" title=\"Direct link to References\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a href=\"https://developer.chrome.com/docs/web-platform/device-bound-session-credentials\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Chrome Developers: Device Bound Session Credentials</a></li>\n<li class=\"\"><a href=\"https://security.googleblog.com/2024/04/fighting-cookie-theft-using-device.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Google Security Blog: Fighting cookie theft using device bound sessions</a></li>\n<li class=\"\"><a href=\"https://github.com/WICG/dbsc\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">WICG DBSC Explainer</a></li>\n<li class=\"\"><a href=\"https://wicg.github.io/dbsc/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">W3C Draft: Device Bound Session Credentials</a></li>\n<li class=\"\"><a href=\"https://www.rfc-editor.org/rfc/rfc9449.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">RFC 9449: OAuth 2.0 Demonstrating Proof of Possession</a></li>\n<li class=\"\"><a href=\"https://learn.microsoft.com/windows/security/hardware-security/tpm/trusted-platform-module-overview\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Microsoft: Trusted Platform Module Technology Overview</a></li>\n<li class=\"\"><a href=\"https://cheatsheetseries.owasp.org/cheatsheets/Session_Management_Cheat_Sheet.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">OWASP Session Management Cheat Sheet</a></li>\n<li class=\"\"><a href=\"https://www.youtube.com/watch?v=v6J2A0MV4t8\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">YouTube reference video</a></li>\n</ul>",
            "url": "https://blogs.pranjalkumar.in/blog/chrome-dbsc-device-bound-session-credentials",
            "title": "Chrome DBSC: shift from bearer cookies to device-bound session credentials",
            "summary": "An engineering deep dive into Chrome Device Bound Session Credentials - how TPM-backed keys, proof-of-possession sessions, and short-lived cookies change the web session security model.",
            "date_modified": "2026-05-10T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "security",
                "chrome",
                "authentication",
                "web-security",
                "dbsc",
                "tpm",
                "session-management"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" alt=\"Bloom filter bit array visualization showing how hash functions map elements to bit positions for probabilistic set membership testing | Pranjal Kumar\" src=\"https://blogs.pranjalkumar.in/assets/images/probabilistic-data-structures-bloom-filters-explained%20by%20Pranjal%20Kumar%20-%20software%20engineer-94b8b0ef12c3f69d6dc226c2af08b46d.png\" width=\"1843\" height=\"1229\" class=\"img_ev3q\"></p>\n<blockquote>\n<p>Here's a question that sounds impossible: can you check if an element is in a set of <strong>1 billion items</strong> using only <strong>1.2 GB of RAM</strong>, with lookups completing in <strong>constant time</strong>, and never producing a false negative? Oh, and the data structure is a single contiguous array of bits; no pointers, no allocations, no garbage collection pauses.</p>\n<p>The answer is yes. It's called a Bloom filter, and once you understand it, you'll see it everywhere; from the database engine under your app to Chrome's malicious URL checker to the network switches routing your packets.</p>\n<p>This post goes deep. Not \"here's a pretty diagram\" deep. <em>\"I need to tune the false positive rate for a production system handling 400K QPS\"</em> deep.</p>\n</blockquote>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-probabilistic-data-structures-exist\">Why probabilistic data structures exist<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#why-probabilistic-data-structures-exist\" class=\"hash-link\" aria-label=\"Direct link to Why probabilistic data structures exist\" title=\"Direct link to Why probabilistic data structures exist\" translate=\"no\">​</a></h2>\n<p>Let's start with a confession: <strong>deterministic data structures are expensive.</strong></p>\n<p>A <code>HashSet&lt;String&gt;</code> holding 1 billion URLs? That's roughly:</p>\n<ul>\n<li class=\"\">1 billion pointers (8 bytes each) = 8 GB just for the pointer array</li>\n<li class=\"\">Plus the actual string data (average URL ~80 bytes) = 80 GB</li>\n<li class=\"\">Plus hash table overhead (load factor, tombstones, resizing) = another 30-40%</li>\n</ul>\n<p>You're looking at <strong>~120 GB of RAM</strong> for a set membership test. And every single read might chase a pointer into some random heap location; cache miss city. Your L3 cache is crying.</p>\n<p>Probabilistic data structures trade a small, <em>bounded</em> error rate for massive savings in space and time. They answer a subtly different question: instead of \"is X in the set?\" they answer \"is X <em>definitely not</em> in the set, or <em>probably</em> in the set?\"</p>\n<p>That sounds like a downgrade. But in practice? It's one of the most powerful engineering tradeoffs you can make.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-pool-of-probabilistic-structures\">The pool of probabilistic structures<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-pool-of-probabilistic-structures\" class=\"hash-link\" aria-label=\"Direct link to The pool of probabilistic structures\" title=\"Direct link to The pool of probabilistic structures\" translate=\"no\">​</a></h2>\n<p>Before we go deep on Bloom filters, let me give you the lay of the land:</p>\n<table><thead><tr><th>Structure</th><th>What it answers</th><th>Error type</th><th>Space</th></tr></thead><tbody><tr><td><strong>Bloom filter</strong></td><td>\"Is X in the set?\"</td><td>False positives (never false negatives)</td><td>~10 bits per element for 1% FPR</td></tr><tr><td><strong>Counting Bloom filter</strong></td><td>Same, but supports deletion</td><td>Same</td><td>~40 bits per element</td></tr><tr><td><strong>Cuckoo filter</strong></td><td>Same, supports deletion, often better FPR</td><td>False positives</td><td>~12 bits per element for &lt;1% FPR</td></tr><tr><td><strong>HyperLogLog</strong></td><td>\"How many distinct elements?\"</td><td>±0.8% error</td><td>12 KB (!) for billions of elements</td></tr><tr><td><strong>Count-Min Sketch</strong></td><td>\"How many times has X appeared?\"</td><td>Over-estimates only</td><td>O(1/ε × log(1/δ))</td></tr><tr><td><strong>Quotient filter</strong></td><td>\"Is X in the set?\" (cache-friendly)</td><td>False positives</td><td>~10-12 bits per element</td></tr><tr><td><strong>XOR filter</strong></td><td>\"Is X in the set?\" (immutable, faster)</td><td>False positives</td><td>~9 bits per element</td></tr></tbody></table>\n<p>Each one is beautiful in its own way. But Bloom filters are the gateway drug; once you grok them, the rest click into place.</p>\n<blockquote>\n<p><em><strong>FPR:</strong> False Positive Rate</em></p>\n</blockquote>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"bloom-filters-from-first-principles\">Bloom filters from first principles<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#bloom-filters-from-first-principles\" class=\"hash-link\" aria-label=\"Direct link to Bloom filters from first principles\" title=\"Direct link to Bloom filters from first principles\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-simplest-possible-explanation\">The simplest possible explanation<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-simplest-possible-explanation\" class=\"hash-link\" aria-label=\"Direct link to The simplest possible explanation\" title=\"Direct link to The simplest possible explanation\" translate=\"no\">​</a></h3>\n<p>A Bloom filter is:</p>\n<ol>\n<li class=\"\">A <strong>bit array</strong> of <code>m</code> bits, all initialized to 0</li>\n<li class=\"\"><code>k</code> independent <strong>hash functions</strong>, each mapping an element to a position in <code>[0, m)</code></li>\n</ol>\n<p><strong>To add</strong> element <code>x</code>: compute <code>h₁(x), h₂(x), ..., hₖ(x)</code> and set those bit positions to 1.</p>\n<p><strong>To query</strong> element <code>x</code>: compute the same hashes. If <em>all</em> <code>k</code> positions are 1, answer \"probably yes.\" If <em>any</em> position is 0, answer \"definitely no.\"</p>\n<p>That's it. That's the whole thing. No linked lists, no trees, no rebalancing, no resizing. Just bits and hashes.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-false-negatives-are-impossible\">Why false negatives are impossible<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#why-false-negatives-are-impossible\" class=\"hash-link\" aria-label=\"Direct link to Why false negatives are impossible\" title=\"Direct link to Why false negatives are impossible\" translate=\"no\">​</a></h3>\n<p>Think about it: if we added element <code>x</code>, we set bits at positions <code>h₁(x)</code> through <code>hₖ(x)</code>. We never <em>unset</em> bits. So when we query <code>x</code> later, those positions will <em>still</em> be 1. Always. The filter never forgets what it's seen.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-false-positives-happen\">Why false positives happen<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#why-false-positives-happen\" class=\"hash-link\" aria-label=\"Direct link to Why false positives happen\" title=\"Direct link to Why false positives happen\" translate=\"no\">​</a></h3>\n<p>But other elements might have <em>also</em> set those same positions. If elements <code>a</code>, <code>b</code>, and <code>c</code> collectively lit up the same bit positions that <code>h₁(x)</code> through <code>hₖ(x)</code> would need; then querying <code>x</code> returns \"probably yes\" even though <code>x</code> was never inserted. The bits don't remember <em>who</em> set them.</p>\n<p>This is the tradeoff. And it's quantifiable.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-math-and-why-you-should-actually-understand-it\">The math; and why you should actually understand it<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-math-and-why-you-should-actually-understand-it\" class=\"hash-link\" aria-label=\"Direct link to The math; and why you should actually understand it\" title=\"Direct link to The math; and why you should actually understand it\" translate=\"no\">​</a></h2>\n<p>I know, I know; \"just tell me what parameters to use.\" But if you don't understand the math, you can't tune these things in production. And you <em>will</em> need to tune them. Trust me.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"false-positive-probability\">False positive probability<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#false-positive-probability\" class=\"hash-link\" aria-label=\"Direct link to False positive probability\" title=\"Direct link to False positive probability\" translate=\"no\">​</a></h3>\n<p>For a Bloom filter with <code>m</code> bits, <code>k</code> hash functions, and <code>n</code> inserted elements:</p>\n<p>The probability a specific bit is still 0 after all insertions:</p>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>P</mi><mo stretchy=\"false\">(</mo><mtext>bit</mtext><mo>=</mo><mn>0</mn><mo stretchy=\"false\">)</mo><mo>=</mo><msup><mrow><mo fence=\"true\">(</mo><mn>1</mn><mo>−</mo><mfrac><mn>1</mn><mi>m</mi></mfrac><mo fence=\"true\">)</mo></mrow><mrow><mi>k</mi><mi>n</mi></mrow></msup><mo>≈</mo><msup><mi>e</mi><mrow><mo>−</mo><mi>k</mi><mi>n</mi><mi mathvariant=\"normal\">/</mi><mi>m</mi></mrow></msup></mrow><annotation encoding=\"application/x-tex\">P(\\text{bit} = 0) = \\left(1 - \\frac{1}{m}\\right)^{kn} \\approx e^{-kn/m}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.1389em\">P</span><span class=\"mopen\">(</span><span class=\"mord text\"><span class=\"mord\">bit</span></span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord\">0</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.439em;vertical-align:-0.35em\"></span><span class=\"minner\"><span class=\"minner\"><span class=\"mopen delimcenter\" style=\"top:0em\"><span class=\"delimsizing size1\">(</span></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.8451em\"><span style=\"top:-2.655em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">m</span></span></span></span><span style=\"top:-3.23em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em\"></span></span><span style=\"top:-3.394em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">1</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mclose delimcenter\" style=\"top:0em\"><span class=\"delimsizing size1\">)</span></span></span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.089em\"><span style=\"top:-3.3029em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.0315em\">k</span><span class=\"mord mathnormal mtight\">n</span></span></span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">≈</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.888em\"></span><span class=\"mord\"><span class=\"mord mathnormal\">e</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.888em\"><span style=\"top:-3.063em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">−</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.0315em\">k</span><span class=\"mord mathnormal mtight\">n</span><span class=\"mord mtight\">/</span><span class=\"mord mathnormal mtight\">m</span></span></span></span></span></span></span></span></span></span></span></span></p>\n<p>The false positive probability (all <code>k</code> bits are 1 for an element not in the set):</p>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mi>P</mi><mo stretchy=\"false\">(</mo><mtext>FP</mtext><mo stretchy=\"false\">)</mo><mo>=</mo><msup><mrow><mo fence=\"true\">(</mo><mn>1</mn><mo>−</mo><msup><mi>e</mi><mrow><mo>−</mo><mi>k</mi><mi>n</mi><mi mathvariant=\"normal\">/</mi><mi>m</mi></mrow></msup><mo fence=\"true\">)</mo></mrow><mi>k</mi></msup></mrow><annotation encoding=\"application/x-tex\">P(\\text{FP}) = \\left(1 - e^{-kn/m}\\right)^k</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.1389em\">P</span><span class=\"mopen\">(</span><span class=\"mord text\"><span class=\"mord\">FP</span></span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.477em;vertical-align:-0.35em\"></span><span class=\"minner\"><span class=\"minner\"><span class=\"mopen delimcenter\" style=\"top:0em\"><span class=\"delimsizing size1\">(</span></span><span class=\"mord\">1</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mord\"><span class=\"mord mathnormal\">e</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.888em\"><span style=\"top:-3.063em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mtight\">−</span><span class=\"mord mathnormal mtight\" style=\"margin-right:0.0315em\">k</span><span class=\"mord mathnormal mtight\">n</span><span class=\"mord mtight\">/</span><span class=\"mord mathnormal mtight\">m</span></span></span></span></span></span></span></span></span><span class=\"mclose delimcenter\" style=\"top:0em\"><span class=\"delimsizing size1\">)</span></span></span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:1.127em\"><span style=\"top:-3.3409em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\" style=\"margin-right:0.0315em\">k</span></span></span></span></span></span></span></span></span></span></span></p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"optimal-number-of-hash-functions\">Optimal number of hash functions<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#optimal-number-of-hash-functions\" class=\"hash-link\" aria-label=\"Direct link to Optimal number of hash functions\" title=\"Direct link to Optimal number of hash functions\" translate=\"no\">​</a></h3>\n<p>Given <code>m</code> and <code>n</code>, the optimal <code>k</code> that minimizes false positive rate:</p>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>k</mi><mtext>opt</mtext></msub><mo>=</mo><mfrac><mi>m</mi><mi>n</mi></mfrac><mi>ln</mi><mo>⁡</mo><mn>2</mn><mo>≈</mo><mn>0.693</mn><mo>⋅</mo><mfrac><mi>m</mi><mi>n</mi></mfrac></mrow><annotation encoding=\"application/x-tex\">k_{\\text{opt}} = \\frac{m}{n} \\ln 2 \\approx 0.693 \\cdot \\frac{m}{n}</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:0.9805em;vertical-align:-0.2861em\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.0315em\">k</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2806em\"><span style=\"top:-2.55em;margin-left:-0.0315em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord text mtight\"><span class=\"mord mtight\">opt</span></span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2861em\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0404em;vertical-align:-0.345em\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6954em\"><span style=\"top:-2.655em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span style=\"top:-3.23em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em\"></span></span><span style=\"top:-3.394em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">m</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mop\">ln</span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord\">2</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">≈</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em\"></span><span class=\"mord\">0.693</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.0404em;vertical-align:-0.345em\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6954em\"><span style=\"top:-2.655em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span style=\"top:-3.23em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em\"></span></span><span style=\"top:-3.394em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">m</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span></span></span></span></p>\n<p>This is a beautiful result. It says: for a given bits-per-element ratio, there's a sweet spot for the number of hashes. Too few hashes → not enough discrimination. Too many hashes → you fill up the bit array too fast.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"required-bits-per-element\">Required bits per element<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#required-bits-per-element\" class=\"hash-link\" aria-label=\"Direct link to Required bits per element\" title=\"Direct link to Required bits per element\" translate=\"no\">​</a></h3>\n<p>If you want a false positive rate of <code>p</code>:</p>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><mfrac><mi>m</mi><mi>n</mi></mfrac><mo>=</mo><mo>−</mo><mfrac><mrow><mi>ln</mi><mo>⁡</mo><mi>p</mi></mrow><mrow><mo stretchy=\"false\">(</mo><mi>ln</mi><mo>⁡</mo><mn>2</mn><msup><mo stretchy=\"false\">)</mo><mn>2</mn></msup></mrow></mfrac><mo>≈</mo><mo>−</mo><mn>1.44</mn><mo>⋅</mo><msub><mrow><mi>log</mi><mo>⁡</mo></mrow><mn>2</mn></msub><mi>p</mi></mrow><annotation encoding=\"application/x-tex\">\\frac{m}{n} = -\\frac{\\ln p}{(\\ln 2)^2} \\approx -1.44 \\cdot \\log_2 p</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1.0404em;vertical-align:-0.345em\"></span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.6954em\"><span style=\"top:-2.655em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">n</span></span></span></span><span style=\"top:-3.23em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em\"></span></span><span style=\"top:-3.394em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mord mathnormal mtight\">m</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.345em\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1.4522em;vertical-align:-0.52em\"></span><span class=\"mord\">−</span><span class=\"mord\"><span class=\"mopen nulldelimiter\"></span><span class=\"mfrac\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.9322em\"><span style=\"top:-2.655em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mopen mtight\">(</span><span class=\"mop mtight\"><span class=\"mtight\">l</span><span class=\"mtight\">n</span></span><span class=\"mspace mtight\" style=\"margin-right:0.1952em\"></span><span class=\"mord mtight\">2</span><span class=\"mclose mtight\"><span class=\"mclose mtight\">)</span><span class=\"msupsub\"><span class=\"vlist-t\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.7463em\"><span style=\"top:-2.786em;margin-right:0.0714em\"><span class=\"pstrut\" style=\"height:2.5em\"></span><span class=\"sizing reset-size3 size1 mtight\"><span class=\"mord mtight\">2</span></span></span></span></span></span></span></span></span></span></span><span style=\"top:-3.23em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"frac-line\" style=\"border-bottom-width:0.04em\"></span></span><span style=\"top:-3.4461em\"><span class=\"pstrut\" style=\"height:3em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\"><span class=\"mop mtight\"><span class=\"mtight\">l</span><span class=\"mtight\">n</span></span><span class=\"mspace mtight\" style=\"margin-right:0.1952em\"></span><span class=\"mord mathnormal mtight\">p</span></span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.52em\"><span></span></span></span></span></span><span class=\"mclose nulldelimiter\"></span></span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">≈</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.7278em;vertical-align:-0.0833em\"></span><span class=\"mord\">−</span><span class=\"mord\">1.44</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.9386em;vertical-align:-0.2441em\"></span><span class=\"mop\"><span class=\"mop\">lo<span style=\"margin-right:0.0139em\">g</span></span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.207em\"><span style=\"top:-2.4559em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.2441em\"><span></span></span></span></span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord mathnormal\">p</span></span></span></span></p>\n<p>Let's make this concrete:</p>\n<table><thead><tr><th>Desired FP rate</th><th>Bits per element</th><th>Hash functions (k)</th></tr></thead><tbody><tr><td>10%</td><td>4.8</td><td>3</td></tr><tr><td>1%</td><td>9.6</td><td>7</td></tr><tr><td>0.1%</td><td>14.4</td><td>10</td></tr><tr><td>0.01%</td><td>19.2</td><td>13</td></tr><tr><td>0.001%</td><td>24.0</td><td>17</td></tr></tbody></table>\n<p><strong>The takeaway:</strong> each additional order of magnitude in accuracy costs ~4.8 bits per element. That's incredibly space-efficient. A 1% false positive Bloom filter uses <strong>~1.2 bytes per element</strong> regardless of element size; whether you're storing 10-byte integers or 10 KB URLs.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"implementation-the-parts-nobody-tells-you-about\">Implementation; the parts nobody tells you about<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#implementation-the-parts-nobody-tells-you-about\" class=\"hash-link\" aria-label=\"Direct link to Implementation; the parts nobody tells you about\" title=\"Direct link to Implementation; the parts nobody tells you about\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-hash-function-problem\">The hash function problem<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-hash-function-problem\" class=\"hash-link\" aria-label=\"Direct link to The hash function problem\" title=\"Direct link to The hash function problem\" translate=\"no\">​</a></h3>\n<p>The textbook says \"use <code>k</code> independent hash functions.\" In practice, nobody does this. Computing k independent hashes is expensive, and you don't actually need independence.</p>\n<p><strong>Kirsch-Mitzenmacker optimization (2006):</strong> You can simulate <code>k</code> hash functions using only <strong>two</strong> hash functions:</p>\n<p><span class=\"katex\"><span class=\"katex-mathml\"><math xmlns=\"http://www.w3.org/1998/Math/MathML\"><semantics><mrow><msub><mi>g</mi><mi>i</mi></msub><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>=</mo><msub><mi>h</mi><mn>1</mn></msub><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mo>+</mo><mi>i</mi><mo>⋅</mo><msub><mi>h</mi><mn>2</mn></msub><mo stretchy=\"false\">(</mo><mi>x</mi><mo stretchy=\"false\">)</mo><mspace></mspace><mspace width=\"0.6667em\"></mspace><mrow><mi mathvariant=\"normal\">m</mi><mi mathvariant=\"normal\">o</mi><mi mathvariant=\"normal\">d</mi></mrow><mtext> </mtext><mtext> </mtext><mi>m</mi><mo separator=\"true\">,</mo><mspace width=\"1em\"></mspace><mi>i</mi><mo>=</mo><mn>0</mn><mo separator=\"true\">,</mo><mn>1</mn><mo separator=\"true\">,</mo><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mi mathvariant=\"normal\">.</mi><mo separator=\"true\">,</mo><mi>k</mi><mo>−</mo><mn>1</mn></mrow><annotation encoding=\"application/x-tex\">g_i(x) = h_1(x) + i \\cdot h_2(x) \\mod m, \\quad i = 0, 1, ..., k-1</annotation></semantics></math></span><span class=\"katex-html\" aria-hidden=\"true\"><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord\"><span class=\"mord mathnormal\" style=\"margin-right:0.0359em\">g</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3117em\"><span style=\"top:-2.55em;margin-left:-0.0359em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mathnormal mtight\">i</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord\"><span class=\"mord mathnormal\">h</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">1</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">+</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6595em\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">⋅</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:1em;vertical-align:-0.25em\"></span><span class=\"mord\"><span class=\"mord mathnormal\">h</span><span class=\"msupsub\"><span class=\"vlist-t vlist-t2\"><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.3011em\"><span style=\"top:-2.55em;margin-left:0em;margin-right:0.05em\"><span class=\"pstrut\" style=\"height:2.7em\"></span><span class=\"sizing reset-size6 size3 mtight\"><span class=\"mord mtight\">2</span></span></span></span><span class=\"vlist-s\">​</span></span><span class=\"vlist-r\"><span class=\"vlist\" style=\"height:0.15em\"><span></span></span></span></span></span></span><span class=\"mopen\">(</span><span class=\"mord mathnormal\">x</span><span class=\"mclose\">)</span><span class=\"mspace allowbreak\"></span><span class=\"mspace\" style=\"margin-right:0.6667em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em\"></span><span class=\"mord\"><span class=\"mord\"><span class=\"mord mathrm\">mod</span></span></span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord mathnormal\">m</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:1em\"></span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord mathnormal\">i</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span><span class=\"mrel\">=</span><span class=\"mspace\" style=\"margin-right:0.2778em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.8889em;vertical-align:-0.1944em\"></span><span class=\"mord\">0</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord\">1</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord\">...</span><span class=\"mpunct\">,</span><span class=\"mspace\" style=\"margin-right:0.1667em\"></span><span class=\"mord mathnormal\" style=\"margin-right:0.0315em\">k</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span><span class=\"mbin\">−</span><span class=\"mspace\" style=\"margin-right:0.2222em\"></span></span><span class=\"base\"><span class=\"strut\" style=\"height:0.6444em\"></span><span class=\"mord\">1</span></span></span></span></p>\n<p>This gives the same asymptotic false positive rate as <code>k</code> truly independent hashes. In practice, people use:</p>\n<ul>\n<li class=\"\"><strong>MurmurHash3</strong>; fast, excellent distribution, 128-bit output gives you two 64-bit hashes</li>\n<li class=\"\"><strong>xxHash</strong>; even faster, modern SIMD-friendly design</li>\n<li class=\"\"><strong>SipHash</strong>; if you need cryptographic-grade collision resistance (usually you don't)</li>\n</ul>\n<p>Here's what this looks like in practice:</p>\n<div class=\"language-rust codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-rust codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">fn</span><span class=\"token plain\"> </span><span class=\"token function-definition function\" style=\"color:hsl(207, 82%, 66%)\">get_bit_positions</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">item</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&amp;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u8</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> num_hashes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u32</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> num_bits</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u64</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">-&gt;</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">Vec</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u64</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">let</span><span class=\"token plain\"> hash </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">murmurhash3_x64_128</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">item</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">let</span><span class=\"token plain\"> h1 </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> hash </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">as</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u64</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">let</span><span class=\"token plain\"> h2 </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">hash </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;&gt;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">64</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">as</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u64</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">..</span><span class=\"token plain\">num_hashes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">map</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token closure-params closure-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">|</span><span class=\"token closure-params\">i</span><span class=\"token closure-params closure-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">|</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">            h1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">wrapping_add</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">i </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">as</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">u64</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">wrapping_mul</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">h2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">%</span><span class=\"token plain\"> num_bits</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">collect</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><br></div></code></pre></div></div>\n<p>Two hashes, <code>k</code> bit positions. Simple, fast, and proven correct.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"bit-array-implementation\">Bit array implementation<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#bit-array-implementation\" class=\"hash-link\" aria-label=\"Direct link to Bit array implementation\" title=\"Direct link to Bit array implementation\" translate=\"no\">​</a></h3>\n<p>The bit array seems trivial; just <code>malloc(m / 8)</code> bytes, right? In theory, yes. In practice, there are a few gotchas that separate a toy implementation from a production one:</p>\n<div class=\"language-c codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-c codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Setting a bit</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">void</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">bloom_set</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">uint8_t</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\">filter</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">uint64_t</span><span class=\"token plain\"> pos</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    filter</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">pos </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;&gt;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">3</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">|=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;&lt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">pos </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&amp;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">7</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Testing a bit</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">bool </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">bloom_test</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">uint8_t</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\">filter</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">uint64_t</span><span class=\"token plain\"> pos</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> filter</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">pos </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;&gt;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">3</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&amp;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;&lt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">pos </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&amp;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">7</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><br></div></code></pre></div></div>\n<p><strong>Cache line awareness:</strong> On modern CPUs, a cache line is 64 bytes (512 bits). If your <code>k</code> hash outputs are spread uniformly across a large filter, each query potentially touches <code>k</code> different cache lines. For a 1 GB filter with k=7, you're looking at 7 cache misses per lookup; at ~100 ns each, that's 700 ns per query.</p>\n<p><strong>Blocked Bloom filters</strong> solve this: partition the bit array into cache-line-sized blocks. Hash the element to pick a block, then do all <code>k</code> hash probes <em>within</em> that block. You lose a bit of theoretical FP optimality, but you gain cache-friendliness that more than compensates in practice.</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">Traditional</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> k probes scattered across m bits → k cache misses</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">Blocked</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">     </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> hash to select block </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> k probes within </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">512</span><span class=\"token plain\"> bits → </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> cache miss</span><br></div></code></pre></div></div>\n<p>I've seen this take query time from ~500 ns to ~50 ns on real hardware. A 10x improvement just from thinking about cache lines.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"memory-mapped-filters\">Memory-mapped filters<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#memory-mapped-filters\" class=\"hash-link\" aria-label=\"Direct link to Memory-mapped filters\" title=\"Direct link to Memory-mapped filters\" translate=\"no\">​</a></h3>\n<p>For filters that don't fit in RAM (or that you want to persist across process restarts), <code>mmap</code> is your friend:</p>\n<div class=\"language-c codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-c codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">int</span><span class=\"token plain\"> fd </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">open</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"bloom.dat\"</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> O_RDWR </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">|</span><span class=\"token plain\"> O_CREAT</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0644</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">ftruncate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">fd</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> filter_size_bytes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token class-name\" style=\"color:hsl(29, 54%, 61%)\">uint8_t</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\">filter </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">mmap</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">NULL</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> filter_size_bytes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                        PROT_READ </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">|</span><span class=\"token plain\"> PROT_WRITE</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> MAP_SHARED</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> fd</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><br></div></code></pre></div></div>\n<p>The OS handles paging; hot parts stay in RAM, cold parts stay on disk. This is exactly how databases like RocksDB implement their Bloom filters: they're part of the SST file format and get <code>mmap</code>'d when the file is opened.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-bloom-filters-live-in-the-real-world\">Where Bloom filters live in the real world<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#where-bloom-filters-live-in-the-real-world\" class=\"hash-link\" aria-label=\"Direct link to Where Bloom filters live in the real world\" title=\"Direct link to Where Bloom filters live in the real world\" translate=\"no\">​</a></h2>\n<p>This isn't academic. Bloom filters are everywhere in production systems. Let me walk you through the ones I find most interesting.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"lsm-tree-databases-rocksdb-leveldb-cassandra-hbase\">LSM-tree databases (RocksDB, LevelDB, Cassandra, HBase)<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#lsm-tree-databases-rocksdb-leveldb-cassandra-hbase\" class=\"hash-link\" aria-label=\"Direct link to LSM-tree databases (RocksDB, LevelDB, Cassandra, HBase)\" title=\"Direct link to LSM-tree databases (RocksDB, LevelDB, Cassandra, HBase)\" translate=\"no\">​</a></h3>\n<p>This is probably the most impactful use. In an LSM-tree, data lives in sorted immutable files (SSTables) across multiple levels. A point lookup (<code>GET key</code>) might need to check <em>every</em> SSTable for the key.</p>\n<p>Without Bloom filters: reading a non-existent key requires checking all SSTables → potentially dozens of disk reads → unacceptable latency.</p>\n<p>With Bloom filters: each SSTable has an associated Bloom filter (stored in the file's metadata block). Before reading the SSTable's data blocks, check the filter. If it says \"definitely not here\" → skip the file entirely. Zero disk I/O for that SSTable.</p>\n<p><strong>Impact:</strong> RocksDB's documentation states that Bloom filters reduce read amplification by 10-100x for point lookups. Cassandra uses them on every SSTable, and a misconfigured <code>bloom_filter_fp_chance</code> (their tuning knob) is one of the most common causes of read latency spikes I've seen in production.</p>\n<div class=\"language-yaml codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-yaml codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># Cassandra table options</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">CREATE TABLE users (</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">...</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">) WITH bloom_filter_fp_chance = 0.01;  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">-</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">-</span><span class=\"token plain\"> 1% FP rate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> ~10 bits/key</span><br></div></code></pre></div></div>\n<p>Changing this from 0.01 to 0.001 doubles memory usage but reduces unnecessary disk reads by 10x. Whether that's worth it depends entirely on your read/write ratio.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"chromes-safe-browsing\">Chrome's Safe Browsing<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#chromes-safe-browsing\" class=\"hash-link\" aria-label=\"Direct link to Chrome's Safe Browsing\" title=\"Direct link to Chrome's Safe Browsing\" translate=\"no\">​</a></h3>\n<p>Your browser maintains a local Bloom filter of ~4 million malicious URLs. When you navigate to a page, Chrome checks the URL against this filter <em>locally</em>; no network request needed. If the filter says \"definitely not malicious\" (which is &gt;99.99% of the time), you proceed instantly.</p>\n<p>If the filter says \"maybe malicious,\" Chrome then makes an API call to Google's Safe Browsing service for a definitive answer. The Bloom filter turned a network round-trip on every single navigation into a network round-trip on 0.01% of navigations.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cdn-cache-routing-akamai-cloudflare\">CDN cache routing (Akamai, Cloudflare)<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#cdn-cache-routing-akamai-cloudflare\" class=\"hash-link\" aria-label=\"Direct link to CDN cache routing (Akamai, Cloudflare)\" title=\"Direct link to CDN cache routing (Akamai, Cloudflare)\" translate=\"no\">​</a></h3>\n<p>When a CDN edge node receives a request, it needs to know if the content is cached <em>somewhere in the cluster</em> before fetching from origin. The nodes share Bloom filter summaries of their cache contents. A request arrives → check all peer filters → if any say \"maybe here\" → ask that peer → otherwise fetch from origin.</p>\n<p>This is why CDNs can maintain hit rates &gt;95% even with object counts in the hundreds of billions.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"network-routers-packet-forwarding\">Network routers (packet forwarding)<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#network-routers-packet-forwarding\" class=\"hash-link\" aria-label=\"Direct link to Network routers (packet forwarding)\" title=\"Direct link to Network routers (packet forwarding)\" translate=\"no\">​</a></h3>\n<p>Hardware routers use Bloom filters in TCAM (Ternary Content-Addressable Memory) for longest-prefix match in routing tables. At 100 Gbps line rate, you have ~6.7 nanoseconds per packet. A Bloom filter in SRAM gives you constant-time membership checks at wire speed.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"bitcoin-spv-clients\">Bitcoin SPV clients<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#bitcoin-spv-clients\" class=\"hash-link\" aria-label=\"Direct link to Bitcoin SPV clients\" title=\"Direct link to Bitcoin SPV clients\" translate=\"no\">​</a></h3>\n<p>Lightweight Bitcoin wallets use Bloom filters to request only <em>relevant</em> transactions from full nodes without revealing which addresses they own (BIP 37). The wallet sends a Bloom filter of its addresses to the full node, which then only forwards transactions matching the filter. Privacy through false positives; the node can't tell which matches are real and which are noise.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"spell-checkers-the-og-use-case\">Spell checkers (the OG use case)<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#spell-checkers-the-og-use-case\" class=\"hash-link\" aria-label=\"Direct link to Spell checkers (the OG use case)\" title=\"Direct link to Spell checkers (the OG use case)\" translate=\"no\">​</a></h3>\n<p>The original 1970 Bloom filter paper by Burton Bloom was literally about spell checking. Store a dictionary in a Bloom filter. Check each word in the document. If the filter says \"not in dictionary\" → it's definitely misspelled. If it says \"in dictionary\" → it's <em>probably</em> spelled correctly (and you can do a more expensive exact check if needed).</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-variants-because-vanilla-isnt-always-enough\">The variants; because vanilla isn't always enough<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-variants-because-vanilla-isnt-always-enough\" class=\"hash-link\" aria-label=\"Direct link to The variants; because vanilla isn't always enough\" title=\"Direct link to The variants; because vanilla isn't always enough\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"counting-bloom-filters\">Counting Bloom filters<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#counting-bloom-filters\" class=\"hash-link\" aria-label=\"Direct link to Counting Bloom filters\" title=\"Direct link to Counting Bloom filters\" translate=\"no\">​</a></h3>\n<p><strong>The problem:</strong> standard Bloom filters don't support deletion. You can't unset a bit because you don't know if other elements also need that bit.</p>\n<p><strong>The solution:</strong> replace each bit with a <strong>counter</strong> (typically 4 bits). Insert increments, delete decrements. A position is \"set\" if its counter &gt; 0.</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">Standard</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\">    ← </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> bit per position</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">Counting</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">3</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\">    ← </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">4</span><span class=\"token plain\"> bits per position</span><br></div></code></pre></div></div>\n<p><strong>Tradeoff:</strong> 4x the space (4 bits instead of 1 per position). And there's a counter overflow risk; if more than 15 elements hash to the same position, the 4-bit counter wraps. In practice, the probability of this is negligible for properly sized filters.</p>\n<p><strong>When to use:</strong> when your set changes over time and you need to remove elements. Think: \"which users are currently online?\"; users go offline, and you need to remove them.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cuckoo-filters\">Cuckoo filters<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#cuckoo-filters\" class=\"hash-link\" aria-label=\"Direct link to Cuckoo filters\" title=\"Direct link to Cuckoo filters\" translate=\"no\">​</a></h3>\n<p>I think cuckoo filters are underrated. They were introduced by Fan et al. in 2014 and in many practical scenarios they're just... better.</p>\n<p><strong>How they work:</strong> instead of <code>k</code> bit positions, store a <strong>fingerprint</strong> (compact hash) of each element in one of two candidate bucket positions (using cuckoo hashing; hence the name).</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Bucket</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₁</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₂</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\">    ← </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">4</span><span class=\"token plain\"> slots per bucket</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Bucket</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₃</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Bucket</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₄</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₅</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">fp₆</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token spread operator\" style=\"color:hsl(207, 82%, 66%)\">...</span><br></div></code></pre></div></div>\n<p>To insert: compute two candidate buckets via <code>h₁(x)</code> and <code>h₂(x) = h₁(x) ⊕ hash(fingerprint(x))</code>. If either has space, place the fingerprint. If both are full, evict an existing fingerprint to its alternative bucket (cuckoo displacement). Repeat until placed or max iterations reached.</p>\n<p>To query: check both candidate buckets for the fingerprint.</p>\n<p><strong>Advantages over Bloom filters:</strong></p>\n<ul>\n<li class=\"\"><strong>Supports deletion</strong> (just remove the fingerprint) without the 4x overhead of counting</li>\n<li class=\"\"><strong>Better space efficiency</strong> at FP rates below ~3%</li>\n<li class=\"\"><strong>Better cache performance</strong>; at most 2 cache misses per lookup</li>\n</ul>\n<p><strong>Disadvantages:</strong></p>\n<ul>\n<li class=\"\">Insertion can fail if the table is too full (&gt;95% load)</li>\n<li class=\"\">Implementation is more complex</li>\n<li class=\"\">Not as embarrassingly parallelizable</li>\n</ul>\n<p>Here's the crossover point I use as a rule of thumb:</p>\n<ul>\n<li class=\"\">FP rate &gt; 3%: Bloom filter wins on space</li>\n<li class=\"\">FP rate &lt; 3%: Cuckoo filter wins</li>\n<li class=\"\">Need deletion: Cuckoo filter (or counting Bloom with 4x penalty)</li>\n<li class=\"\">Maximum simplicity: Bloom filter, always</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"scalable-bloom-filters\">Scalable Bloom filters<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#scalable-bloom-filters\" class=\"hash-link\" aria-label=\"Direct link to Scalable Bloom filters\" title=\"Direct link to Scalable Bloom filters\" translate=\"no\">​</a></h3>\n<p>Standard Bloom filters require you to know <code>n</code> (number of elements) upfront. What if you don't? Scalable Bloom filters (Almeida et al., 2007) solve this:</p>\n<ul>\n<li class=\"\">Start with a small initial filter</li>\n<li class=\"\">When the estimated fill ratio exceeds a threshold, allocate a <em>new</em> filter with a tighter FP rate</li>\n<li class=\"\">Query checks all filters (OR of results)</li>\n<li class=\"\">Each successive filter has a geometrically tighter FP rate so the overall error stays bounded</li>\n</ul>\n<p>This is what Redis uses in its <code>BF.ADD</code>/<code>BF.EXISTS</code> implementation; it auto-scales without requiring you to pre-declare the capacity.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"xor-filters-and-ribbon-filters\">XOR filters (and Ribbon filters)<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#xor-filters-and-ribbon-filters\" class=\"hash-link\" aria-label=\"Direct link to XOR filters (and Ribbon filters)\" title=\"Direct link to XOR filters (and Ribbon filters)\" translate=\"no\">​</a></h3>\n<p>If your set is <strong>static</strong> (built once, queried many times), XOR filters are the new hotness:</p>\n<ul>\n<li class=\"\">~9 bits per element (vs. ~10 for Bloom filters at same FP rate)</li>\n<li class=\"\">Exactly 3 memory accesses per query (no variance)</li>\n<li class=\"\">Construction uses a peeling algorithm on a random 3-hypergraph</li>\n</ul>\n<p>The downside: you can't add elements after construction. It's an immutable snapshot. Perfect for SSTable-level filters in databases (you build the filter when the SSTable is written and never modify it), but useless for streaming membership tracking.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"production-tuning-the-stuff-they-dont-teach-in-school\">Production tuning; the stuff they don't teach in school<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#production-tuning-the-stuff-they-dont-teach-in-school\" class=\"hash-link\" aria-label=\"Direct link to Production tuning; the stuff they don't teach in school\" title=\"Direct link to Production tuning; the stuff they don't teach in school\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"sizing-for-your-workload\">Sizing for your workload<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#sizing-for-your-workload\" class=\"hash-link\" aria-label=\"Direct link to Sizing for your workload\" title=\"Direct link to Sizing for your workload\" translate=\"no\">​</a></h3>\n<p>Here's my mental model for sizing a production Bloom filter:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">import</span><span class=\"token plain\"> math</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">bloom_filter_size</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">n_elements</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> fp_rate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token triple-quoted-string string\" style=\"color:hsl(95, 38%, 62%)\">\"\"\"Calculate optimal Bloom filter parameters.\"\"\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">n_elements </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\"> math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">log</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">fp_rate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">log</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">**</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    k </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> n_elements</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\"> math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">log</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'bits'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\" style=\"color:hsl(95, 38%, 62%)\">int</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">ceil</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">m</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'bytes'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\" style=\"color:hsl(95, 38%, 62%)\">int</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">ceil</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">8</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'megabytes'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">8</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1024</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1024</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'hash_functions'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> </span><span class=\"token builtin\" style=\"color:hsl(95, 38%, 62%)\">int</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">ceil</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">k</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'bits_per_element'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"> m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> n_elements</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># Example: 100 million URLs, 0.1% false positive rate</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">params </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> bloom_filter_size</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">100_000_000</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0.001</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># → ~172 MB, 10 hash functions, 14.4 bits/element</span><br></div></code></pre></div></div>\n<p><strong>Rule of thumb:</strong> 10 bits per element gives you 1% FP. Each additional 5 bits per element gives you ~10x better FP rate.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"monitoring-false-positive-rate-in-production\">Monitoring false positive rate in production<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#monitoring-false-positive-rate-in-production\" class=\"hash-link\" aria-label=\"Direct link to Monitoring false positive rate in production\" title=\"Direct link to Monitoring false positive rate in production\" translate=\"no\">​</a></h3>\n<p>Your Bloom filter's actual FP rate drifts as you insert more elements than planned. Monitor it:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># Approximate current FP rate based on fill ratio</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">def</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">estimated_fp_rate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">m_bits</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> k_hashes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> n_inserted</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> math</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">exp</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">k_hashes </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">*</span><span class=\"token plain\"> n_inserted </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> m_bits</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">**</span><span class=\"token plain\"> k_hashes</span><br></div></code></pre></div></div>\n<p>Set an alert when the estimated FP rate exceeds your threshold. When it fires, you need to resize; which for a standard Bloom filter means building a new, larger filter and reinserting everything. Plan for this.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"serialization-and-network-transfer\">Serialization and network transfer<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#serialization-and-network-transfer\" class=\"hash-link\" aria-label=\"Direct link to Serialization and network transfer\" title=\"Direct link to Serialization and network transfer\" translate=\"no\">​</a></h3>\n<p>Bloom filters are just byte arrays. They serialize trivially:</p>\n<ul>\n<li class=\"\">Write the header (m, k, n, hash seed)</li>\n<li class=\"\">Write the raw bytes</li>\n</ul>\n<p>But transferring a 100 MB filter over the network on every update is wasteful. Two tricks:</p>\n<ol>\n<li class=\"\">\n<p><strong>Delta compression:</strong> if you're syncing filters between nodes, XOR the old and new filter. The delta is sparse (mostly zeros) and compresses beautifully with LZ4 or zstd.</p>\n</li>\n<li class=\"\">\n<p><strong>Partitioned filters:</strong> split the filter into segments. Only transfer segments that changed since the last sync. This is how distributed systems like Cassandra share filter updates during anti-entropy repair.</p>\n</li>\n</ol>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"thread-safety\">Thread safety<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#thread-safety\" class=\"hash-link\" aria-label=\"Direct link to Thread safety\" title=\"Direct link to Thread safety\" translate=\"no\">​</a></h3>\n<p>Bloom filters are naturally <strong>read-safe</strong> without locks; reading bits is idempotent. For concurrent writes, you have options:</p>\n<ul>\n<li class=\"\"><strong>Atomic bit-set operations:</strong> <code>__sync_fetch_and_or(&amp;filter[byte_pos], bit_mask)</code>; lock-free, correct, minimal overhead</li>\n<li class=\"\"><strong>Partitioned writes:</strong> each writer owns a segment, readers check all segments</li>\n<li class=\"\"><strong>Copy-on-write:</strong> build a new filter in the background, atomically swap the pointer</li>\n</ul>\n<p>In my experience, atomic bit-set is the sweet spot for most workloads. The false positive rate increases <em>very slightly</em> due to non-atomic multi-bit operations (a query might see a partially-inserted element), but in practice this is within noise.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"a-war-story-the-bloom-filter-that-saved-us-2myear\">A war story: the Bloom filter that saved us $2M/year<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#a-war-story-the-bloom-filter-that-saved-us-2myear\" class=\"hash-link\" aria-label=\"Direct link to A war story: the Bloom filter that saved us $2M/year\" title=\"Direct link to A war story: the Bloom filter that saved us $2M/year\" translate=\"no\">​</a></h2>\n<p>A few years back, I was working on a system that processed event deduplication at ~400K events/second. Each event had a UUID, and we needed to detect duplicates within a 24-hour window.</p>\n<p>The naive approach: a Redis SET with 24-hour TTL. At 400K/sec × 86400 seconds × ~40 bytes per UUID = <strong>~1.4 TB of Redis</strong>. At AWS ElastiCache pricing, that's... not cheap.</p>\n<p>The Bloom filter approach:</p>\n<ul>\n<li class=\"\">24 rotating hourly filters (each covering ~1.44 billion events)</li>\n<li class=\"\">0.01% FP rate per filter (19.2 bits/element)</li>\n<li class=\"\">Total memory: 24 × ~3.5 GB = <strong>~84 GB</strong></li>\n</ul>\n<p>On the rare false positive (0.01% × 24 filters ≈ 0.24% worst case), we'd do a more expensive exact check against a backing store. In practice, the composite FP rate was much lower because events rarely hash identically across multiple hourly filters.</p>\n<p>Result: 17x less memory, easily fit on a few commodity machines, and the latency per dedup check went from ~1 ms (Redis network round trip) to ~200 ns (in-process Bloom filter). The infra cost savings alone justified the engineering effort in the first sprint.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"common-mistakes-ive-seen-in-production\">Common mistakes I've seen in production<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#common-mistakes-ive-seen-in-production\" class=\"hash-link\" aria-label=\"Direct link to Common mistakes I've seen in production\" title=\"Direct link to Common mistakes I've seen in production\" translate=\"no\">​</a></h2>\n<p><strong>1. Not accounting for growth</strong></p>\n<p>\"We have 10 million users, so we'll size for 10 million.\"</p>\n<p>Six months later, you have 25 million users. Your 1% FP rate is now 15%, and your database is getting hammered with false-positive-triggered lookups. <strong>Always size for 2-3x your expected growth</strong>, or use scalable Bloom filters.</p>\n<p><strong>2. Choosing k based on vibes</strong></p>\n<p>I've seen codebases that hardcode <code>k=3</code> or <code>k=7</code> without any justification. Use the formula: <code>k = (m/n) × ln(2)</code>. If your bits-per-element ratio is 10, optimal k is 7. If it's 20, optimal k is 14. Getting k wrong by even 2-3 costs you 2-5x in FP rate for free.</p>\n<p><strong>3. Using a bad hash function</strong></p>\n<p><code>hashCode()</code> in Java is a 32-bit hash with terrible distribution for Bloom filter use. I once saw a production Bloom filter using <code>String.hashCode()</code> with k=7; but since the hash is only 32 bits, the entropy was exhausted after ~4 hash functions. The last 3 were essentially correlated noise. FP rate was 10x worse than predicted.</p>\n<p><strong>Use a 128-bit hash</strong> (MurmurHash3-128 or xxHash-128) and split it into two 64-bit values for the Kirsch-Mitzenmacker trick. This gives you effectively unlimited k without entropy exhaustion.</p>\n<p><strong>4. Ignoring the \"definitely not\" guarantee in application logic</strong></p>\n<p>The whole point of a Bloom filter is the asymmetry: \"no\" means NO. \"Yes\" means MAYBE. I've seen code that treats both answers as probabilistic:</p>\n<div class=\"language-python codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-python codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># WRONG: treating \"not found\" as probabilistic</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">not</span><span class=\"token plain\"> bloom</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token plain\">might_contain</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">key</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">:</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    result </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"probably not in set\"</span><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\"># NO! It's DEFINITELY not in set!</span><br></div></code></pre></div></div>\n<p>Build your system logic around the certainty of negatives. That's where the value is.</p>\n<p><strong>5. Not versioning your hash function</strong></p>\n<p>If you change the hash function (or its seed), every existing filter becomes invalid. All queries will return nonsense. Version your filters with a header that includes the hash algorithm and seed. This sounds obvious until you're doing a zero-downtime migration and half your nodes are running the old hash and half the new one.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-deeper-insight\">The deeper insight<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#the-deeper-insight\" class=\"hash-link\" aria-label=\"Direct link to The deeper insight\" title=\"Direct link to The deeper insight\" translate=\"no\">​</a></h2>\n<p>Here's what I want you to walk away with: Bloom filters aren't just a clever trick. They represent a fundamental insight about information theory.</p>\n<p>Shannon taught us that information has an irreducible cost. If you need to distinguish N items with error rate ε, you need at minimum <code>log₂(1/ε)</code> bits per item. A Bloom filter uses <code>1.44 × log₂(1/ε)</code> bits per item; only 44% above the information-theoretic minimum. That's astounding for a structure this simple.</p>\n<p>The reason they're everywhere in systems engineering isn't because engineers love clever algorithms. It's because the tradeoff they offer; certainty of absence in exchange for ambiguity of presence; maps perfectly onto how distributed systems actually work:</p>\n<ul>\n<li class=\"\">A database doesn't need to <em>know</em> a key is present to open the file; it needs to know a key is <em>absent</em> to skip the file.</li>\n<li class=\"\">A CDN doesn't need to <em>know</em> content is cached; it needs to know content is <em>not cached</em> to go to origin.</li>\n<li class=\"\">A firewall doesn't need to <em>prove</em> a URL is safe; it needs to <em>catch</em> URLs that are definitely malicious.</li>\n</ul>\n<p>In all these cases, the certain negative is more valuable than the uncertain positive. Bloom filters are the mathematical embodiment of this asymmetry.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tldr\">TL;DR<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#tldr\" class=\"hash-link\" aria-label=\"Direct link to TL;DR\" title=\"Direct link to TL;DR\" translate=\"no\">​</a></h2>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Bloom</span><span class=\"token plain\"> filter </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> bit array </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> k hashes</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Insert</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">set</span><span class=\"token plain\"> bits at </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">h₁</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">h₂</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token spread operator\" style=\"color:hsl(207, 82%, 66%)\">...</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">hₖ</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Query</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">   </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ALL</span><span class=\"token plain\"> bits at </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">h₁</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token spread operator\" style=\"color:hsl(207, 82%, 66%)\">...</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">hₖ</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> are </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> → </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"maybe\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">            </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ANY</span><span class=\"token plain\"> bit is </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token plain\"> → </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"definitely not\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Size</span><span class=\"token plain\"> it</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">    m </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">n·ln</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">p</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">ln2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">²</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Tune</span><span class=\"token plain\"> it</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">    k </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">m</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">n</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">·ln</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Hack</span><span class=\"token plain\"> it</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">    </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">gᵢ</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">h₁</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">i·h₂</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> mod </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">m</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">only need </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token plain\"> hashes</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Use</span><span class=\"token plain\"> it when</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"definitely not\"</span><span class=\"token plain\"> is more valuable than </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"definitely yes\"</span><br></div></code></pre></div></div>\n<p>The next time someone proposes a <code>HashMap</code> for a membership check on a billion items, you'll know there's a better way. And now you know exactly how to size it, tune it, and keep it healthy in production.</p>\n<hr>\n<p><em>Bloom, Burton H. \"Space/time trade-offs in hash coding with allowable errors.\" Communications of the ACM 13.7 (1970): 422-426. — Still worth reading. The paper is 4 pages long and changed systems engineering forever.</em></p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"further-reading\">Further reading<a href=\"https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters#further-reading\" class=\"hash-link\" aria-label=\"Direct link to Further reading\" title=\"Direct link to Further reading\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a href=\"https://dl.acm.org/doi/10.1145/362686.362692\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Space/Time Trade-offs in Hash Coding with Allowable Errors</a> — Bloom's original 1970 paper. 4 pages. Start here.</li>\n<li class=\"\"><a href=\"https://www.eecs.harvard.edu/~michaelm/postscripts/rsa2008.pdf\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Less Hashing, Same Performance: Building a Better Bloom Filter</a> — Kirsch &amp; Mitzenmacker (2006). The double-hashing trick everyone actually uses in production.</li>\n<li class=\"\"><a href=\"https://www.cs.cmu.edu/~dga/papers/cuckoo-conext2014.pdf\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Cuckoo Filter: Practically Better Than Bloom</a> — Fan et al. (2014). Read this when you outgrow vanilla Bloom filters.</li>\n<li class=\"\"><a href=\"https://blog.cloudflare.com/when-bloom-filters-dont-bloom/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">When Bloom Filters Don't Bloom</a> — Cloudflare on why cache-unfriendly filters can be slower than expected. Essential before deploying large filters.</li>\n<li class=\"\"><a href=\"https://github.com/facebook/rocksdb/wiki/RocksDB-Bloom-Filter\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">RocksDB Wiki: Bloom Filter</a> — How Meta actually deploys them at scale. The best \"theory meets practice\" resource.</li>\n</ul>",
            "url": "https://blogs.pranjalkumar.in/blog/probabilistic-data-structures-bloom-filters",
            "title": "Probabilistic data structures: Why Bloom filters are one of the most elegant hack",
            "summary": "A deep dive into probabilistic data structures; focusing on Bloom filters from first principles through production deployment. Covers the math, the bit manipulation, optimal hash functions, false positive tuning, counting variants, cuckoo filters, and real-world war stories from systems operating at billions of queries per second.",
            "date_modified": "2026-03-15T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "data-structures",
                "bloom-filters",
                "distributed-systems",
                "algorithms",
                "system-design",
                "databases"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" alt=\"Diagram showing the full network request lifecycle from keystroke to rendered pixels, covering DNS resolution, TCP handshake, TLS encryption, HTTP response, and browser rendering pipeline | Pranjal Kumar\" src=\"https://blogs.pranjalkumar.in/assets/images/how-internet-works-explained%20by%20Pranjal%20Kumar%20-%20software%20engineer-3a40dbfe9cdd13f7e81698a1ecc5d34e.png\" width=\"1738\" height=\"1303\" class=\"img_ev3q\"></p>\n<blockquote>\n<p>Every time I read a \"how the internet works\" article, I cringe - they all stop at DNS → TCP → HTTP → HTML. That's like explaining a car engine by saying \"fuel goes in, wheels spin.\" Super helpful when the engine is on fire.</p>\n<p>This post is what I wish someone had handed me when I was staring at a waterfall chart at 3 AM, wondering why a page took 4 seconds to load on a 1 Gbps connection. We're going to trace every system boundary crossing - from the electrical signal your keyboard fires to the GPU draw call that lights up the final pixel.</p>\n</blockquote>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-keyboard-interrupt-yes-it-starts-here\">The keyboard interrupt (yes, it starts here)<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-keyboard-interrupt-yes-it-starts-here\" class=\"hash-link\" aria-label=\"Direct link to The keyboard interrupt (yes, it starts here)\" title=\"Direct link to The keyboard interrupt (yes, it starts here)\" translate=\"no\">​</a></h2>\n<p>You press <strong>Enter</strong>. That's a physical key-switch completing a circuit on a matrix scan. Your keyboard's microcontroller detects the state change, debounces it (~5 ms), and sends a <strong>USB HID scancode</strong> (0x28 for Enter) over the USB bus.</p>\n<p>The host controller raises a <strong>hardware interrupt</strong> (IRQ). The kernel's USB HID driver picks it up, translates the scancode to a <strong>virtual keycode</strong>, and enqueues a <code>KEY_ENTER</code> event into the input subsystem (<code>/dev/input/eventN</code> on Linux, IOKit HID on macOS, Raw Input on Windows).</p>\n<p>The window manager dispatches this as a <strong>keydown event</strong> to your browser. The browser's UI thread captures it, recognizes you're in the URL bar, and kicks off navigation. Chrome's <code>NavigationController</code> fires and the network stack starts work <em>before</em> the UI thread finishes its current animation frame. They're racing against your perception of speed.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"chromes-multi-process-architecture\">Chrome's multi-process architecture<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#chromes-multi-process-architecture\" class=\"hash-link\" aria-label=\"Direct link to Chrome's multi-process architecture\" title=\"Direct link to Chrome's multi-process architecture\" translate=\"no\">​</a></h3>\n<p>Before we go further, here's Chrome's process model - it shapes everything that follows:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">┌─────────────────────────────────────────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Browser</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Process</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> per </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Chrome</span><span class=\"token plain\"> instance</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">                │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">UI</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">thread</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">address bar</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> tabs</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> bookmarks</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">             │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Network</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Service</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">DNS</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">TCP</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">TLS</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HTTP</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> all </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">of</span><span class=\"token plain\"> it</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">    │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Storage</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Service</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">cookies</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> cache</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">IndexedDB</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">          │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">├─────────────────────────────────────────────────────────┤</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Renderer</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Process</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> per site </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\"> site isolation</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">         │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Main</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">thread</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">DOM</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CSSOM</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">JS</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Layout</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Paint</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">          │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Compositor</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">thread</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">layer tree</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> tile management</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">      │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Raster</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">threads</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">pixel generation via </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Skia</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">           │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">├─────────────────────────────────────────────────────────┤</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">GPU</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Process</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> shared across all renderers</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\">            │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Composites</span><span class=\"token plain\"> layers </span><span class=\"token keyword module\" style=\"color:hsl(286, 60%, 67%)\">from</span><span class=\"token plain\"> all renderer processes        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Issues</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">GL</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Vulkan</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Metal</span><span class=\"token plain\"> draw calls                    │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">└─────────────────────────────────────────────────────────┘</span><br></div></code></pre></div></div>\n<p>When you press Enter, the <strong>Browser Process</strong> owns the entire navigation until the first response bytes arrive. Only then does it spin up (or reuse) a <strong>Renderer Process</strong> and hand off the byte stream. This is a security boundary - the renderer is sandboxed and can't touch the network directly. Every fetch goes through the Browser Process via IPC.</p>\n<p>This also explains <strong>site isolation</strong>: each cross-origin site gets its own renderer process with its own V8 isolate. A malicious script on <code>evil.com</code> literally cannot read memory from <code>bank.com</code>'s renderer because they're separate OS processes.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"url-parsing-and-the-hsts-check\">URL parsing and the HSTS check<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#url-parsing-and-the-hsts-check\" class=\"hash-link\" aria-label=\"Direct link to URL parsing and the HSTS check\" title=\"Direct link to URL parsing and the HSTS check\" translate=\"no\">​</a></h2>\n<p>Now the browser has a string: <code>https://example.com/path?q=1</code>. You'd think parsing a URL is trivial - and you'd be wrong. I've seen production bugs from URL parsing edge cases.</p>\n<p>The browser runs it through <strong>URL parsing</strong> (RFC 3986): normalizes the scheme, Punycode-encodes IDN labels (<code>münchen.de</code> → <code>xn--mnchen-3ya.de</code>), percent-encodes illegal characters, and resolves the default port (443 for HTTPS).</p>\n<p>Then, before <em>any</em> network I/O:</p>\n<p><strong>HSTS Preload check.</strong> Chrome ships a <strong>static preload list</strong> baked into the binary - domains that must <em>always</em> use HTTPS. If the domain is on this list and you typed <code>http://</code>, the browser internally redirects to <code>https://</code> without sending a single plaintext byte to the network.</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Status</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">307</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Internal</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Redirect</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Non</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Authoritative</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Reason</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HSTS</span><br></div></code></pre></div></div>\n<p>There's also the <strong>dynamic HSTS store</strong>: if the server previously sent a <code>Strict-Transport-Security</code> header, Chrome stored that policy. It's persisted at <code>~/.config/google-chrome/Default/TransportSecurity</code> - just a JSON file. I once debugged a redirect loop that turned out to be a stale HSTS entry from a dev environment. Knowing this file exists saves you hours.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"dns-resolution---the-part-nobody-explains-well\">DNS resolution - the part nobody explains well<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#dns-resolution---the-part-nobody-explains-well\" class=\"hash-link\" aria-label=\"Direct link to DNS resolution - the part nobody explains well\" title=\"Direct link to DNS resolution - the part nobody explains well\" translate=\"no\">​</a></h2>\n<p>DNS is one of those things everyone <em>thinks</em> they understand. \"It's like a phone book for the internet!\" Sure. And a CPU is like a calculator. Technically correct, practically useless for debugging.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-local-resolver-chain\">The local resolver chain<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-local-resolver-chain\" class=\"hash-link\" aria-label=\"Direct link to The local resolver chain\" title=\"Direct link to The local resolver chain\" translate=\"no\">​</a></h3>\n<p>Before anything hits the network, the browser goes through a caching chain:</p>\n<ol>\n<li class=\"\"><strong>Browser DNS cache</strong> - Chrome has its own (<code>chrome://net-internals/#dns</code>) with per-record TTL. Negative caches (NXDOMAIN) are stored too. Chrome will happily cache a failure for minutes while <code>dig</code> shows the record is fine.</li>\n<li class=\"\"><strong>OS stub resolver cache</strong> - <code>systemd-resolved</code> on Linux, <code>mDNSResponder</code> on macOS.</li>\n<li class=\"\"><strong><code>/etc/hosts</code></strong> - still checked. I've seen senior engineers spend hours debugging DNS issues that turned out to be a forgotten entry from a hackathon two years ago.</li>\n<li class=\"\"><strong>Router/gateway cache</strong> - your home router usually runs <code>dnsmasq</code> or equivalent.</li>\n</ol>\n<p>If all miss, we go to the <strong>recursive resolver</strong> (let's say <code>8.8.8.8</code>).</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"recursive-resolution\">Recursive resolution<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#recursive-resolution\" class=\"hash-link\" aria-label=\"Direct link to Recursive resolution\" title=\"Direct link to Recursive resolution\" translate=\"no\">​</a></h3>\n<p>The stub resolver sends a UDP datagram (port 53). The recursive resolver performs the actual recursion:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Stub</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Recursive</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Resolver</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">8.8</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">.8</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">.8</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  └─→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Root</span><span class=\"token plain\"> server → </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"Try .com TLD at 192.5.6.30\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      └─→ </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">com</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">TLD</span><span class=\"token plain\"> server → </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"Try example.com NS at 93.184.216.34\"</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">          └─→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Authoritative</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">NS</span><span class=\"token plain\"> → </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"A record: 93.184.215.14, TTL: 86400\"</span><br></div></code></pre></div></div>\n<p>In theory, that's 3 round trips. In practice, the recursive resolver has cached the root and TLD responses (hit billions of times daily), so you usually pay for only the final authoritative query. But on a cold resolver, you'll feel all three hops - that's why the first page load after changing DNS settings feels sluggish.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-modern-dns-landscape\">The modern DNS landscape<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-modern-dns-landscape\" class=\"hash-link\" aria-label=\"Direct link to The modern DNS landscape\" title=\"Direct link to The modern DNS landscape\" translate=\"no\">​</a></h3>\n<p>A few things worth knowing about DNS as it exists today:</p>\n<p><strong>DNSSEC</strong> validates the chain of trust from root → TLD → domain using signed records. A failed validation returns <code>SERVFAIL</code> - hard error, not a redirect.</p>\n<p><strong>DNS-over-HTTPS (DoH)</strong> encrypts queries as HTTP/2 POSTs to providers like <code>https://dns.google/dns-query</code>. Your ISP can't see what you're resolving anymore, but it requires an existing TLS connection to the DoH provider (bootstrapped via hardcoded IPs).</p>\n<p><strong>Happy Eyeballs (RFC 8305)</strong> - my favorite name in networking. If both IPv4 and IPv6 records come back, the browser starts IPv6 first, gives it a 250ms head start, then races it against IPv4. Whichever SYN-ACK arrives first wins. Users shouldn't suffer because their ISP's IPv6 is half-broken.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tcp---the-handshake-tax\">TCP - the handshake tax<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#tcp---the-handshake-tax\" class=\"hash-link\" aria-label=\"Direct link to TCP - the handshake tax\" title=\"Direct link to TCP - the handshake tax\" translate=\"no\">​</a></h2>\n<p>TCP was designed in the 1970s and still causes performance headaches its creators never imagined.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-three-way-handshake\">The three-way handshake<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-three-way-handshake\" class=\"hash-link\" aria-label=\"Direct link to The three-way handshake\" title=\"Direct link to The three-way handshake\" translate=\"no\">​</a></h3>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SYN</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">seq</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\">x</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Window</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Scale</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">MSS</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SACK</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Permitted</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Timestamps</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SYN</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ACK</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">seq</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\">y</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> ack</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\">x</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Window</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Scale</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">MSS</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SACK</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Permitted</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ACK</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">ack</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\">y</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><br></div></code></pre></div></div>\n<p><strong>Cost: 1 RTT.</strong> For a US West → Europe server, that's ~150 ms before any data flows.</p>\n<p>The options negotiated during SYN matter more than people think:</p>\n<table><thead><tr><th>Option</th><th>What it does</th></tr></thead><tbody><tr><td><strong>Window Scale</strong></td><td>Allows receive windows &gt; 64KB (max 1 GB window)</td></tr><tr><td><strong>MSS</strong></td><td>Maximum Segment Size - typically 1460 bytes for Ethernet</td></tr><tr><td><strong>SACK</strong></td><td>Selective Acknowledgments - smarter retransmission</td></tr><tr><td><strong>ECN</strong></td><td>Explicit Congestion Notification - routers signal congestion without dropping packets</td></tr></tbody></table>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"congestion-control---the-hidden-performance-governor\">Congestion control - the hidden performance governor<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#congestion-control---the-hidden-performance-governor\" class=\"hash-link\" aria-label=\"Direct link to Congestion control - the hidden performance governor\" title=\"Direct link to Congestion control - the hidden performance governor\" translate=\"no\">​</a></h3>\n<p>After the handshake, the kernel's congestion control algorithm dictates how fast data flows. This will fundamentally change how you think about web performance.</p>\n<ul>\n<li class=\"\"><strong>Initial congestion window (IW):</strong> Typically 10 segments (<strong>14.6 KB</strong>). This means the <em>first flight of data</em> after the handshake carries at most ~14.6 KB. Your entire first impression of a website must fit in that or you're paying another round trip.</li>\n<li class=\"\"><strong>Slow start:</strong> cwnd doubles every RTT until packet loss or threshold.</li>\n<li class=\"\"><strong>BBR</strong> models bandwidth and RTT explicitly instead of reacting to loss - significantly better on mobile/lossy links.</li>\n</ul>\n<p>If your critical CSS is 30 KB, you're paying an extra RTT - maybe 100+ ms on a cross-continent connection - just because you shipped 15 KB too much CSS. This is why the \"14 KB rule\" exists, and why every byte in your critical path matters far more than raw bandwidth suggests.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"connection-pooling\">Connection pooling<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#connection-pooling\" class=\"hash-link\" aria-label=\"Direct link to Connection pooling\" title=\"Direct link to Connection pooling\" translate=\"no\">​</a></h3>\n<p>Browsers maintain <strong>up to 6 TCP connections per origin</strong> (HTTP/1.1). With HTTP/2, everything multiplexes over a <strong>single connection</strong>, amortizing the handshake cost across all requests.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tls-13---the-crypto-handshake\">TLS 1.3 - the crypto handshake<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#tls-13---the-crypto-handshake\" class=\"hash-link\" aria-label=\"Direct link to TLS 1.3 - the crypto handshake\" title=\"Direct link to TLS 1.3 - the crypto handshake\" translate=\"no\">​</a></h2>\n<p>I've spent more hours staring at TLS handshake failures than I'd like to admit. TLS 1.3 collapsed the handshake from 2 RTTs (TLS 1.2) to 1 RTT by doing key exchange and authentication in the same flight:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">ClientHello</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">key_share</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">X25519</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ECDH</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">public</span><span class=\"token plain\"> key</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">server_name</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SNI</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"example.com\"</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ALPN</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">h2</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> http</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1.1</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">ServerHello</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> key_share</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">EncryptedExtensions</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Certificate</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">CertificateVerify</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Finished</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Client</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Server</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Finished</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Application</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Data</span><span class=\"token plain\"> starts </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HERE</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><br></div></code></pre></div></div>\n<p>Both sides derive traffic keys from the shared ECDH secret via HKDF. All data is now encrypted with AES-256-GCM or ChaCha20-Poly1305.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-sni-privacy-problem\">The SNI privacy problem<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-sni-privacy-problem\" class=\"hash-link\" aria-label=\"Direct link to The SNI privacy problem\" title=\"Direct link to The SNI privacy problem\" translate=\"no\">​</a></h3>\n<p>Here's a dirty secret: the <code>server_name</code> extension (SNI) is sent in <strong>plaintext</strong> in the ClientHello. Any network observer - your ISP, a corporate proxy, a nation-state firewall - can see <em>which domain</em> you're connecting to, even though the content is encrypted. <strong>Encrypted Client Hello (ECH)</strong> fixes this by encrypting the ClientHello under a public key from the domain's DNS HTTPS record.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"0-rtt-resumption\">0-RTT resumption<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#0-rtt-resumption\" class=\"hash-link\" aria-label=\"Direct link to 0-RTT resumption\" title=\"Direct link to 0-RTT resumption\" translate=\"no\">​</a></h3>\n<p>If the client previously connected to this server, it may have cached a <strong>PSK</strong> from the server's <code>NewSessionTicket</code>. On reconnection, it sends application data <em>with</em> the ClientHello - zero round trips for TLS.</p>\n<p>The catch: 0-RTT data is <strong>replayable</strong>. An attacker who captures the ClientHello can replay it. This is why only idempotent requests (GET) go in 0-RTT, and servers need anti-replay mechanisms.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"certificate-validation\">Certificate validation<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#certificate-validation\" class=\"hash-link\" aria-label=\"Direct link to Certificate validation\" title=\"Direct link to Certificate validation\" translate=\"no\">​</a></h3>\n<p>The chain is validated: leaf cert → intermediate(s) → root CA in the OS trust store. Chrome uses <strong>CRLSets</strong> (a compressed revocation list pushed via component updates) instead of slow online OCSP checks, and requires <strong>Certificate Transparency SCTs</strong> to prevent rogue CA issuance.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"http2-http3-and-quic\">HTTP/2, HTTP/3, and QUIC<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#http2-http3-and-quic\" class=\"hash-link\" aria-label=\"Direct link to HTTP/2, HTTP/3, and QUIC\" title=\"Direct link to HTTP/2, HTTP/3, and QUIC\" translate=\"no\">​</a></h2>\n<p>We finally have an encrypted pipe. Now let's shove data through it.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"http2-multiplexing\">HTTP/2 multiplexing<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#http2-multiplexing\" class=\"hash-link\" aria-label=\"Direct link to HTTP/2 multiplexing\" title=\"Direct link to HTTP/2 multiplexing\" translate=\"no\">​</a></h3>\n<p>HTTP/2's killer feature: multiple request/response pairs share a single TCP connection as independent <strong>streams</strong>. No more 6-connection limit.</p>\n<p>But here's the cruel irony - TCP delivers bytes in order. If one segment is lost, <em>all</em> streams stall waiting for retransmission. Your CSS stream is held hostage by a lost packet from the JavaScript stream. This <strong>head-of-line blocking</strong> drove the creation of QUIC.</p>\n<p><strong>HPACK</strong> compresses headers using a static table of common values plus a per-connection dynamic table. The second request to the same origin typically sends ~20 bytes of headers instead of ~800 bytes.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"http3-and-quic\">HTTP/3 and QUIC<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#http3-and-quic\" class=\"hash-link\" aria-label=\"Direct link to HTTP/3 and QUIC\" title=\"Direct link to HTTP/3 and QUIC\" translate=\"no\">​</a></h3>\n<p>HTTP/3 runs over <strong>QUIC</strong> (RFC 9000) - reliable delivery rebuilt on top of UDP. When I first heard this, I thought it was insane. Then I read the design and realized it was brilliant:</p>\n<ul>\n<li class=\"\"><strong>Per-stream ordering</strong> (not per-connection - no head-of-line blocking)</li>\n<li class=\"\"><strong>Built-in TLS 1.3</strong> (crypto handshake is part of the QUIC handshake)</li>\n<li class=\"\"><strong>Connection migration</strong> - connections are identified by a Connection ID, not the IP/port 4-tuple. Switch from Wi-Fi to cellular? Connection survives.</li>\n</ul>\n<table><thead><tr><th>Protocol</th><th>RTTs to first byte</th></tr></thead><tbody><tr><td>HTTP/1.1 + TLS 1.2</td><td>3</td></tr><tr><td>HTTP/2 + TLS 1.3</td><td>2</td></tr><tr><td>HTTP/3 (QUIC)</td><td>1</td></tr><tr><td>HTTP/3 0-RTT</td><td>0</td></tr></tbody></table>\n<p>Browsers discover HTTP/3 via the <code>Alt-Svc</code> header. The first request always goes over TCP; subsequent requests migrate to QUIC if it works.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-http-request-and-response\">The HTTP request and response<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-http-request-and-response\" class=\"hash-link\" aria-label=\"Direct link to The HTTP request and response\" title=\"Direct link to The HTTP request and response\" translate=\"no\">​</a></h2>\n<p>What actually goes over the wire - not the textbook version:</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">GET /path?q=1 HTTP/2</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">:authority: example.com</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">:scheme: https</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">accept-encoding: gzip, br, zstd</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">sec-ch-ua: \"Chromium\";v=\"128\"</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">sec-fetch-dest: document</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">sec-fetch-mode: navigate</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">sec-fetch-site: none</span><br></div></code></pre></div></div>\n<p>The <strong>Sec-Fetch-</strong>* headers are criminally underused. They tell the server the <em>context</em> of the request - and they're unforgeable (the browser sets them, not JavaScript). If you're building an API and not checking these, you're missing a free layer of CSRF defense.</p>\n<p>The request hits a load balancer (Envoy, nginx), gets routed to an app server, which generates the response:</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">HTTP/2 200</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">content-type: text/html; charset=utf-8</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">content-encoding: br</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">cache-control: public, max-age=3600, stale-while-revalidate=86400</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">strict-transport-security: max-age=63072000; includeSubDomains; preload</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">content-security-policy: default-src 'self'; script-src 'self' 'nonce-r4nd0m';</span><br></div></code></pre></div></div>\n<p>The body is <strong>Brotli-compressed</strong>. The browser starts decompressing as chunks arrive - it doesn't wait for the full response. The HTML parser starts building the DOM while the last bytes are still in flight.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"from-bytes-to-dom---the-rendering-pipeline\">From bytes to DOM - the rendering pipeline<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#from-bytes-to-dom---the-rendering-pipeline\" class=\"hash-link\" aria-label=\"Direct link to From bytes to DOM - the rendering pipeline\" title=\"Direct link to From bytes to DOM - the rendering pipeline\" translate=\"no\">​</a></h2>\n<p>This is where most articles wave their hands and say \"the browser renders the page.\" It's not one step. It's an absurdly complex pipeline.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"preload-scanning\">Preload scanning<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#preload-scanning\" class=\"hash-link\" aria-label=\"Direct link to Preload scanning\" title=\"Direct link to Preload scanning\" translate=\"no\">​</a></h3>\n<p>While the main HTML parser runs on the main thread, Chrome fires up a <strong>preload scanner</strong> on a <em>separate thread</em>. It scans ahead looking for resource URLs (<code>&lt;link&gt;</code>, <code>&lt;script src&gt;</code>, <code>&lt;img&gt;</code>) and kicks off network requests <em>before</em> the main parser reaches those nodes. If you bury a critical CSS <code>&lt;link&gt;</code> below a huge inline script, you've negated this optimization. I've seen this cost 500+ ms.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"html-parsing-and-dom-construction\">HTML parsing and DOM construction<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#html-parsing-and-dom-construction\" class=\"hash-link\" aria-label=\"Direct link to HTML parsing and DOM construction\" title=\"Direct link to HTML parsing and DOM construction\" translate=\"no\">​</a></h3>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Network</span><span class=\"token plain\"> bytes → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Content</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">decoding</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">streaming</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Character</span><span class=\"token plain\"> encoding detection</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Tokenizer</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">state machine per </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HTML5</span><span class=\"token plain\"> spec</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Tree</span><span class=\"token plain\"> builder</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">DOM</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Tree</span><br></div></code></pre></div></div>\n<p>The parser <strong>blocks</strong> on <code>&lt;script&gt;</code> tags without <code>async</code> or <code>defer</code> - pauses DOM construction entirely until the script is fetched, compiled, and executed. Every synchronous script in your <code>&lt;head&gt;</code> is a toll booth on the highway to first paint.</p>\n<p>A <code>&lt;link rel=\"stylesheet\"&gt;</code> <strong>blocks rendering</strong> (not parsing) - the browser won't paint until CSSOM is ready, because painting without styles causes a flash of unstyled content.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cssom-and-the-layout-tree\">CSSOM and the layout tree<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#cssom-and-the-layout-tree\" class=\"hash-link\" aria-label=\"Direct link to CSSOM and the layout tree\" title=\"Direct link to CSSOM and the layout tree\" translate=\"no\">​</a></h3>\n<p>All stylesheets merge into a <strong>CSSOM</strong>. The DOM and CSSOM combine into a <strong>layout tree</strong> - elements with <code>display: none</code> excluded, pseudo-elements added, computed styles resolved.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"layout\">Layout<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#layout\" class=\"hash-link\" aria-label=\"Direct link to Layout\" title=\"Direct link to Layout\" translate=\"no\">​</a></h3>\n<p>The engine walks the tree and computes geometry. Block layout, inline layout, flex/grid constraint solving. This is where <strong>layout thrashing</strong> kills you - reading a layout property after modifying the DOM forces a synchronous reflow:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// BAD: forces layout on every iteration</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">for</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">let</span><span class=\"token plain\"> i </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">0</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"> i </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1000</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"> i</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">++</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  el</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">style</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">width</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> el</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">offsetWidth</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'px'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"paint-composite-draw\">Paint, composite, draw<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#paint-composite-draw\" class=\"hash-link\" aria-label=\"Direct link to Paint, composite, draw\" title=\"Direct link to Paint, composite, draw\" translate=\"no\">​</a></h3>\n<p>After layout, Chrome <strong>records</strong> display items (draw commands). Then the page is split into <strong>layers</strong> (elements with <code>will-change: transform</code>, 3D transforms, <code>&lt;video&gt;</code>, <code>&lt;canvas&gt;</code>). Each layer is divided into tiles and <strong>rasterized</strong> by GPU threads into textures. Finally, the GPU process composites all layers together and submits the framebuffer.</p>\n<p>On a 60 Hz display, this entire pipeline must complete in <strong>16.67 ms</strong>. On 120 Hz, <strong>8.33 ms</strong>. You have 8 milliseconds from a DOM change to photons. That's why UI frameworks obsess over minimizing re-renders.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"javascript-execution---v8s-pipeline\">JavaScript execution - V8's pipeline<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#javascript-execution---v8s-pipeline\" class=\"hash-link\" aria-label=\"Direct link to JavaScript execution - V8's pipeline\" title=\"Direct link to JavaScript execution - V8's pipeline\" translate=\"no\">​</a></h2>\n<p>When the parser hits a <code>&lt;script&gt;</code>, V8 takes over:</p>\n<p><strong>Lazy parsing:</strong> V8 only fully parses functions when they're <em>called</em>, not declared. If you ship a 2 MB bundle but only execute 200 KB on first load, V8 won't waste time parsing the rest upfront. This is why code splitting works.</p>\n<p><strong>Tiered compilation:</strong></p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Cold</span><span class=\"token plain\"> code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">    </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Ignition</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">interpreter</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Warm</span><span class=\"token plain\"> code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">    </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Maglev</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">mid</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">tier compiler</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">~</span><span class=\"token plain\">10x faster</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Hot</span><span class=\"token plain\"> code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">     </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Turbofan</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">full optimizing compiler</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">~</span><span class=\"token plain\">100x faster</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><br></div></code></pre></div></div>\n<p>Turbofan does type specialization, inlining, escape analysis, and dead code elimination based on runtime feedback from Inline Caches.</p>\n<p><strong>Deoptimization</strong> is the trap: if Turbofan's type assumptions are violated, it bails out back to Ignition. I've seen this cause performance cliffs in production - code runs fast for an hour, then one edge-case input triggers a deopt and that function is 100x slower until re-optimized. This is why polymorphic call sites kill performance, and why TypeScript helps the JIT too.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-physical-layer---arp-ip-and-photons\">The physical layer - ARP, IP, and photons<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#the-physical-layer---arp-ip-and-photons\" class=\"hash-link\" aria-label=\"Direct link to The physical layer - ARP, IP, and photons\" title=\"Direct link to The physical layer - ARP, IP, and photons\" translate=\"no\">​</a></h2>\n<p>Your data needs to physically get from here to there.</p>\n<p><strong>ARP resolution:</strong> Before the first SYN leaves your machine, the kernel needs the MAC address of your router. It checks the ARP cache; if missing, broadcasts \"who has 192.168.1.1?\" and caches the reply.</p>\n<p><strong>IP routing:</strong> The kernel's routing table determines the next hop. The packet gets encapsulated: <code>[Ethernet frame [IP packet [TCP segment [TLS record [HTTP/2 frame [payload]]]]]]</code></p>\n<p><strong>The physical journey:</strong> NIC → Ethernet/Wi-Fi → router → ISP backbone (fiber, DWDM links) → Internet Exchange Point → destination CDN/ISP → server NIC.</p>\n<p>Light in fiber travels at ~200,000 km/s. NY→London (5,500 km) is 27.5 ms one-way <em>at the speed of light</em> - real-world is ~35-40 ms due to routing and signal regeneration. No amount of engineering can beat this. Physics doesn't care about your SLA. This is why CDNs exist.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cdn-edge---cheating-physics\">CDN edge - cheating physics<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#cdn-edge---cheating-physics\" class=\"hash-link\" aria-label=\"Direct link to CDN edge - cheating physics\" title=\"Direct link to CDN edge - cheating physics\" translate=\"no\">​</a></h2>\n<p>For major sites, you don't hit the origin server. A CDN (Cloudflare, Fastly, Akamai) <strong>terminates your TLS connection at an edge PoP</strong> within ~10 ms of your location. The server you're talking to might be in a rack in your city.</p>\n<p>The edge checks its cache, serves on hit (TTFB ≈ 10-30 ms), or fetches from origin on miss. CDNs use <strong>tiered caching</strong> - edge PoP → regional shield → origin - so most misses never reach your actual servers.</p>\n<p><strong>Edge compute</strong> is changing the game: Cloudflare Workers, Fastly Compute, and Lambda@Edge let you run code at the edge. Authentication, A/B testing, SSR - no round trip to origin.</p>\n<p><strong>103 Early Hints</strong> is underused magic: the CDN sends preload hints <em>while</em> waiting for the origin response, so the browser starts fetching CSS/JS before the HTML even arrives.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"service-workers---the-invisible-middleware\">Service workers - the invisible middleware<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#service-workers---the-invisible-middleware\" class=\"hash-link\" aria-label=\"Direct link to Service workers - the invisible middleware\" title=\"Direct link to Service workers - the invisible middleware\" translate=\"no\">​</a></h2>\n<p>If the site has a <strong>service worker</strong> registered, the request may never hit the network. Service workers intercept every request and can serve from cache, synthesize responses from IndexedDB, or implement any caching strategy you want:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">self</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">addEventListener</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'fetch'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">event</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:hsl(207, 82%, 66%)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  event</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">respondWith</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    caches</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">match</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">request</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">then</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:hsl(207, 82%, 66%)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">fetch</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">request</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">then</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">response</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:hsl(207, 82%, 66%)\">=&gt;</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">const</span><span class=\"token plain\"> clone </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">clone</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        caches</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">open</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'v1'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">then</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">cache</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token arrow operator\" style=\"color:hsl(207, 82%, 66%)\">=&gt;</span><span class=\"token plain\"> cache</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">put</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">event</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token property-access\">request</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> clone</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> response</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><br></div></code></pre></div></div>\n<p>The cost: if the SW thread is idle (~30s of inactivity), the browser must spin it up (50-100ms on mobile). Chrome's <strong>navigation preload</strong> fires the network request simultaneously while waking the SW, so you don't pay that penalty on the critical path.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"putting-it-all-together---time-budget\">Putting it all together - time budget<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#putting-it-all-together---time-budget\" class=\"hash-link\" aria-label=\"Direct link to Putting it all together - time budget\" title=\"Direct link to Putting it all together - time budget\" translate=\"no\">​</a></h2>\n<p>Here's a real navigation to <code>https://example.com</code> from a cold start:</p>\n<table><thead><tr><th>Phase</th><th>Time (typical)</th><th>Notes</th></tr></thead><tbody><tr><td>Keyboard → browser</td><td>&lt; 1 ms</td><td>Hardware interrupt</td></tr><tr><td>URL parse + HSTS</td><td>&lt; 1 ms</td><td>In-memory</td></tr><tr><td>DNS resolution</td><td>20-150 ms</td><td>Depends on cache state</td></tr><tr><td>TCP handshake</td><td>10-150 ms</td><td>1 RTT</td></tr><tr><td>TLS 1.3 handshake</td><td>10-150 ms</td><td>1 RTT (overlaps with TCP on QUIC)</td></tr><tr><td>Service worker</td><td>0-100 ms</td><td>If registered; may skip network</td></tr><tr><td>HTTP request → first byte</td><td>10-500 ms</td><td>Server processing</td></tr><tr><td>HTML download</td><td>10-200 ms</td><td>Size + bandwidth</td></tr><tr><td>Critical CSS/JS fetch</td><td>0-200 ms</td><td>Parallel, preload scanner</td></tr><tr><td>DOM + CSSOM + Layout + Paint</td><td>15-150 ms</td><td>Complexity dependent</td></tr><tr><td><strong>Total (cold)</strong></td><td><strong>~100-1500 ms</strong></td><td></td></tr><tr><td><strong>Total (warm, 0-RTT)</strong></td><td><strong>~50-200 ms</strong></td><td></td></tr></tbody></table>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-things-go-wrong\">When things go wrong<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#when-things-go-wrong\" class=\"hash-link\" aria-label=\"Direct link to When things go wrong\" title=\"Direct link to When things go wrong\" translate=\"no\">​</a></h2>\n<p>The patterns that cause real outages:</p>\n<p><strong>Slow DNS</strong> - <code>dns_start</code> to <code>dns_end</code> &gt; 100 ms in DevTools Timing. Fix: <code>&lt;link rel=\"dns-prefetch\"&gt;</code>, fast resolver.</p>\n<p><strong>TCP slow start penalty</strong> - first load slow, subsequent fast. Your critical path exceeds the 14.6 KB initial congestion window. Fix: keep HTML + critical CSS under 14 KB compressed.</p>\n<p><strong>TLS chain too long</strong> - extra RTT if the certificate message exceeds initial cwnd. Fix: short chains (leaf + 1 intermediate), ECDSA certs.</p>\n<p><strong>Render-blocking resources</strong> - gap between TTFB and First Paint. Fix: <code>async</code>/<code>defer</code> scripts, inline critical CSS.</p>\n<p><strong>Layout thrashing</strong> - long \"Layout\" blocks in Performance panel. Fix: batch reads/writes, <code>requestAnimationFrame</code>, CSS containment.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-this-is-all-heading\">Where this is all heading<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#where-this-is-all-heading\" class=\"hash-link\" aria-label=\"Direct link to Where this is all heading\" title=\"Direct link to Where this is all heading\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>QUIC everywhere</strong> - HTTP/3 adoption crossing 30%+. The TCP handshake tax is disappearing.</li>\n<li class=\"\"><strong>ECH</strong> - SNI privacy becoming standard. Makes censorship harder.</li>\n<li class=\"\"><strong>Shared dictionaries</strong> - Brotli/Zstandard with shared dictionaries could compress responses to 5-10% of current sizes for repeat visitors.</li>\n<li class=\"\"><strong>Speculation Rules API</strong> - browsers pre-rendering entire pages based on declarative rules. Sub-100ms navigations as the norm.</li>\n<li class=\"\"><strong>WebTransport</strong> - QUIC without HTTP semantics for real-time apps. Could finally kill WebSocket.</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"tldr\">TL;DR<a href=\"https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works#tldr\" class=\"hash-link\" aria-label=\"Direct link to TL;DR\" title=\"Direct link to TL;DR\" translate=\"no\">​</a></h2>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Keyboard</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">IRQ</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">USB</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HID</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">OS</span><span class=\"token plain\"> input → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Browser</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Process</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">URL</span><span class=\"token plain\"> parse → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HSTS</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">DNS</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">cache chain → recursive resolution</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">TCP</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">SYN</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">ACK</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">TLS</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">1.3</span><span class=\"token plain\"> key exchange</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Service</span><span class=\"token plain\"> </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Worker</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">HTTP</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token plain\"> request → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CDN</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">origin → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Response</span><span class=\"token plain\"> stream</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">→ </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Preload</span><span class=\"token plain\"> scan → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">DOM</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CSSOM</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Layout</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Paint</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Composite</span><span class=\"token plain\"> → </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">GPU</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Pixels</span><br></div></code></pre></div></div>\n<p>Every arrow is a potential latency cliff. Every one is debuggable. And now you know where to look.</p>\n<p>The internet is not magic. It's layers of engineering held together by RFCs, backwards compatibility, and the stubbornness of protocol designers who refuse to accept \"good enough.\"</p>\n<p>Next time your page loads slowly, open DevTools. Look at the waterfall. Ask: <em>which layer is bleeding time?</em> DNS? TCP slow start? Render-blocking script? Layout thrash? You now have the mental model to answer that.</p>\n<p><em>Your scalpels: Chrome DevTools <strong>Network panel</strong> (timing breakdown), <strong>Performance panel</strong> (frame analysis), <strong><code>chrome://net-internals</code></strong> (socket pools, DNS cache, QUIC sessions), and <strong>WebPageTest</strong> (real-device global testing).</em></p>",
            "url": "https://blogs.pranjalkumar.in/blog/how-the-internet-actually-works",
            "title": "Internet working: What actually happens when you hit Enter on a URL",
            "summary": "An in-depth walkthrough of every layer the network stack touches - from the keyboard interrupt to the final composite frame - covering ARP, DNS recursion, TCP state machines, TLS 1.3 0-RTT, HTTP/2 multiplexing, QUIC, kernel socket buffers, browser process orchestration, speculative parsing, and GPU rasterization.",
            "date_modified": "2026-01-26T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "networking",
                "browser",
                "dns",
                "tcp",
                "tls",
                "http",
                "system-design",
                "architecture"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/aws-s3-object-storage",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" alt=\"AWS S3 internal working explained | Pranjal Kumar\" src=\"https://blogs.pranjalkumar.in/assets/images/aws-s3-internals-explained%20by%20Pranjal%20Kumar%20-%20software%20engineer-29252d109b924c88897631cc47096fa0.png\" width=\"1536\" height=\"1024\" class=\"img_ev3q\">\nWhen people first hear about Amazon S3, they usually think of it as “cloud file storage.”</p>\n<p>That description is convenient, but architecturally misleading.</p>\n<p>S3 is not a giant hard drive in the sky. It is not a shared folder. It is not a filesystem with infinite space. And it is almost certainly not just a pile of premium SSDs waiting to serve your objects.</p>\n<p>A better mental model is this:</p>\n<blockquote>\n<p><strong>S3 is a massive distributed object storage system that converts unreliable commodity hardware into durable, highly available, high-throughput storage through software, redundancy, metadata systems, erasure coding, checksums, repair loops, and extreme parallelism.</strong></p>\n</blockquote>\n<p>The magic of S3 is not that AWS buys the fastest discs.</p>\n<p>The magic is that AWS operates so many discs, across so many failure domains, with so much automation, that the system behaves like something far more powerful than the sum of its parts.</p>\n<p>Or, put more simply:</p>\n<blockquote>\n<p><strong>You do not buy the fastest disk. You buy so many slow ones that they behave like a supercomputer.</strong></p>\n</blockquote>\n<p>That sentence captures the soul of S3.</p>\n<p>But the deeper question is:</p>\n<blockquote>\n<p><strong>How does a system made of ordinary failure-prone hardware deliver extraordinary reliability?</strong></p>\n</blockquote>\n<p>That is where S3 becomes fascinating.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"misconception-s3-must-be-ssd-backed\">Misconception: \"S3 must be SSD-backed\"<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#misconception-s3-must-be-ssd-backed\" class=\"hash-link\" aria-label=\"Direct link to Misconception: &quot;S3 must be SSD-backed&quot;\" title=\"Direct link to Misconception: &quot;S3 must be SSD-backed&quot;\" translate=\"no\">​</a></h2>\n<p>Many engineers assume S3 must be powered primarily by SSDs because it feels cloud-native, fast, and infinitely scalable.</p>\n<p>But S3’s economics are fundamentally different from a low-latency database or an NVMe-backed transactional system.</p>\n<p>SSDs are excellent when you need low-latency random I/O and high IOPS from a small number of devices.</p>\n<p>HDDs are excellent when you need massive capacity at low cost per terabyte.</p>\n<p>S3 is primarily an object storage system optimized for:</p>\n<ul>\n<li class=\"\">Durability</li>\n<li class=\"\">Scale</li>\n<li class=\"\">Throughput</li>\n<li class=\"\">Availability</li>\n<li class=\"\">Cost efficiency</li>\n<li class=\"\">Operational simplicity for customers</li>\n</ul>\n<p>It is not designed as a single-digit millisecond random-mutation storage engine for tiny records.</p>\n<p>The tradeoff looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">SSD:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Excellent random I/O</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Higher IOPS per device</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Lower latency</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Higher cost per TB</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">HDD:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Lower random IOPS</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Great sequential throughput</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Much lower cost per TB</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Excellent for massive object storage when parallelized</span><br></div></code></pre></div></div>\n<p>S3’s brilliance is that it does not try to make one disk fast.</p>\n<p>It makes thousands or millions of discs cooperate.</p>\n<p>That is a completely different optimization strategy.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"parallelism-over-speed\">Parallelism over speed<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#parallelism-over-speed\" class=\"hash-link\" aria-label=\"Direct link to Parallelism over speed\" title=\"Direct link to Parallelism over speed\" translate=\"no\">​</a></h2>\n<p>If you store a large object on one disk, your read throughput is bounded by that disk.</p>\n<p>But if you split the object into many pieces and distribute those pieces across many discs, servers, racks, and Availability Zones, you can read many fragments in parallel.</p>\n<p>Conceptually:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Large object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Split into shards</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Distribute across many drives</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Read shards in parallel</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Validate and reassemble object</span><br></div></code></pre></div></div>\n<p>This is why the torrent analogy is useful.</p>\n<p>In BitTorrent, a file downloads faster because many peers provide different pieces simultaneously. S3’s internal design is not literally BitTorrent, but the high-level performance idea is similar:</p>\n<blockquote>\n<p><strong>Aggregate throughput comes from parallelism.</strong></p>\n</blockquote>\n<p>One HDD may only provide modest IOPS.</p>\n<p>But thousands of HDDs serving predictable sequential ranges in parallel can provide enormous aggregate throughput.</p>\n<p>This is one of the most important distributed-systems lessons:</p>\n<blockquote>\n<p><strong>At cloud scale, the performance unit is not the disk. It is the fleet.</strong></p>\n</blockquote>\n<p>A single disk is slow.</p>\n<p>A coordinated fleet of discs can behave like a storage supercomputer.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"object-storage-not-a-filesystem\">Object storage, not a filesystem<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#object-storage-not-a-filesystem\" class=\"hash-link\" aria-label=\"Direct link to Object storage, not a filesystem\" title=\"Direct link to Object storage, not a filesystem\" translate=\"no\">​</a></h2>\n<p>A filesystem gives you directories, in-place mutation, file locking, append semantics, fine-grained metadata operations, and often POSIX-like behavior.</p>\n<p>S3 gives you something different:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bucket + key → object</span><br></div></code></pre></div></div>\n<p>An object is not just bytes. It can include:</p>\n<ul>\n<li class=\"\">Object data</li>\n<li class=\"\">Key/name</li>\n<li class=\"\">Metadata</li>\n<li class=\"\">Version information if versioning is enabled</li>\n<li class=\"\">Tags</li>\n<li class=\"\">ACL and policy-related access context</li>\n<li class=\"\">Checksum and integrity metadata</li>\n<li class=\"\">Encryption context depending on configuration</li>\n</ul>\n<p>This object model is one reason S3 scales so well.</p>\n<p>It avoids many of the hardest problems in distributed filesystems:</p>\n<ul>\n<li class=\"\">Arbitrary in-place mutation</li>\n<li class=\"\">Fine-grained locking</li>\n<li class=\"\">Shared mutable file handles</li>\n<li class=\"\">POSIX directory semantics</li>\n<li class=\"\">Complex cross-directory consistency expectations</li>\n</ul>\n<p>Instead of pretending to be a traditional disk, S3 exposes a simpler abstraction:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">PUT object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">GET object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DELETE object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">LIST objects</span><br></div></code></pre></div></div>\n<p>That simplicity is not a limitation.</p>\n<p>It is a scalability feature.</p>\n<p>The less the system promises at the API layer, the more freedom it has internally to shard, replicate, encode, route, repair, migrate, and optimize.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-metadata-problem\">The metadata problem<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#the-metadata-problem\" class=\"hash-link\" aria-label=\"Direct link to The metadata problem\" title=\"Direct link to The metadata problem\" translate=\"no\">​</a></h2>\n<p>Most people think S3 is about storing bytes.</p>\n<p>At scale, storing bytes is only half the problem.</p>\n<p>The harder question is:</p>\n<blockquote>\n<p><strong>Given this bucket and key, where are the object fragments, what version is current, what policies apply, what encryption state exists, and what should the system return right now?</strong></p>\n</blockquote>\n<p>That is metadata.</p>\n<p>For every GET, PUT, DELETE, LIST, lifecycle transition, replication event, or restore request, S3 needs to coordinate metadata.</p>\n<p>A simplified S3 read path looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Client sends GET bucket/key</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Front-end request router receives request</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Authentication and policy checks happen</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Metadata/index layer resolves object location/version</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Storage fleet retrieves required data fragments</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Fragments are validated and assembled</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object is streamed back to client</span><br></div></code></pre></div></div>\n<p>This means S3 is not just a storage fleet.</p>\n<p>It is also a massive distributed metadata system.</p>\n<p>And metadata systems are where distributed storage usually becomes difficult.</p>\n<p>A system can have petabytes or exabytes of raw capacity, but if its metadata layer cannot answer location, version, permission, and lifecycle questions quickly and correctly, the storage system collapses operationally.</p>\n<p>The hidden challenge is not only:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Where are the bytes?</span><br></div></code></pre></div></div>\n<p>It is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">What are the correct bytes for this request at this exact moment?</span><br></div></code></pre></div></div>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"durability\">Durability<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#durability\" class=\"hash-link\" aria-label=\"Direct link to Durability\" title=\"Direct link to Durability\" translate=\"no\">​</a></h2>\n<p>The beginner view of durability is:</p>\n<blockquote>\n<p>“Store multiple copies.”</p>\n</blockquote>\n<p>The senior-engineer view is:</p>\n<blockquote>\n<p>“Assume discs fail, servers fail, racks fail, networks partition, software deploys go wrong, checksums catch corruption, repair systems lag, and correlated failure is the real enemy.”</p>\n</blockquote>\n<p>At S3 scale, failure is not an exception.</p>\n<p>Failure is the steady state.</p>\n<p>Somewhere, a disk is failing. Somewhere else, a server is unhealthy. Somewhere else, a network device is dropping packets. Somewhere else, background repair is rebuilding redundancy.</p>\n<p>The system cannot depend on every component being healthy.</p>\n<p>It must be designed so that component failure is boring.</p>\n<p>This is the core design philosophy:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Do not try to prevent all hardware failure.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Design the software so hardware failure does not matter.</span><br></div></code></pre></div></div>\n<p>That idea sounds simple until you try to implement it across millions of devices.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"replication-is-expensive\">Replication is expensive<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#replication-is-expensive\" class=\"hash-link\" aria-label=\"Direct link to Replication is expensive\" title=\"Direct link to Replication is expensive\" translate=\"no\">​</a></h2>\n<p>The simplest durability strategy is replication.</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object → copy 1</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object → copy 2</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object → copy 3</span><br></div></code></pre></div></div>\n<p>If one copy is lost, another copy survives.</p>\n<p>Replication is easy to reason about and often fast to read from. But it has a major cost problem.</p>\n<p>Three-way replication means storing roughly three times the data.</p>\n<p>For small systems, that may be acceptable.</p>\n<p>For S3-scale systems, that overhead becomes enormous.</p>\n<p>If you store exabytes of customer data, every extra percentage point of overhead translates into a massive physical and financial cost:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More drives</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More racks</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More buildings</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More power</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More cooling</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More networking</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More repair traffic</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">More operational complexity</span><br></div></code></pre></div></div>\n<p>This is why naive replication is not enough.</p>\n<p>S3 needs something more storage-efficient.</p>\n<p>That something is erasure coding.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"erasure-coding\">Erasure coding<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#erasure-coding\" class=\"hash-link\" aria-label=\"Direct link to Erasure coding\" title=\"Direct link to Erasure coding\" translate=\"no\">​</a></h2>\n<p>Erasure coding is one of the most important ideas behind large-scale storage systems.</p>\n<p>Instead of storing full copies of an object, the system splits the object into data shards and computes additional parity shards.</p>\n<p>You do not need every shard to reconstruct the object.</p>\n<p>You only need a sufficient subset.</p>\n<p>Conceptually:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Original object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Data shards:   D1 D2 D3 D4 D5 D6</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Parity shards: P1 P2 P3</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Store shards across different drives / servers / racks / AZs</span><br></div></code></pre></div></div>\n<p>If some shards are lost:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Available: D1 D2 D4 D5 D6 P2</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Missing:   D3 P1 P3</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Original object can still be reconstructed.</span><br></div></code></pre></div></div>\n<p>This is the same high-level idea behind Reed-Solomon-style coding used in many distributed storage systems.</p>\n<p>The system adds mathematically derived parity so that missing pieces can be rebuilt.</p>\n<p>The advantage is huge:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Naive replication:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Simple</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Fast reads</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  High storage overhead</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Erasure coding:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  More complex</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Requires repair math</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Much better storage efficiency</span><br></div></code></pre></div></div>\n<p>At S3 scale, storage efficiency is not a micro-optimization.</p>\n<p>It is the business model.</p>\n<p>Saving even a small percentage of storage overhead can mean enormous reductions in hardware, power, cooling, network, and operational cost.</p>\n<p>This is why the story is not:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 stores three full copies of everything and calls it a day.</span><br></div></code></pre></div></div>\n<p>The real story is closer to:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 uses redundancy schemes, placement, integrity checks, and repair systems to survive failures efficiently.</span><br></div></code></pre></div></div>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-repair-race\">The repair race<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#the-repair-race\" class=\"hash-link\" aria-label=\"Direct link to The repair race\" title=\"Direct link to The repair race\" translate=\"no\">​</a></h2>\n<p>S3’s famous durability target is often described as “eleven nines.”</p>\n<p>But the number itself is not magic.</p>\n<p>It emerges from an engineering model involving:</p>\n<ul>\n<li class=\"\">Device failure rates</li>\n<li class=\"\">Failure detection time</li>\n<li class=\"\">Repair throughput</li>\n<li class=\"\">Number of redundant fragments</li>\n<li class=\"\">Placement across independent failure domains</li>\n<li class=\"\">Correlated failure assumptions</li>\n<li class=\"\">Checksum validation</li>\n<li class=\"\">Operational discipline</li>\n</ul>\n<p>The deeper insight is:</p>\n<blockquote>\n<p><strong>Durability is a race between failure and repair.</strong></p>\n</blockquote>\n<p>If one drive fails, that is normal.</p>\n<p>If ten drives fail, that is normal at cloud scale.</p>\n<p>The dangerous case is when failures accumulate faster than the system can detect and repair lost redundancy.</p>\n<p>So S3 needs continuous background work:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Detect failed or unhealthy devices</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Identify affected objects/fragments</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Read surviving fragments</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Reconstruct missing fragments</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Write repaired fragments elsewhere</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Verify checksums</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Update metadata</span><br></div></code></pre></div></div>\n<p>This is not a one-time recovery operation.</p>\n<p>It is an endless repair loop.</p>\n<p>At S3 scale, the system is never in a perfectly static healthy state. Something is always failing somewhere.</p>\n<p>The goal is not to avoid failure.</p>\n<p>The goal is to repair faster than failure can accumulate.</p>\n<p>That is the real durability game.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"checksums\">Checksums<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#checksums\" class=\"hash-link\" aria-label=\"Direct link to Checksums\" title=\"Direct link to Checksums\" translate=\"no\">​</a></h2>\n<p>Durability is not only about missing discs.</p>\n<p>It is also about silent corruption.</p>\n<p>Bits can rot. Drives can return bad data. Network paths can corrupt packets. Software bugs can write the wrong bytes. Memory can flip bits. Firmware can misbehave.</p>\n<p>That is why checksums matter.</p>\n<p>A good storage system does not merely store bytes.</p>\n<p>It stores evidence that the bytes are still the same bytes.</p>\n<p>A simplified integrity flow looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Client uploads object with checksum</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 validates received data</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 stores object/fragments with integrity metadata</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Background systems revalidate stored data</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Corruption is repaired from healthy redundant fragments</span><br></div></code></pre></div></div>\n<p>This is a subtle but important point:</p>\n<blockquote>\n<p><strong>Redundancy without integrity checking can preserve corrupted data.</strong></p>\n</blockquote>\n<p>If a system has three copies but does not know which one is correct, replication alone is not enough.</p>\n<p>Checksums are what let the system detect and reason about correctness.</p>\n<p>Without integrity metadata, a storage system may become very good at preserving the wrong bytes.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"availability\">Availability<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#availability\" class=\"hash-link\" aria-label=\"Direct link to Availability\" title=\"Direct link to Availability\" translate=\"no\">​</a></h2>\n<p>Durability asks:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Will my data survive?</span><br></div></code></pre></div></div>\n<p>Availability asks:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Can I access it right now?</span><br></div></code></pre></div></div>\n<p>These are different properties.</p>\n<p>A system can be durable but temporarily unavailable.</p>\n<p>For example, your data may be safely stored, but a metadata service, network path, authorization service, or regional dependency may prevent immediate access.</p>\n<p>S3 availability requires:</p>\n<ul>\n<li class=\"\">Request routing</li>\n<li class=\"\">Healthy front-end fleets</li>\n<li class=\"\">Metadata availability</li>\n<li class=\"\">Fragment availability</li>\n<li class=\"\">Load balancing</li>\n<li class=\"\">Retry behavior</li>\n<li class=\"\">Failure isolation</li>\n<li class=\"\">Capacity planning</li>\n<li class=\"\">Operational safety during deployments</li>\n</ul>\n<p>S3 must handle failures at many levels:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Disk failure</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Server failure</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Rack failure</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Network failure</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Availability Zone impairment</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Overload</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Software deployment issue</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Metadata partition issue</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Regional control-plane issue</span><br></div></code></pre></div></div>\n<p>A highly available system does not require every component to be healthy.</p>\n<p>It requires enough independent components to be healthy so the request can complete.</p>\n<p>That is why S3 distributes data and metadata across failure domains.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"strong-consistency\">Strong consistency<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#strong-consistency\" class=\"hash-link\" aria-label=\"Direct link to Strong consistency\" title=\"Direct link to Strong consistency\" translate=\"no\">​</a></h2>\n<p>For many years, S3 was famously eventually consistent for some operations.</p>\n<p>That meant after writing an object, there could be a small window where reads or listings might not immediately reflect the latest state.</p>\n<p>This created pain for data lakes and big-data systems.</p>\n<p>Workloads sometimes needed extra consistency layers or commit protocols to avoid reading stale listings or missing newly written files.</p>\n<p>Then S3 evolved.</p>\n<p>S3 now provides strong read-after-write consistency for key operations such as reads, writes, lists, and metadata changes.</p>\n<p>This was a major architectural milestone.</p>\n<p>The deeper point is this:</p>\n<blockquote>\n<p><strong>S3 evolved from massively scalable object storage into massively scalable strongly consistent object storage.</strong></p>\n</blockquote>\n<p>That is not a small change.</p>\n<p>Strong consistency at S3 scale is a serious distributed-systems achievement.</p>\n<p>It means customers can build simpler data pipelines because the object store behaves more predictably after writes.</p>\n<p>For data lake systems, this reduced the need for certain external consistency workarounds.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"horizontal-scaling\">Horizontal scaling<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#horizontal-scaling\" class=\"hash-link\" aria-label=\"Direct link to Horizontal scaling\" title=\"Direct link to Horizontal scaling\" translate=\"no\">​</a></h2>\n<p>If you treat S3 like one disk behind one connection, you will leave performance on the table.</p>\n<p>S3 is designed to scale horizontally.</p>\n<p>The right performance model is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Many concurrent requests</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Multiple connections</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Multipart upload for large objects</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Byte-range GETs for parallel reads</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Distributed prefixes for high request rates</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Compute close to the bucket Region</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Caching for hot content</span><br></div></code></pre></div></div>\n<p>A high-throughput S3 client does not ask:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">How fast is one request?</span><br></div></code></pre></div></div>\n<p>It asks:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">How many independent requests can I safely run in parallel?</span><br></div></code></pre></div></div>\n<p>This is the same mental model behind most cloud-scale services.</p>\n<p>Throughput comes from concurrency.</p>\n<p>Latency comes from placement, routing, caching, and minimizing unnecessary hops.</p>\n<p>Efficiency comes from choosing the right object sizes, request patterns, and lifecycle policies.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"multipart-upload\">Multipart upload<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#multipart-upload\" class=\"hash-link\" aria-label=\"Direct link to Multipart upload\" title=\"Direct link to Multipart upload\" translate=\"no\">​</a></h2>\n<p>Multipart upload is one of the most important S3 performance features.</p>\n<p>Instead of uploading a huge object as one request, the client splits it into parts and uploads parts in parallel:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Large file</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Part 1 ─┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Part 2 ─┼── uploaded in parallel</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Part 3 ─┤</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Part 4 ─┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">CompleteMultipartUpload</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">   ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 assembles object</span><br></div></code></pre></div></div>\n<p>This improves:</p>\n<ul>\n<li class=\"\">Throughput</li>\n<li class=\"\">Retry efficiency</li>\n<li class=\"\">Failure recovery</li>\n<li class=\"\">Upload stability for large objects</li>\n</ul>\n<p>If part 37 fails, you retry part 37.</p>\n<p>You do not restart the entire upload.</p>\n<p>This is a core pattern in distributed systems:</p>\n<blockquote>\n<p><strong>Split large work into independently retryable chunks.</strong></p>\n</blockquote>\n<p>Multipart upload is not just a convenience feature.</p>\n<p>It is the API exposing the same principle S3 uses internally: large work should be sharded, parallelized, and made retryable.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"small-objects\">Small objects<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#small-objects\" class=\"hash-link\" aria-label=\"Direct link to Small objects\" title=\"Direct link to Small objects\" translate=\"no\">​</a></h2>\n<p>S3 can store huge numbers of objects, but not all object layouts are equally efficient.</p>\n<p>A billion 1 KB objects are very different from a thousand 1 GB objects.</p>\n<p>Small objects create overhead in:</p>\n<ul>\n<li class=\"\">Request cost</li>\n<li class=\"\">Metadata cost</li>\n<li class=\"\">LIST operations</li>\n<li class=\"\">Lifecycle transitions</li>\n<li class=\"\">Archive overhead</li>\n<li class=\"\">Analytics query planning</li>\n<li class=\"\">Replication overhead</li>\n<li class=\"\">Operational complexity</li>\n</ul>\n<p>This is why data lake engineers often compact small files into larger columnar files like Parquet.</p>\n<p>S3 can store tiny objects.</p>\n<p>But your architecture should not accidentally create a small-file disaster.</p>\n<p>A bad small-file layout can make analytics slow, lifecycle policies noisy, metadata operations expensive, and archival transitions inefficient.</p>\n<p>Good object layout matters.</p>\n<p>A common pattern is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bad:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  millions of tiny JSON files</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Better:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  compacted Parquet files partitioned by date/customer/region</span><br></div></code></pre></div></div>\n<p>The storage service can scale, but that does not mean every layout is equally wise.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"storage-classes\">Storage classes<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#storage-classes\" class=\"hash-link\" aria-label=\"Direct link to Storage classes\" title=\"Direct link to Storage classes\" translate=\"no\">​</a></h2>\n<p>S3 is really a family of storage classes with different tradeoffs.</p>\n<p>At a high level:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Standard:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Frequently accessed data</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Intelligent-Tiering:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Unknown or changing access patterns</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Standard-IA:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Infrequently accessed but needs milliseconds retrieval</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 One Zone-IA:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Lower-cost infrequent access in one Availability Zone</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Glacier Instant Retrieval:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Archive data with milliseconds access</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Glacier Flexible Retrieval:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Archive data with minutes-to-hours retrieval</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Glacier Deep Archive:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Lowest-cost archive with hours-level retrieval</span><br></div></code></pre></div></div>\n<p>This is a crucial architectural principle:</p>\n<blockquote>\n<p><strong>The cheapest byte is the byte whose access pattern you understand.</strong></p>\n</blockquote>\n<p>If data is hot, keep it in a hot class.</p>\n<p>If it is cold but needs instant access, use an instant retrieval class.</p>\n<p>If it is archival and rarely read, use Glacier Flexible Retrieval or Deep Archive.</p>\n<p>Storage class selection is not just an AWS billing exercise.</p>\n<p>It is an architectural decision about latency, cost, retrieval behavior, and operational expectations.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"glacier-where-cost-optimization-goes-even-deeper\">Glacier: where cost optimization goes even deeper<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#glacier-where-cost-optimization-goes-even-deeper\" class=\"hash-link\" aria-label=\"Direct link to Glacier: where cost optimization goes even deeper\" title=\"Direct link to Glacier: where cost optimization goes even deeper\" translate=\"no\">​</a></h2>\n<p>Glacier storage classes are designed for archive workloads where retrieval latency can be minutes or hours instead of milliseconds.</p>\n<p>That tells us something important:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Standard optimizes for frequent access.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Glacier optimizes for low-cost retention.</span><br></div></code></pre></div></div>\n<p>Some reports and discussions suggest archive systems may use very low-cost media such as tape-like systems, but AWS does not fully disclose the exact hardware implementation.</p>\n<p>So the correct engineering stance is:</p>\n<blockquote>\n<p><strong>Reason from the service contract, not from unverified hardware assumptions.</strong></p>\n</blockquote>\n<p>The service contract says Glacier trades retrieval latency for lower storage cost.</p>\n<p>That alone tells us the architecture is optimized differently from hot S3 Standard storage.</p>\n<p>A good archival design should consider:</p>\n<ul>\n<li class=\"\">Retrieval time objective</li>\n<li class=\"\">Retrieval cost</li>\n<li class=\"\">Minimum storage duration</li>\n<li class=\"\">Restore workflow</li>\n<li class=\"\">Compliance retention</li>\n<li class=\"\">Object size</li>\n<li class=\"\">Restore concurrency</li>\n<li class=\"\">Whether users expect instant access</li>\n</ul>\n<p>Archival storage is cheap only when the workflow matches the storage class.</p>\n<p>If you frequently restore from deep archive, your architecture may be fighting the product design.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"lifecycle-policies\">Lifecycle policies<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#lifecycle-policies\" class=\"hash-link\" aria-label=\"Direct link to Lifecycle policies\" title=\"Direct link to Lifecycle policies\" translate=\"no\">​</a></h2>\n<p>S3 cost is not just dollars per GB.</p>\n<p>It includes:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Storage cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Request cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Retrieval cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Data transfer cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Lifecycle transition cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Replication cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">KMS cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Monitoring and automation cost</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Minimum storage duration penalties</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Small-object overhead</span><br></div></code></pre></div></div>\n<p>Lifecycle policies are powerful because they let storage follow data temperature.</p>\n<p>A typical log retention policy might look like:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">0–30 days:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  S3 Standard</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">30–90 days:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  S3 Standard-IA or Intelligent-Tiering</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">90+ days:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Glacier Flexible Retrieval</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">1+ year:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Glacier Deep Archive</span><br></div></code></pre></div></div>\n<p>But lifecycle policies can also create surprises.</p>\n<p>Bad lifecycle rules can save storage cost but increase:</p>\n<ul>\n<li class=\"\">Restore latency</li>\n<li class=\"\">Retrieval cost</li>\n<li class=\"\">Operational friction</li>\n<li class=\"\">Analytics failures</li>\n<li class=\"\">Customer support incidents</li>\n</ul>\n<p>A good lifecycle policy starts with access patterns, not pricing pages.</p>\n<p>Ask:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">How often is this data read?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">How quickly must it be restored?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Who owns restore operations?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">What is the compliance requirement?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">What is the minimum retention period?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">What happens if restore takes 12 hours?</span><br></div></code></pre></div></div>\n<p>Cost optimization without workflow understanding is just delayed pain.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"security\">Security<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#security\" class=\"hash-link\" aria-label=\"Direct link to Security\" title=\"Direct link to Security\" translate=\"no\">​</a></h2>\n<p>S3 itself provides strong security capabilities.</p>\n<p>The most common real-world S3 failures usually come from misconfiguration:</p>\n<ul>\n<li class=\"\">Public buckets</li>\n<li class=\"\">Overly broad IAM policies</li>\n<li class=\"\">Leaked credentials</li>\n<li class=\"\">Weak bucket policies</li>\n<li class=\"\">Ungoverned cross-account access</li>\n<li class=\"\">Missing encryption governance</li>\n<li class=\"\">Poor logging and detection</li>\n</ul>\n<p>A mature S3 security baseline should include:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Block Public Access at organization/account level</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Least-privilege IAM</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bucket policies with explicit conditions</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">SSE-KMS for sensitive data</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Bucket Keys where appropriate</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">CloudTrail data events for sensitive buckets</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 Inventory and Storage Lens</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object Lock for WORM/compliance use cases</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Versioning for recovery</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Replication for resilience and compliance</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Access Analyzer for policy review</span><br></div></code></pre></div></div>\n<p>S3 security is not one setting.</p>\n<p>It is a governance system.</p>\n<p>The biggest mistake is treating S3 as “just storage” and forgetting that it often contains the organization’s most valuable data:</p>\n<ul>\n<li class=\"\">Customer data</li>\n<li class=\"\">Logs</li>\n<li class=\"\">Backups</li>\n<li class=\"\">ML datasets</li>\n<li class=\"\">Financial exports</li>\n<li class=\"\">Production artifacts</li>\n<li class=\"\">Security telemetry</li>\n<li class=\"\">Data lake tables</li>\n</ul>\n<p>If S3 is your data lake, then S3 is part of your security perimeter.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"encryption\">Encryption<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#encryption\" class=\"hash-link\" aria-label=\"Direct link to Encryption\" title=\"Direct link to Encryption\" translate=\"no\">​</a></h2>\n<p>S3 encryption is often explained too simply.</p>\n<p>At a high level, there are two common server-side encryption models:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">SSE-S3:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  S3 manages encryption keys.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">SSE-KMS:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  AWS KMS manages keys with stronger customer control, auditability, and policy governance.</span><br></div></code></pre></div></div>\n<p>SSE-S3 is simple and low-friction.</p>\n<p>SSE-KMS gives stronger governance knobs:</p>\n<ul>\n<li class=\"\">Key policies</li>\n<li class=\"\">CloudTrail visibility</li>\n<li class=\"\">Key rotation controls</li>\n<li class=\"\">Cross-account controls</li>\n<li class=\"\">Separation of duties</li>\n<li class=\"\">Conditional access policies</li>\n</ul>\n<p>But SSE-KMS also introduces architectural considerations:</p>\n<ul>\n<li class=\"\">KMS request volume</li>\n<li class=\"\">KMS quotas</li>\n<li class=\"\">KMS cost</li>\n<li class=\"\">Cross-account key policy complexity</li>\n<li class=\"\">Multi-region key strategy</li>\n<li class=\"\">Operational blast radius if key access breaks</li>\n</ul>\n<p>For sensitive enterprise data, SSE-KMS is often the right choice.</p>\n<p>But it should be designed deliberately.</p>\n<p>Encryption is not only about cryptography.</p>\n<p>It is about ownership, auditability, key lifecycle, and operational failure modes.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"versioning-and-object-lock\">Versioning and Object Lock<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#versioning-and-object-lock\" class=\"hash-link\" aria-label=\"Direct link to Versioning and Object Lock\" title=\"Direct link to Versioning and Object Lock\" translate=\"no\">​</a></h2>\n<p>S3 versioning is one of the most underrated safety features.</p>\n<p>Without versioning:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Accidental overwrite or delete → object may be gone</span><br></div></code></pre></div></div>\n<p>With versioning:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Overwrite creates new version</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Delete creates delete marker</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Older versions can be recovered</span><br></div></code></pre></div></div>\n<p>Versioning helps with:</p>\n<ul>\n<li class=\"\">Accidental deletion</li>\n<li class=\"\">Bad deployments</li>\n<li class=\"\">Corrupt uploads</li>\n<li class=\"\">Ransomware-style overwrite attempts</li>\n<li class=\"\">Human mistakes</li>\n</ul>\n<p>Object Lock goes further by supporting write-once-read-many behavior for compliance and retention scenarios.</p>\n<p>A mature backup/archive architecture often combines:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Versioning</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object Lock</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Lifecycle policies</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cross-region replication</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Restricted delete permissions</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">CloudTrail audit logs</span><br></div></code></pre></div></div>\n<p>The key principle is:</p>\n<blockquote>\n<p><strong>Backups are not real backups unless they are protected from the same identities and automation that can destroy production.</strong></p>\n</blockquote>\n<p>S3 gives you primitives, but you still need a recovery architecture.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"replication-vs-disaster-recovery\">Replication vs disaster recovery<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#replication-vs-disaster-recovery\" class=\"hash-link\" aria-label=\"Direct link to Replication vs disaster recovery\" title=\"Direct link to Replication vs disaster recovery\" translate=\"no\">​</a></h2>\n<p>S3 durability inside a Region is not the same as cross-region disaster recovery.</p>\n<p>If your requirement is regional resilience, compliance locality, or faster recovery from regional disruption, you may need replication.</p>\n<p>Common replication patterns include:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Same-Region Replication:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Compliance, log aggregation, account separation</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cross-Region Replication:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Disaster recovery, geographic resilience, data locality</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Replication Time Control:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  More predictable replication SLA requirements</span><br></div></code></pre></div></div>\n<p>Replication introduces its own tradeoffs:</p>\n<ul>\n<li class=\"\">Additional storage cost</li>\n<li class=\"\">Request cost</li>\n<li class=\"\">Replication lag</li>\n<li class=\"\">KMS key configuration</li>\n<li class=\"\">Delete marker behavior</li>\n<li class=\"\">Versioning requirement</li>\n<li class=\"\">Cross-account policy complexity</li>\n</ul>\n<p>A principal engineer should distinguish clearly between:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Durability:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Will the object survive local device/AZ failures?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Availability:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Can I access it now?</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Disaster recovery:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  Can my business continue if a larger regional event occurs?</span><br></div></code></pre></div></div>\n<p>They are related, but not identical.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"event-driven-patterns\">Event-driven patterns<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#event-driven-patterns\" class=\"hash-link\" aria-label=\"Direct link to Event-driven patterns\" title=\"Direct link to Event-driven patterns\" translate=\"no\">​</a></h2>\n<p>S3 is also commonly used as an event source.</p>\n<p>For example:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Object uploaded to bucket</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 event notification</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Lambda / SQS / SNS / EventBridge</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">        ↓</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Processing pipeline</span><br></div></code></pre></div></div>\n<p>This pattern powers:</p>\n<ul>\n<li class=\"\">Image processing</li>\n<li class=\"\">Document ingestion</li>\n<li class=\"\">Data lake ETL</li>\n<li class=\"\">Malware scanning</li>\n<li class=\"\">Metadata extraction</li>\n<li class=\"\">ML feature generation</li>\n<li class=\"\">Log processing</li>\n</ul>\n<p>But event-driven S3 systems require careful design.</p>\n<p>You should think about:</p>\n<ul>\n<li class=\"\">Idempotency</li>\n<li class=\"\">Duplicate events</li>\n<li class=\"\">Ordering assumptions</li>\n<li class=\"\">Partial failure</li>\n<li class=\"\">Poison messages</li>\n<li class=\"\">Retry behavior</li>\n<li class=\"\">Backpressure</li>\n<li class=\"\">Dead-letter queues</li>\n</ul>\n<p>A robust S3 ingestion pipeline should assume that processing can happen more than once.</p>\n<p>The safe design is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Every object processing operation should be idempotent.</span><br></div></code></pre></div></div>\n<p>If your pipeline breaks when the same event is delivered twice, the pipeline is not production-grade.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"putting-it-together\">Putting it together<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#putting-it-together\" class=\"hash-link\" aria-label=\"Direct link to Putting it together\" title=\"Direct link to Putting it together\" translate=\"no\">​</a></h2>\n<p>A simplified mental model of S3 looks like this:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   ┌────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   │      Client        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   └─────────┬──────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                             │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                             ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   ┌────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   │  S3 Front-End/API  │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                   └─────────┬──────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                             │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                ┌────────────┴────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                ▼                         ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      ┌──────────────────┐       ┌──────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      │ Auth/Policy Path │       │ Metadata/Index   │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      └──────────────────┘       └─────────┬────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                                           │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                                           ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              ┌──────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              │ Object Placement Map │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              └─────────┬────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                                        │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">          ┌─────────────────────────────┼─────────────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">          ▼                             ▼                             ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">┌──────────────────┐          ┌──────────────────┐          ┌──────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│ Storage Fleet AZ1│          │ Storage Fleet AZ2│          │ Storage Fleet AZ3│</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">│ Data fragments   │          │ Data fragments   │          │ Parity fragments │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">└──────────────────┘          └──────────────────┘          └──────────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">          │                             │                             │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">          └─────────────────────────────┼─────────────────────────────┘</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                                        ▼</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              ┌──────────────────────┐</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              │ Repair + Scrubbing   │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              │ Checksums + Metrics  │</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">                              └──────────────────────┘</span><br></div></code></pre></div></div>\n<p>This is not AWS’s exact internal architecture.</p>\n<p>It is the right conceptual model.</p>\n<p>S3 is a collection of control planes and data planes working together:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Data plane:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  PUT, GET, DELETE, LIST, multipart upload, restore</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Control plane:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  bucket configuration, policies, lifecycle, replication, encryption config</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Background systems:</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  repair, checksum validation, lifecycle transitions, inventory, replication, monitoring</span><br></div></code></pre></div></div>\n<p>The background systems are not secondary.</p>\n<p>They are what make the durability promise real.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"why-s3-won\">Why S3 won<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#why-s3-won\" class=\"hash-link\" aria-label=\"Direct link to Why S3 won\" title=\"Direct link to Why S3 won\" translate=\"no\">​</a></h2>\n<p>S3 is now more than object storage.</p>\n<p>It is the storage substrate for:</p>\n<ul>\n<li class=\"\">Data lakes</li>\n<li class=\"\">ML training datasets</li>\n<li class=\"\">Backups</li>\n<li class=\"\">Static websites</li>\n<li class=\"\">Media pipelines</li>\n<li class=\"\">Log archives</li>\n<li class=\"\">Lakehouse tables</li>\n<li class=\"\">Serverless applications</li>\n<li class=\"\">Event-driven pipelines</li>\n<li class=\"\">Compliance archives</li>\n<li class=\"\">Disaster recovery</li>\n</ul>\n<p>The reason is simple:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">S3 separated storage from compute.</span><br></div></code></pre></div></div>\n<p>Before S3-style architectures, storage and compute were often tightly coupled.</p>\n<p>Your data lived on the same cluster that processed it.</p>\n<p>S3 changed that.</p>\n<p>Now you can store data once and process it with many different compute engines:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Athena</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">EMR</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Glue</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Redshift Spectrum</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Spark</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Presto/Trino</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Lambda</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">SageMaker</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Snowflake external tables</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Databricks</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Custom EC2/EKS workloads</span><br></div></code></pre></div></div>\n<p>This separation is one of the biggest architectural shifts in cloud computing.</p>\n<p>It allowed organizations to build data lakes where storage is durable, cheap, and independent of the compute engines that query it.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"takeaway\">Takeaway<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#takeaway\" class=\"hash-link\" aria-label=\"Direct link to Takeaway\" title=\"Direct link to Takeaway\" translate=\"no\">​</a></h2>\n<p>S3 is not impressive because it stores files.</p>\n<p>S3 is impressive because it turns failure into a normal operating condition.</p>\n<p>It assumes:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Discs will fail.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Servers will fail.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Networks will fail.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Racks will fail.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Availability Zones may be impaired.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Bits may corrupt.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Customers will create unpredictable workloads.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Access patterns will change.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Costs must remain low.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Performance must scale horizontally.</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Security must be configurable but safe by default.</span><br></div></code></pre></div></div>\n<p>And still, the system provides a simple API:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">PUT object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">GET object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">DELETE object</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">LIST objects</span><br></div></code></pre></div></div>\n<p>That simplicity hides enormous complexity.</p>\n<p>The true genius of S3 is this:</p>\n<blockquote>\n<p><strong>It gives developers a simple object abstraction while hiding one of the most sophisticated distributed storage systems ever built.</strong></p>\n</blockquote>\n<p>S3’s story is not:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">AWS has big discs.</span><br></div></code></pre></div></div>\n<p>S3’s story is:</p>\n<div class=\"language-text codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-text codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cheap hardware</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ extreme parallelism</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ erasure coding</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ checksums</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ metadata systems</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ repair loops</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ lifecycle automation</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">+ operational discipline</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">= planet-scale durable storage</span><br></div></code></pre></div></div>\n<p>That is the lesson worth remembering.</p>\n<p>The future of storage is not about one infinitely fast disk.</p>\n<p>It is about fleets.</p>\n<p>It is about failure-aware software.</p>\n<p>It is about mathematical redundancy.</p>\n<p>It is about background repair.</p>\n<p>It is about turning unreliable parts into a reliable whole.</p>\n<p>That is what S3 does.</p>\n<p>And that is why S3 is one of the most important distributed systems in the history of cloud computing.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"references\">References<a href=\"https://blogs.pranjalkumar.in/blog/aws-s3-object-storage#references\" class=\"hash-link\" aria-label=\"Direct link to References\" title=\"Direct link to References\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><a href=\"https://aws.amazon.com/video/watch/65acaf1dec0/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">AWS Video Hub: Amazon S3 Deep Dive</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/s3/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 Documentation</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/DataDurability.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Data protection and durability</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/optimizing-performance.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Performance guidelines</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/mpuoverview.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Multipart upload</a></li>\n<li class=\"\"><a href=\"https://aws.amazon.com/blogs/aws/amazon-s3-update-strong-read-after-write-consistency/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">AWS News Blog: Amazon S3 Update - Strong Read-After-Write Consistency</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-class-intro.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Storage classes</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/glacier-storage-classes.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Glacier storage classes</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-control-block-public-access.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Block Public Access</a></li>\n<li class=\"\"><a href=\"https://docs.aws.amazon.com/AmazonS3/latest/userguide/serv-side-encryption.html\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon S3 User Guide: Server-side encryption</a></li>\n<li class=\"\"><a href=\"https://aws.amazon.com/builders-library/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Amazon Builders' Library</a></li>\n<li class=\"\"><a href=\"https://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">Dynamo: Amazon's Highly Available Key-value Store</a></li>\n</ul>",
            "url": "https://blogs.pranjalkumar.in/blog/aws-s3-object-storage",
            "title": "AWS S3: how cheap discs became durable storage at scale",
            "summary": "How Amazon S3 turns unreliable commodity HDDs into planet-scale durable storage through erasure coding, parallelism, repair loops, and distributed metadata systems.",
            "date_modified": "2025-11-04T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "aws",
                "s3",
                "cloud",
                "distributed-systems",
                "storage",
                "architecture"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/caching-vs-cdn",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" alt=\"Caching vs CDN — understanding where each belongs in your system architecture | Pranjal Kumar\" src=\"https://blogs.pranjalkumar.in/assets/images/caching-vs-cdn-explained%20by%20Pranjal%20Kumar%20-%20software%20engineer-48f9f95788cfd3f6afd1a14e95ba449b.png\" width=\"1536\" height=\"1024\" class=\"img_ev3q\"></p>\n<blockquote>\n<p>There are only two hard things in Computer Science: cache invalidation and naming things.\n— Phil Karlton</p>\n</blockquote>\n<p>Here’s a conversation I’ve had more times than I can count: someone on the team says \"let’s add a CDN\" when what they actually mean is \"we need caching.\" Or worse, someone implements Redis caching for static assets that should just live on a CDN edge node. Both are about serving content faster, but they solve fundamentally different problems, at different layers, with different tradeoffs.</p>\n<p>This post breaks down what each actually does under the hood, when to reach for one vs. the other, and how they work together in production systems.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-mental-model-layers-of-a-request\">The mental model: layers of a request<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-mental-model-layers-of-a-request\" class=\"hash-link\" aria-label=\"Direct link to The mental model: layers of a request\" title=\"Direct link to The mental model: layers of a request\" translate=\"no\">​</a></h2>\n<p>Before we compare them, let’s zoom out. When a user requests a resource, the request passes through multiple layers where speed-ups can happen:</p>\n<blockquote>\n<p><em><strong>Browser cache → CDN edge → Reverse proxy cache → Application cache → Database cache → Disk</strong></em></p>\n</blockquote>\n<ul>\n<li class=\"\"><strong>CDN territory:</strong> Browser cache, CDN edge</li>\n<li class=\"\"><strong>Caching territory:</strong> Application cache, Database cache, Disk</li>\n</ul>\n<p><strong>Caching</strong> is a technique — storing computed results closer to where they’re needed. It can happen at any layer: browser, server memory, Redis, database query cache, even CPU L1/L2/L3.</p>\n<p><strong>CDN</strong> is infrastructure — a geographically distributed network of servers that moves content physically closer to users. A CDN <em>uses</em> caching as its mechanism, but its value proposition is about <em>geography and network topology</em>, not just storage.</p>\n<p>Think of it this way: all CDNs cache, but not all caches are CDNs.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"caching-the-technique\">Caching: the technique<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#caching-the-technique\" class=\"hash-link\" aria-label=\"Direct link to Caching: the technique\" title=\"Direct link to Caching: the technique\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-it-actually-is\">What it actually is<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#what-it-actually-is\" class=\"hash-link\" aria-label=\"Direct link to What it actually is\" title=\"Direct link to What it actually is\" translate=\"no\">​</a></h3>\n<p>Caching is storing the result of an expensive computation or data retrieval so that future requests for the same thing can be served faster. The \"expensive\" part might be:</p>\n<ul>\n<li class=\"\">A database query that joins 5 tables and takes 200ms</li>\n<li class=\"\">A rendered HTML page that requires calling 3 microservices</li>\n<li class=\"\">An API response that involves complex business logic</li>\n<li class=\"\">A compiled asset (CSS, JS bundle) that doesn’t change between deploys</li>\n</ul>\n<p>The key insight: <strong>caching trades freshness for speed</strong>. Every cache is a bet that the data won’t change before someone asks for it again.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-caching-strategies-that-matter\">The caching strategies that matter<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-caching-strategies-that-matter\" class=\"hash-link\" aria-label=\"Direct link to The caching strategies that matter\" title=\"Direct link to The caching strategies that matter\" translate=\"no\">​</a></h3>\n<p>There are several patterns for how reads and writes interact with the cache:</p>\n<p><strong>Read-through (Cache-aside):</strong> The most common pattern. Application checks cache first; on miss, fetches from source, writes to cache, returns result.</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">getUser</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">userId</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Check cache first</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">const</span><span class=\"token plain\"> cached </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">await</span><span class=\"token plain\"> redis</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">get</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token template-string string\" style=\"color:hsl(95, 38%, 62%)\">user:</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">${</span><span class=\"token template-string interpolation\">userId</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:hsl(29, 54%, 61%)\">JSON</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">parse</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"> </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Cache hit: ~1ms</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Cache miss: fetch from DB (~50ms)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">const</span><span class=\"token plain\"> user </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token plain\"> </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">await</span><span class=\"token plain\"> db</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">query</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'SELECT * FROM users WHERE id = $1'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">userId</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Populate cache for next time (TTL: 1 hour)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">await</span><span class=\"token plain\"> redis</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">setex</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token template-string string\" style=\"color:hsl(95, 38%, 62%)\">user:</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">${</span><span class=\"token template-string interpolation\">userId</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">3600</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token known-class-name class-name\" style=\"color:hsl(29, 54%, 61%)\">JSON</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">stringify</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">user</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">return</span><span class=\"token plain\"> user</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><br></div></code></pre></div></div>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://www.imperva.com/wp-content/uploads/sites/13/2020/03/diagram-31@3x.png\" alt=\"How caching works — request flow through cache layer | Pranjal Kumar\" class=\"img_ev3q\"></p>\n<p><strong>Write-through:</strong> Every write goes to both cache and backing store synchronously. Guarantees consistency but adds write latency.</p>\n<p><strong>Write-behind (Write-back):</strong> Writes go to cache immediately; cache asynchronously flushes to backing store. Fast writes, but you risk data loss if the cache crashes before flushing.</p>\n<p><strong>Write-around:</strong> Writes go directly to the backing store, bypassing cache. The cache only gets populated on reads. Good when writes rarely get re-read.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"http-caching-headers-the-language-of-cache-control\">HTTP caching headers: the language of cache control<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#http-caching-headers-the-language-of-cache-control\" class=\"hash-link\" aria-label=\"Direct link to HTTP caching headers: the language of cache control\" title=\"Direct link to HTTP caching headers: the language of cache control\" translate=\"no\">​</a></h3>\n<p>This is where most developers first encounter caching, and where most mistakes happen. The HTTP spec gives us powerful cache control:</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">HTTP/1.1 200 OK</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cache-Control: public, max-age=31536000, immutable</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">ETag: \"a1b2c3d4\"</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Last-Modified: Wed, 15 Jan 2025 08:00:00 GMT</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Vary: Accept-Encoding</span><br></div></code></pre></div></div>\n<p>Let me break these down because they’re more nuanced than people realize:</p>\n<p><strong><code>Cache-Control</code> directives:</strong></p>\n<table><thead><tr><th>Directive</th><th>What it means</th><th>When to use</th></tr></thead><tbody><tr><td><code>public</code></td><td>Any cache (CDN, proxy, browser) can store this</td><td>Static assets, public pages</td></tr><tr><td><code>private</code></td><td>Only the user’s browser can cache this</td><td>User-specific data (dashboards, profiles)</td></tr><tr><td><code>no-cache</code></td><td>Cache it, but revalidate with origin before serving</td><td>Content that changes unpredictably</td></tr><tr><td><code>no-store</code></td><td>Don’t cache at all. Period.</td><td>Sensitive data (banking, health records)</td></tr><tr><td><code>max-age=N</code></td><td>Fresh for N seconds</td><td>Everything with a known TTL</td></tr><tr><td><code>s-maxage=N</code></td><td>Like max-age, but only for shared caches (CDNs)</td><td>When CDN TTL should differ from browser TTL</td></tr><tr><td><code>stale-while-revalidate=N</code></td><td>Serve stale content while fetching fresh in background</td><td>High-traffic pages where slight staleness is OK</td></tr><tr><td><code>immutable</code></td><td>This will never change (don’t even revalidate)</td><td>Fingerprinted assets (<code>app.a3b4c5.js</code>)</td></tr></tbody></table>\n<p><strong><code>ETag</code> and conditional requests:</strong> Instead of re-downloading a full response, the browser sends <code>If-None-Match: \"a1b2c3d4\"</code>. If the content hasn’t changed, the server responds with <code>304 Not Modified</code> — zero bytes transferred for the body.</p>\n<p><strong><code>stale-while-revalidate</code>:</strong> This is the underrated gem. It lets you serve a stale cached response immediately while fetching a fresh one in the background. Users always get instant responses, and the cache stays reasonably fresh. Cloudflare, Fastly, and modern browsers all support it.</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Cache-Control: public, max-age=60, stale-while-revalidate=300</span><br></div></code></pre></div></div>\n<p>This says: \"fresh for 60 seconds; after that, serve stale for up to 300 more seconds while revalidating.\" User never waits for origin.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cache-eviction-what-gets-kicked-out\">Cache eviction: what gets kicked out?<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#cache-eviction-what-gets-kicked-out\" class=\"hash-link\" aria-label=\"Direct link to Cache eviction: what gets kicked out?\" title=\"Direct link to Cache eviction: what gets kicked out?\" translate=\"no\">​</a></h3>\n<p>When the cache is full, something has to go. The eviction policy determines what:</p>\n<ul>\n<li class=\"\"><strong>LRU (Least Recently Used):</strong> Evicts the item not accessed for the longest time. Most common default (Redis, Memcached).</li>\n<li class=\"\"><strong>LFU (Least Frequently Used):</strong> Evicts the item accessed the fewest times. Better for skewed workloads where some items are consistently hot.</li>\n<li class=\"\"><strong>TTL-based:</strong> Items expire after a fixed time regardless of access patterns. Simple, predictable, but wastes cache space on items that could still serve hits.</li>\n<li class=\"\"><strong>Random:</strong> Surprisingly effective in some workloads and has zero overhead. Redis supports this as <code>allkeys-random</code>.</li>\n</ul>\n<p>In practice, <strong>LRU with TTLs</strong> is the sweet spot for most applications. Set a TTL as a safety net (data can’t be stale forever), and let LRU handle capacity management within that window.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-cache-invalidation-problem\">The cache invalidation problem<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-cache-invalidation-problem\" class=\"hash-link\" aria-label=\"Direct link to The cache invalidation problem\" title=\"Direct link to The cache invalidation problem\" translate=\"no\">​</a></h3>\n<p>Phil Karlton wasn’t joking. Cache invalidation is genuinely hard because you’re dealing with distributed state:</p>\n<p><strong>The stale data problem:</strong> User updates their profile. The database has the new data. But the cache still has the old data. For the next N seconds (until TTL expires), other users see stale information.</p>\n<p><strong>Strategies to handle this:</strong></p>\n<ol>\n<li class=\"\"><strong>TTL-based expiry:</strong> Accept bounded staleness. Simple, works for most cases.</li>\n<li class=\"\"><strong>Active invalidation:</strong> On write, explicitly delete/update the cache entry. Works within a single service but breaks down across distributed systems.</li>\n<li class=\"\"><strong>Event-driven invalidation:</strong> Publish a cache-invalidation event on write. All services holding cached copies listen and purge. More complex but consistent.</li>\n<li class=\"\"><strong>Versioned keys:</strong> Include a version number in cache keys (<code>user:123:v7</code>). On write, increment version. Old versions naturally become unreachable.</li>\n</ol>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Event-driven invalidation example</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">async</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">function</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">updateUser</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token parameter\">userId</span><span class=\"token parameter punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token parameter\"> data</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">await</span><span class=\"token plain\"> db</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">query</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'UPDATE users SET data = $1 WHERE id = $2'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token plain\">data</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> userId</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Publish invalidation event</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">await</span><span class=\"token plain\"> eventBus</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">.</span><span class=\"token method function property-access\" style=\"color:hsl(207, 82%, 66%)\">publish</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'cache.invalidate'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">key</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token template-string string\" style=\"color:hsl(95, 38%, 62%)\">user:</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">${</span><span class=\"token template-string interpolation\">userId</span><span class=\"token template-string interpolation interpolation-punctuation punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token template-string template-punctuation string\" style=\"color:hsl(95, 38%, 62%)\">`</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token literal-property property\" style=\"color:hsl(355, 65%, 65%)\">reason</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">'user_update'</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"where-caching-lives-in-practice\">Where caching lives in practice<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#where-caching-lives-in-practice\" class=\"hash-link\" aria-label=\"Direct link to Where caching lives in practice\" title=\"Direct link to Where caching lives in practice\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\"><strong>Redis/Memcached:</strong> Application-level caching. Session storage, query results, computed aggregations. Sub-millisecond reads, but limited to your data center.</li>\n<li class=\"\"><strong>Database query cache:</strong> MySQL’s query cache (deprecated in 8.0 for good reasons), PostgreSQL’s shared buffers. Transparent but limited control.</li>\n<li class=\"\"><strong>Application-level (in-process):</strong> <code>node-cache</code>, <code>lru-cache</code> (Node.js), Guava Cache, Caffeine (Java). Zero network overhead, but not shared across instances.</li>\n<li class=\"\"><strong>Reverse proxy cache:</strong> Nginx <code>proxy_cache</code>, Varnish. Caches full HTTP responses. Great for APIs and rendered pages.</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cdns-the-infrastructure\">CDNs: the infrastructure<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#cdns-the-infrastructure\" class=\"hash-link\" aria-label=\"Direct link to CDNs: the infrastructure\" title=\"Direct link to CDNs: the infrastructure\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-a-cdn-actually-is\">What a CDN actually is<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#what-a-cdn-actually-is\" class=\"hash-link\" aria-label=\"Direct link to What a CDN actually is\" title=\"Direct link to What a CDN actually is\" translate=\"no\">​</a></h3>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://doimages.nyc3.cdn.digitaloceanspaces.com/CDN.png\" alt=\"Content Delivery Network — globally distributed edge servers | Pranjal Kumar\" class=\"img_ev3q\"></p>\n<p>A CDN is a network of servers (called <strong>edge nodes</strong> or <strong>Points of Presence / PoPs</strong>) deployed in data centers worldwide. When a user requests content, the CDN routes them to the nearest edge node using <strong>anycast routing</strong> or <strong>DNS-based routing</strong>, so the data travels the shortest physical distance.</p>\n<p>The key insight: <strong>CDNs solve the speed-of-light problem.</strong> Light in fiber travels at ~200,000 km/s. A request from Mumbai to a server in Virginia is ~14,000 km — that’s 70ms just for the photons, one way. A CDN PoP in Mumbai makes that ~2ms.</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Without</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CDN</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">  </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">User</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Mumbai</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> ─── </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">14</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">000</span><span class=\"token plain\"> km ───</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Origin</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Virginia</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">RTT</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">~</span><span class=\"token plain\">140ms </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> server processing</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">With</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CDN</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\">     </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">User</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Mumbai</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> ─── </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">50</span><span class=\"token plain\"> km ───</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">CDN</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">PoP</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Mumbai</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">              </span><span class=\"token constant\" style=\"color:hsl(29, 54%, 61%)\">RTT</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">~</span><span class=\"token plain\">4ms </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">+</span><span class=\"token plain\"> edge </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">processing</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token keyword control-flow\" style=\"color:hsl(286, 60%, 67%)\">if</span><span class=\"token plain\"> cached</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><br></div></code></pre></div></div>\n<p>That’s a 35x improvement in network latency alone. For a page that makes 20 requests for CSS, JS, images, and fonts, this adds up fast.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"how-cdns-work-under-the-hood\">How CDNs work under the hood<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#how-cdns-work-under-the-hood\" class=\"hash-link\" aria-label=\"Direct link to How CDNs work under the hood\" title=\"Direct link to How CDNs work under the hood\" translate=\"no\">​</a></h3>\n<ol>\n<li class=\"\"><strong>DNS resolution:</strong> User requests <code>cdn.example.com</code>. DNS resolves to the nearest PoP’s IP (via anycast or geo-DNS).</li>\n<li class=\"\"><strong>Edge check:</strong> The PoP checks its local cache for the requested resource.</li>\n<li class=\"\"><strong>Cache hit:</strong> Serve directly from edge. Response time is dominated by the last-mile network latency (~5-20ms).</li>\n<li class=\"\"><strong>Cache miss:</strong> The PoP fetches from the <strong>origin server</strong> (your actual server). It caches the response according to the <code>Cache-Control</code> headers, then serves to the user.</li>\n<li class=\"\"><strong>Subsequent requests:</strong> Other users near the same PoP get the cached version until TTL expires.</li>\n</ol>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://media.geeksforgeeks.org/wp-content/uploads/20231222162112/Usecase-of-CDN.jpg\" alt=\"CDN architecture — how edge nodes, shields, and origin interact | Pranjal Kumar\" class=\"img_ev3q\"></p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-cdn-architecture-decisions\">The CDN architecture decisions<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-cdn-architecture-decisions\" class=\"hash-link\" aria-label=\"Direct link to The CDN architecture decisions\" title=\"Direct link to The CDN architecture decisions\" translate=\"no\">​</a></h3>\n<p><strong>Pull-based vs Push-based:</strong></p>\n<ul>\n<li class=\"\"><strong>Pull CDN:</strong> Content is fetched from origin on first request (cache miss), then cached. This is what Cloudflare, Fastly, and CloudFront do by default. Zero configuration for what gets cached.</li>\n<li class=\"\"><strong>Push CDN:</strong> You explicitly upload content to the CDN. Think S3 + CloudFront for static site hosting. More control, but more operational overhead.</li>\n</ul>\n<p><strong>Anycast routing:</strong> All CDN PoPs advertise the same IP address via BGP. The internet’s routing protocol naturally sends packets to the nearest PoP. This is how Cloudflare handles DDoS — attack traffic gets absorbed by the nearest PoP rather than concentrating on one location.</p>\n<p><strong>Tiered caching:</strong> Not every PoP goes directly to origin on a miss. CDNs use a hierarchy:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Edge</span><span class=\"token plain\"> </span><span class=\"token function maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">PoP</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">city</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">level</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Regional</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">shield</span><span class=\"token plain\"> </span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">(</span><span class=\"token plain\">continent</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">level</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">)</span><span class=\"token plain\"> → </span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Origin</span><br></div></code></pre></div></div>\n<p>This reduces origin load. If the Mumbai PoP has a miss, it asks the Singapore regional shield first. Only if Singapore also misses does the request go to origin. This is called <strong>origin shielding</strong> and can reduce origin traffic by 90%+.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-cdns-do-beyond-caching\">What CDNs do beyond caching<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#what-cdns-do-beyond-caching\" class=\"hash-link\" aria-label=\"Direct link to What CDNs do beyond caching\" title=\"Direct link to What CDNs do beyond caching\" translate=\"no\">​</a></h3>\n<p>Modern CDNs are more than just cache-and-serve. They’re now full <strong>edge compute platforms</strong>:</p>\n<ul>\n<li class=\"\"><strong>TLS termination:</strong> HTTPS handshake happens at the edge, not origin. Saves a round trip.</li>\n<li class=\"\"><strong>DDoS mitigation:</strong> Attack traffic is absorbed across hundreds of PoPs.</li>\n<li class=\"\"><strong>Edge compute:</strong> Cloudflare Workers, Fastly Compute, AWS Lambda@Edge. Run code at the edge without going to origin.</li>\n<li class=\"\"><strong>Image optimization:</strong> Automatic WebP/AVIF conversion, resizing, quality adjustment.</li>\n<li class=\"\"><strong>HTTP/3 and QUIC:</strong> CDN edges support the latest protocols even if your origin doesn’t.</li>\n<li class=\"\"><strong>Bot detection:</strong> Identify and block malicious traffic before it reaches origin.</li>\n<li class=\"\"><strong>Web Application Firewall (WAF):</strong> Security rules enforced at the edge.</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cdn-cache-invalidation\">CDN cache invalidation<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#cdn-cache-invalidation\" class=\"hash-link\" aria-label=\"Direct link to CDN cache invalidation\" title=\"Direct link to CDN cache invalidation\" translate=\"no\">​</a></h3>\n<p>CDN invalidation is trickier than application cache invalidation because you’re purging content across potentially hundreds of global nodes:</p>\n<p><strong>Purge by URL:</strong> Invalidate a specific resource. Propagates to all PoPs (usually takes 1-30 seconds depending on provider).</p>\n<p><strong>Purge by tag/surrogate key:</strong> Tag responses with categories (<code>product:123</code>, <code>category:electronics</code>). Purge all resources with a specific tag at once. Fastly does this in ~150ms globally.</p>\n<p><strong>Purge everything:</strong> Nuclear option. Clears all cached content. Use with caution on high-traffic sites; origin will get hammered.</p>\n<p><strong>The safer approach — versioned URLs:</strong></p>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">&lt;!-- Instead of purging, just change the URL --&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">link</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">rel</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">stylesheet</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">href</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">/css/app.css?v=a3b4c5</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">&lt;!-- Or better, use content-hash in filename --&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">link</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">rel</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">stylesheet</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">href</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">/css/app.a3b4c5.css</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><br></div></code></pre></div></div>\n<p>With content-hashed filenames, you never need to invalidate. Old versions age out naturally. New deploys reference new filenames. This is what Webpack, Vite, and every modern bundler do.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-actual-differences-beyond-the-obvious\">The actual differences (beyond the obvious)<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-actual-differences-beyond-the-obvious\" class=\"hash-link\" aria-label=\"Direct link to The actual differences (beyond the obvious)\" title=\"Direct link to The actual differences (beyond the obvious)\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"what-they-optimize-for\">What they optimize for<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#what-they-optimize-for\" class=\"hash-link\" aria-label=\"Direct link to What they optimize for\" title=\"Direct link to What they optimize for\" translate=\"no\">​</a></h3>\n<table><thead><tr><th></th><th><strong>Caching</strong></th><th><strong>CDN</strong></th></tr></thead><tbody><tr><td><strong>Primary problem</strong></td><td>Computation/retrieval is expensive</td><td>Users are physically far from servers</td></tr><tr><td><strong>Latency saved</strong></td><td>DB query time (50-500ms)</td><td>Network round-trip time (50-200ms)</td></tr><tr><td><strong>Layer</strong></td><td>Application logic layer</td><td>Network/transport layer</td></tr><tr><td><strong>Scope</strong></td><td>Single datacenter (usually)</td><td>Global</td></tr><tr><td><strong>Content type</strong></td><td>Any computed result (DB rows, API responses, rendered HTML)</td><td>Primarily HTTP responses (static and dynamic)</td></tr><tr><td><strong>Invalidation</strong></td><td>Programmatic, precise, fast</td><td>Global propagation, eventually consistent</td></tr><tr><td><strong>Cost model</strong></td><td>RAM/infrastructure you manage</td><td>Per-GB egress + request count</td></tr></tbody></table>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"when-to-use-which\">When to use which<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#when-to-use-which\" class=\"hash-link\" aria-label=\"Direct link to When to use which\" title=\"Direct link to When to use which\" translate=\"no\">​</a></h3>\n<p><strong>Use caching when:</strong></p>\n<ul>\n<li class=\"\">Your database is the bottleneck (slow queries, high read<!-- -->:write<!-- --> ratio)</li>\n<li class=\"\">You’re computing expensive results that don’t change often (reports, aggregations)</li>\n<li class=\"\">You need sub-millisecond response times within your service</li>\n<li class=\"\">You need fine-grained, programmatic invalidation</li>\n<li class=\"\">Your users are mostly in one geographic region</li>\n</ul>\n<p><strong>Use a CDN when:</strong></p>\n<ul>\n<li class=\"\">Your users are geographically distributed</li>\n<li class=\"\">You serve static assets (images, CSS, JS, fonts, videos)</li>\n<li class=\"\">You want to offload bandwidth from your origin servers</li>\n<li class=\"\">You need DDoS protection or edge security</li>\n<li class=\"\">You want TLS termination closer to users</li>\n<li class=\"\">Your time-to-first-byte is dominated by network latency, not computation</li>\n</ul>\n<p><strong>Use both when (most production systems):</strong></p>\n<ul>\n<li class=\"\">CDN at the edge for static assets and cacheable page responses</li>\n<li class=\"\">Application cache (Redis) behind the CDN for dynamic data assembly</li>\n<li class=\"\">Database cache as the last line of defense before hitting disk</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cache-control-in-practice-a-real-configuration\">Cache-Control in practice: a real configuration<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#cache-control-in-practice-a-real-configuration\" class=\"hash-link\" aria-label=\"Direct link to Cache-Control in practice: a real configuration\" title=\"Direct link to Cache-Control in practice: a real configuration\" translate=\"no\">​</a></h2>\n<p>Here’s how I’d configure caching for a typical web application with both a CDN and application caching:</p>\n<div class=\"language-nginx codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-nginx codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># Nginx configuration (behind CDN)</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># Static assets with content-hash in filename: cache forever</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">location ~* \\.(js|css)$ {</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    # Fingerprinted files never change</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Cache-Control \"public, max-age=31536000, immutable\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">}</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># Images: cache for 1 year on CDN, 1 week in browser</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">location ~* \\.(png|jpg|webp|svg|gif|ico)$ {</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Cache-Control \"public, max-age=604800, s-maxage=31536000\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">}</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># HTML pages: CDN caches for 60s, browser always revalidates</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">location ~* \\.html$ {</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Cache-Control \"public, max-age=0, s-maxage=60, stale-while-revalidate=300\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Surrogate-Key \"pages\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">}</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># API responses: private, short TTL, revalidate</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">location /api/ {</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Cache-Control \"private, max-age=0, must-revalidate\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header ETag $request_id;</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">}</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"># User-specific pages: never cache on shared caches</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">location /dashboard {</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    add_header Cache-Control \"private, no-store\";</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">}</span><br></div></code></pre></div></div>\n<p>The key patterns:</p>\n<ul>\n<li class=\"\"><strong>Immutable static assets</strong> get cached aggressively everywhere</li>\n<li class=\"\"><strong>HTML</strong> gets <code>s-maxage</code> for CDN caching with <code>stale-while-revalidate</code> for seamless updates</li>\n<li class=\"\"><strong>APIs</strong> are private and use ETags for conditional requests</li>\n<li class=\"\"><strong>User-specific content</strong> bypasses all shared caches</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"common-mistakes-ive-seen\">Common mistakes I’ve seen<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#common-mistakes-ive-seen\" class=\"hash-link\" aria-label=\"Direct link to Common mistakes I’ve seen\" title=\"Direct link to Common mistakes I’ve seen\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-caching-user-specific-data-in-shared-caches\">1. Caching user-specific data in shared caches<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#1-caching-user-specific-data-in-shared-caches\" class=\"hash-link\" aria-label=\"Direct link to 1. Caching user-specific data in shared caches\" title=\"Direct link to 1. Caching user-specific data in shared caches\" translate=\"no\">​</a></h3>\n<p>If your CDN caches a page that shows \"Hello, Pranjal\" and serves it to every user... you’ve got a privacy incident. Always use <code>Cache-Control: private</code> or <code>no-store</code> for authenticated responses. If you do cache personalized pages on a CDN, use <code>Vary: Cookie</code> (but this usually kills your cache hit rate anyway).</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-not-setting-vary-headers-correctly\">2. Not setting <code>Vary</code> headers correctly<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#2-not-setting-vary-headers-correctly\" class=\"hash-link\" aria-label=\"Direct link to 2-not-setting-vary-headers-correctly\" title=\"Direct link to 2-not-setting-vary-headers-correctly\" translate=\"no\">​</a></h3>\n<p>If your server returns different content based on <code>Accept-Encoding</code> (gzip vs brotli) or <code>Accept</code> (JSON vs HTML), you must include a <code>Vary</code> header. Otherwise the CDN might serve a gzip response to a client that sent <code>Accept-Encoding: br</code>.</p>\n<div class=\"language-http codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-http codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">Vary: Accept-Encoding, Accept</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-using-query-strings-for-cache-busting-instead-of-filename-hashing\">3. Using query strings for cache busting instead of filename hashing<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#3-using-query-strings-for-cache-busting-instead-of-filename-hashing\" class=\"hash-link\" aria-label=\"Direct link to 3. Using query strings for cache busting instead of filename hashing\" title=\"Direct link to 3. Using query strings for cache busting instead of filename hashing\" translate=\"no\">​</a></h3>\n<div class=\"language-html codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-html codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">&lt;!-- Fragile: some CDNs ignore query strings by default --&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">script</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">/app.js?v=123</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><span class=\"token script\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;/</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">script</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">&lt;!-- Robust: always treated as a unique resource --&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">script</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\"> </span><span class=\"token tag attr-name\" style=\"color:hsl(29, 54%, 61%)\">src</span><span class=\"token tag attr-value punctuation attr-equals\" style=\"color:hsl(220, 14%, 71%)\">=</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag attr-value\" style=\"color:hsl(95, 38%, 62%)\">/app.abc123.js</span><span class=\"token tag attr-value punctuation\" style=\"color:hsl(220, 14%, 71%)\">\"</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><span class=\"token script\"></span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&lt;/</span><span class=\"token tag\" style=\"color:hsl(355, 65%, 65%)\">script</span><span class=\"token tag punctuation\" style=\"color:hsl(220, 14%, 71%)\">&gt;</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-setting-max-age-too-high-without-immutable\">4. Setting max-age too high without immutable<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#4-setting-max-age-too-high-without-immutable\" class=\"hash-link\" aria-label=\"Direct link to 4. Setting max-age too high without immutable\" title=\"Direct link to 4. Setting max-age too high without immutable\" translate=\"no\">​</a></h3>\n<p>If you set <code>max-age=31536000</code> without <code>immutable</code>, browsers will still occasionally revalidate (especially on page reload). Adding <code>immutable</code> tells the browser \"don’t even bother checking, this will never change.\"</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"5-forgetting-about-thundering-herd\">5. Forgetting about thundering herd<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#5-forgetting-about-thundering-herd\" class=\"hash-link\" aria-label=\"Direct link to 5. Forgetting about thundering herd\" title=\"Direct link to 5. Forgetting about thundering herd\" translate=\"no\">​</a></h3>\n<p>When a popular cached item expires, hundreds of requests simultaneously hit origin. Solutions:</p>\n<ul>\n<li class=\"\"><strong>Stale-while-revalidate:</strong> Serve stale content while one request refreshes</li>\n<li class=\"\"><strong>Request coalescing:</strong> CDN sends only one request to origin and holds the others</li>\n<li class=\"\"><strong>Cache locking:</strong> Only one process fetches; others wait for cache population</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"real-world-examples-how-companies-combine-both\">Real-world examples: how companies combine both<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#real-world-examples-how-companies-combine-both\" class=\"hash-link\" aria-label=\"Direct link to Real-world examples: how companies combine both\" title=\"Direct link to Real-world examples: how companies combine both\" translate=\"no\">​</a></h2>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"netflix\">Netflix<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#netflix\" class=\"hash-link\" aria-label=\"Direct link to Netflix\" title=\"Direct link to Netflix\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\"><strong>CDN (Open Connect):</strong> Netflix runs its own CDN with servers inside ISP networks. Video chunks are cached directly inside your internet provider’s data center.</li>\n<li class=\"\"><strong>Application caching (EVCache):</strong> A distributed Memcached layer that caches user data, recommendations, and metadata. Handles 30+ million requests/second.</li>\n<li class=\"\">The combination: when you open Netflix, your personalized homepage is assembled from EVCache (application cache), but the actual video bytes come from the nearest Open Connect appliance (CDN).</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"shopify\">Shopify<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#shopify\" class=\"hash-link\" aria-label=\"Direct link to Shopify\" title=\"Direct link to Shopify\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\"><strong>CDN (Cloudflare + Fastly):</strong> All storefront assets (product images, theme CSS/JS) are served from CDN edges. They use surrogate keys to instantly purge a merchant’s cache when they update their store.</li>\n<li class=\"\"><strong>Application caching (identity cache + Rails cache):</strong> Product data, collection listings, and rendered Liquid templates are cached in application memory and Redis.</li>\n<li class=\"\"><strong>Cache hierarchy:</strong> Browser → CDN edge → CDN shield → Rails page cache → Object cache → Database.</li>\n</ul>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"wikipedia\">Wikipedia<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#wikipedia\" class=\"hash-link\" aria-label=\"Direct link to Wikipedia\" title=\"Direct link to Wikipedia\" translate=\"no\">​</a></h3>\n<ul>\n<li class=\"\"><strong>CDN (custom Varnish cluster):</strong> Wikipedia runs ~40 Varnish caching servers across 5 data centers. For a site with 20+ billion page views/month, caching is existential — without it, their relatively small infrastructure would collapse.</li>\n<li class=\"\"><strong>Application caching (memcached):</strong> Parsed wiki markup, user sessions, and metadata are cached in a large Memcached cluster.</li>\n<li class=\"\"><strong>Hit rate:</strong> &gt;90% of requests are served from Varnish without ever touching the application servers.</li>\n</ul>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"the-decision-framework\">The decision framework<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#the-decision-framework\" class=\"hash-link\" aria-label=\"Direct link to The decision framework\" title=\"Direct link to The decision framework\" translate=\"no\">​</a></h2>\n<p>When you’re designing a system and thinking about performance:</p>\n<ol>\n<li class=\"\">\n<p><strong>Measure first.</strong> Where is the actual latency? Network? Database? Computation? Don’t add caching for a problem that’s actually a slow query needing an index.</p>\n</li>\n<li class=\"\">\n<p><strong>If the bottleneck is network latency to users</strong> → CDN.</p>\n</li>\n<li class=\"\">\n<p><strong>If the bottleneck is repeated expensive computation</strong> → Application cache.</p>\n</li>\n<li class=\"\">\n<p><strong>If you need both speed and freshness</strong> → <code>stale-while-revalidate</code> + background refresh.</p>\n</li>\n<li class=\"\">\n<p><strong>If consistency matters more than speed</strong> → Cache conservatively with short TTLs and active invalidation.</p>\n</li>\n<li class=\"\">\n<p><strong>If you’re serving static assets</strong> → CDN with immutable caching. This is non-negotiable for any production site.</p>\n</li>\n</ol>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"wrapping-up\">Wrapping up<a href=\"https://blogs.pranjalkumar.in/blog/caching-vs-cdn#wrapping-up\" class=\"hash-link\" aria-label=\"Direct link to Wrapping up\" title=\"Direct link to Wrapping up\" translate=\"no\">​</a></h2>\n<p>Caching and CDNs are complementary, not competing. Caching is the <em>technique</em> of storing results to avoid re-computation. CDNs are the <em>infrastructure</em> that moves content geographically closer to users. Almost every production system needs both:</p>\n<ul>\n<li class=\"\">A CDN in front, handling static assets and absorbing traffic spikes</li>\n<li class=\"\">Application caching behind it, reducing database load and speeding up dynamic responses</li>\n<li class=\"\">HTTP cache headers orchestrating how long each layer holds onto content</li>\n</ul>\n<p>The art isn’t in choosing one over the other. It’s in understanding which cache layer is responsible for which content, setting appropriate TTLs for your consistency requirements, and having a clear invalidation strategy for when things change.</p>\n<p>Get the headers right, version your static assets, and use <code>stale-while-revalidate</code>. That alone puts you ahead of 90% of web applications.</p>",
            "url": "https://blogs.pranjalkumar.in/blog/caching-vs-cdn",
            "title": "Caching vs content delivery networks: What's the difference?",
            "summary": "A comparison of caching and CDNs: How they work, when to use each, eviction strategies, cache invalidation, and real-world applications in high-traffic systems.",
            "date_modified": "2024-03-23T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "caching",
                "cdn",
                "web"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/1*meHpNW0zTlYpyxNa1aqTFw.png\" alt=\"Multi-process browser architecture diagram\" class=\"img_ev3q\"></p>\n<blockquote>\n<p>The front end may be a rapidly changing field, and it is difficult for us to understand all aspects of it. However, front-end systems generally run in browsers, so a better understanding of browsers can help us develop front-end applications more effectively. This is also one of the reasons for this article and serves as an instance analysis of runtime.</p>\n</blockquote>\n<p>The browser architecture has undergone a transition from single-process browsers to multi-process browsers. Emphasizing stability, smoothness, and security, processes have been decomposed into rendering, GPU, network, and plugins, improving the cleanliness of the architecture. To review the browser's architecture, it is necessary to further understand the process of opening pages, the page rendering process, and the browser plugin mechanism. By organizing the timeline of Chrome extension versions, especially the transition from Manifest V1 to Manifest V3, one can gain a relatively comprehensive understanding of how browsers have evolved.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-evolution-of-browser-architecture\">1. Evolution of Browser Architecture<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#1-evolution-of-browser-architecture\" class=\"hash-link\" aria-label=\"Direct link to 1. Evolution of Browser Architecture\" title=\"Direct link to 1. Evolution of Browser Architecture\" translate=\"no\">​</a></h3>\n<p>Before 2007, the typical browser architecture was like this:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:700/0*TSW5YPSGBsBiBaRw\" alt=\"None | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>Single-process browser architecture runs the entire web browser in a single operating system process, consolidating tasks such as network processing, plugins, JavaScript runtime, rendering engine, page management, and user interface elements into one execution space. While simplifying resource management, this architectural design has the following main issues:</p>\n<ul>\n<li class=\"\"><strong>Instability</strong> - Plugins and rendering engines handling functions like web video and games run in the same process. Crashes in plugins or rendering engines can lead to the entire browser crashing, with this instability particularly evident when dealing with complex JavaScript code.</li>\n<li class=\"\"><strong>Lack of smoothness</strong> - All modules (including page rendering, JavaScript execution, and plugins) share a single thread. If a script becomes very time-consuming, it can monopolize the entire thread, causing other pages to be unresponsive and resulting in delays across the whole browser.</li>\n<li class=\"\"><strong>Insecurity</strong> - Plugins running on pages can access operating system resources. Malicious plugins can exploit this access to release viruses compromising security and potentially stealing sensitive information like user credentials.</li>\n</ul>\n<p>The advantage of a single-process browser is that all browser components operated within one process simplify resource management and coordination. Single-process browsers typically exhibit lower memory usage rates which benefit resource efficiency improvement. Tasks run sequentially within a unified process.</p>\n<p>The Chrome process architecture released in 2008 is an example of a multi-process browser as shown in the diagram below:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:700/0*IjE21_65L--4cLJC\" alt=\"None | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>Early browser architectures divided functionality into three main processes: browser, plugins, and rendering. Each page and its plugins run independently in dedicated rendering and plugin processes, communicating through IPC.</p>\n<p>Inter-process communication (IPC) is a mechanism that allows processes to communicate and synchronize operations on a computer. It facilitates efficient data exchange and coordination between different programs. Key IPC mechanisms include shared memory, allowing processes to synchronize access to shared public memory areas using semaphores. Named and unnamed pipes provide one-way communication; IPC in Linux typically involves sharing files or shared memory storage with semaphores. Message queues support asynchronous communication, helping separate sender and receiver processes. Additionally, processes can communicate through signals to notify specific events or requests. Sockets extend IPC across different machines using network protocols.</p>\n<p>Multi-process browsers enhance stability; isolated processes prevent crashes from affecting the entire browser. Crashes of pages or plugins only affect their specific process, ensuring the stability of other pages and the browser itself. Running JavaScript in a separate rendering process also isolates its impact; if a script blocks the rendering process, it only affects the current page while leaving the rest of the browser unaffected since each page runs scripts in its dedicated rendering process. Furthermore, Chrome places plugins and rendering processes in sandbox environments limiting read/write access to data - even if malicious software executes within these processes it cannot breach the sandbox for system permissions gain - this is an example of a compartmentalized architecture pattern.</p>\n<p>A sandbox is a testing environment that allows users to run programs or open files without impacting the entire system's operation. In cybersecurity fields, sandboxes analyze potential malicious code execution detecting threats for mitigation purposes.</p>\n<p>In recent versions of Chrome browsers have key components as shown below:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:700/0*x5ZgnUhmK1ZcUXhd\" alt=\"None | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>The browser process manages the display interface, user interaction, and subprocess coordination, and provides storage functions. It acts as a \"scheduler\" to coordinate other processes, for example calling the network process when entering a URL. The rendering process converts HTML, CSS, and JavaScript into interactive web pages and runs the V8 engine. For security reasons, Chrome creates a separate rendering process for each tab in sandbox mode.</p>\n<p>The GPU process was initially designed for 3D CSS effects but later expanded to drawing web pages and the Chrome UI interface. Introduced in Chrome's multi-process architecture to meet common browser needs. The network process independently loads page network resources; originally a module within the browser process, it now runs as a separate process. The plugin process manages plugins to prevent crashes affecting browsers and pages due to the inherent instability of plugins.</p>\n<p>The modern browser architecture is shown in the diagram below:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:700/0*r6J1bYM8y5i1-WFq\" alt=\"None | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-behind-the-browser-page-opening\">2. Behind the browser page opening<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#2-behind-the-browser-page-opening\" class=\"hash-link\" aria-label=\"Direct link to 2. Behind the browser page opening\" title=\"Direct link to 2. Behind the browser page opening\" translate=\"no\">​</a></h3>\n<ol>\n<li class=\"\">Adding a tab initiates the creation of basic processes: system browser, rendering, GPU, and network processes.</li>\n<li class=\"\">User input triggers the browser process to check, assemble protocols, and form a complete URL.</li>\n<li class=\"\">The browser process sends the URL request to the network process through inter-process communication.</li>\n<li class=\"\">The network process checks the local cache for requested resources. If found in the cache, it returns them to the browser process.</li>\n<li class=\"\">If not in the cache, the network process sends an HTTP request to the web server.</li>\n<li class=\"\">The network process parses responses and checks status codes; non-200 status codes prompt specific handling logic.</li>\n<li class=\"\">For a 200 response, the browser process checks Content-Type. A byte stream triggers a download manager while HTML signals readiness for rendering.</li>\n<li class=\"\">The browser process verifies if the current URL matches the root domain of existing rendering processes. If different, it starts a new rendering process.</li>\n<li class=\"\">The browser sends a \"submit document\" message to the rendering process establishing the data transfer pipeline with the network process.</li>\n<li class=\"\">After receiving data, the rendering process confirms back to the browser. Browser updates interface state including security indicators, address bar URL, browsing history, and webpage content.</li>\n</ol>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-rendering-process\">3. Rendering process<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#3-rendering-process\" class=\"hash-link\" aria-label=\"Direct link to 3. Rendering process\" title=\"Direct link to 3. Rendering process\" translate=\"no\">​</a></h3>\n<p>Modern browsers use strategies such as lazy loading and caching to prioritize performance. Browsers display web content through rendering processes. Key stages include HTML parsing, CSS styling, layout creation, and drawing, with specific steps as follows:</p>\n<ol>\n<li class=\"\">User input - Enter the URL in the browser's address bar.</li>\n<li class=\"\">URL parsing - Parse the URL to identify the protocol, host, port, and path.</li>\n<li class=\"\">DNS lookup - Convert the hostname into an IP address through DNS lookup.</li>\n<li class=\"\">Socket connection - Establish a connection between the user and server IP.</li>\n<li class=\"\">HTTP request - Send an HTTP request to the server specifying the protocol.</li>\n<li class=\"\">Server processing - The server evaluates requests and determines handling plugins (e.g., PHP, Java).</li>\n<li class=\"\">Processing via plugins - Access databases or other resources as part of an HTTP response.</li>\n<li class=\"\">Browser response - Send back the HTTP response to the browser.</li>\n<li class=\"\">Response analysis - Analyze HTML data from the response in browsers.</li>\n<li class=\"\">DOM tree creation - Build a Document Object Model (DOM) tree from parsed HTML.</li>\n<li class=\"\">Stylesheet parsing - Parse stylesheets linking presentation data to DOM nodes.</li>\n<li class=\"\">JavaScript execution - Execute JavaScript code to modify DOM elements.</li>\n<li class=\"\">Page rendering - Display web pages using DOM and style data.</li>\n</ol>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"31-html-parsing\">3.1 HTML Parsing<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#31-html-parsing\" class=\"hash-link\" aria-label=\"Direct link to 3.1 HTML Parsing\" title=\"Direct link to 3.1 HTML Parsing\" translate=\"no\">​</a></h4>\n<p>The browser reads HTML character by character, identifying elements, attributes, and text, then constructs the DOM tree representing the structure of the webpage to ensure the correct display of HTML code.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"32-css-object-model\">3.2 CSS Object Model<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#32-css-object-model\" class=\"hash-link\" aria-label=\"Direct link to 3.2 CSS Object Model\" title=\"Direct link to 3.2 CSS Object Model\" translate=\"no\">​</a></h4>\n<p>The CSS Object Model expresses the styles applied to HTML elements, similar to the structured hierarchy of the DOM tree, taking into account the specificity and cascading nature of styles, allowing access, manipulation, and computation of styles.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"33-layout-manager\">3.3 Layout Manager<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#33-layout-manager\" class=\"hash-link\" aria-label=\"Direct link to 3.3 Layout Manager\" title=\"Direct link to 3.3 Layout Manager\" translate=\"no\">​</a></h4>\n<p>Layout managers combine the DOM and CSS object model to form a rendering tree, determine the size of the Box based on content, padding, etc., and use various methods to build specific positions. At the same time, stacking contexts and Z-index are used to handle overlapping elements and batch processing techniques are used to optimize layout changes. Finally, elements are drawn on the screen and continuously updated during user interaction.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-plugin-mechanism\">4 Plugin Mechanism<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#4-plugin-mechanism\" class=\"hash-link\" aria-label=\"Direct link to 4 Plugin Mechanism\" title=\"Direct link to 4 Plugin Mechanism\" translate=\"no\">​</a></h3>\n<blockquote>\n<p>When using plugins, the browser's operation is simpler than regular web pages. The rendering process is responsible for running the webpage. When a page is opened, contentscript.js is loaded and injected into the webpage environment, operating similar to JavaScript by manipulating the DOM tree and altering display. The GPU process supports hardware functions for rendering plugin interfaces, while the network process manages external resource requests within plugins, such as dependencies on external JS resources. Simultaneously, the storage process provides local storage functionality for plugins using chrome.storage.local to store and retrieve data in Chrome extensions. The browser process acts as a bridge facilitating communication between Extension Page and contentscript.js.</p>\n</blockquote>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"41-development-history-of-plugins\">4.1 Development History of Plugins<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#41-development-history-of-plugins\" class=\"hash-link\" aria-label=\"Direct link to 4.1 Development History of Plugins\" title=\"Direct link to 4.1 Development History of Plugins\" translate=\"no\">​</a></h4>\n<p>The development process of the plugin mechanism is as follows:</p>\n<table><thead><tr><th>Year</th><th>Version</th><th>Description</th></tr></thead><tbody><tr><td>August 2012</td><td>Manifest V1</td><td>Chrome plugins were initially based on Manifest V1, defining basic functions and permissions.</td></tr><tr><td>April 2013</td><td>Chrome26 Stable</td><td>Including support for Manifest V1 plugins.</td></tr><tr><td>May 2014</td><td>Chrome35 Stable</td><td>Incremental updates of the browser continue to support Manifest V1 plugins.</td></tr><tr><td>September 2014</td><td>Chrome 37 Stable</td><td>Further improvements and bug fixes for Manifest V1 plugins.</td></tr><tr><td>May 2015</td><td>Chrome43 Stable</td><td>Continued support for Manifest V1.</td></tr><tr><td>December 2015</td><td>Manifest V2</td><td>Introduced Manifest V2, bringing better security and additional features.</td></tr><tr><td>June 2016</td><td>Chrome51 Stable</td><td>Manifest V2 became the standard for plugin development.</td></tr><tr><td>September 2016</td><td>Chrome53 Stable</td><td>Continuous improvement and optimization of Manifest V2.</td></tr><tr><td>January 2019</td><td>Manifest V3 Birthed</td><td>Focuses on security, performance, and development flexibility.</td></tr><tr><td>March 2020</td><td>Chrome80 Stable</td><td>While manifest v2 remains the standard for plugins. manifest v3 is available for testing but not mandatory yet.</td></tr><tr><td>March 2021</td><td>Chrome89 stable</td><td>Manifest v2 still default but attention shifting towards manifest v3.</td></tr><tr><td>October 2021</td><td>Chrome94 stable</td><td>Manifestv3 starts enforcing some features with migration guides &amp; tools provided to developers.</td></tr><tr><td>March 2022</td><td>Chrome98 stable</td><td>Manifestv3 becomes the default new plugin version while continuing to support manifestv2.</td></tr><tr><td>August 2022</td><td>Chrome104 stable</td><td>All plugins fully transitioned to manifestv3 officially announcing no more support for manifestv2.</td></tr><tr><td>March 2023</td><td>Chrome108 stable</td><td>Maintained full support for manifestv3 ensuring smooth transition for all plugins.</td></tr><tr><td>July 2023</td><td>ManifestV3 Preview</td><td>Allowing developers to explore upcoming changes and provide valuable feedback.</td></tr><tr><td>October 2023</td><td>Chrome version</td><td>Further improved support for ManifestV3 in Chrome Stable Version addressing all issues reported during the preview stage.</td></tr><tr><td>January 2024</td><td>Pre-stable release</td><td>Encouraging developers to migrate their extensions to Manifest V3 and providing comprehensive documentation and migration guidance.</td></tr><tr><td>January 2024</td><td>Manifest V3 pre-stable version released</td><td>Manifest V3 has reached a stable state, encouraging developers to migrate their extensions to V3 and providing comprehensive documentation and migration guides.</td></tr><tr><td>March 2024</td><td>Chrome116 stable</td><td>Fully supports Manifest V3, developers update their plugins to ensure compatibility with the latest standards.</td></tr></tbody></table>\n<p>Overall, Chrome extensions (also known as add-ons) have gone through the development of 3 major versions: Manifest V1, Manifest V2, and Manifest V3.</p>\n<p>Manifest V1 (MV1) was the initial version of the Chrome extension manifest and has been deprecated. Manifest V2 (MV2) is the mainstream version widely used in current Chrome extensions, providing a robust framework for building extensions with enhanced browser functionality features. Manifest V3 is the latest version gradually replacing MV2. The introduction of MV3 aims to address security and performance issues by strengthening security measures and promoting better performance in extension development. Starting from Chrome 127 (June 2024), Google will begin disabling Manifest V2 extensions in pre-stable versions of Chrome, encouraging developers to transition to MV3.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"42-features-and-version-migration-of-manifest\">4.2 Features and Version Migration of Manifest<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#42-features-and-version-migration-of-manifest\" class=\"hash-link\" aria-label=\"Direct link to 4.2 Features and Version Migration of Manifest\" title=\"Direct link to 4.2 Features and Version Migration of Manifest\" translate=\"no\">​</a></h4>\n<p>Features of Manifest V2:</p>\n<ul>\n<li class=\"\">Use <code>script-src 'self'</code>; <code>object-src 'self'</code>; Content-Security-Policy (CSP) to set the default content security policy.</li>\n<li class=\"\">Plugin package resources are no longer available externally; the whitelist is listed through the <code>web_access_resources</code> property in the manifest.</li>\n<li class=\"\">Changes have been made to browser operation APIs and page operation APIs, which <code>chrome.extension</code> replaces <code>chrome.self</code> pointing to the plugin itself, <code>chrome.tension.getTabContentses</code> is replaced by <code>tension.getView</code>, <code>Port.tab</code> is replaced by <code>runtime.Port</code>, etc.</li>\n</ul>\n<p>Features of Manifest V3:</p>\n<ul>\n<li class=\"\"><code>Manifest V3</code> introduces <code>Service worker</code>, replacing background pages.</li>\n<li class=\"\">Network request modifications use the new Declarative Net Request API instead of the deprecated webRequest API.</li>\n<li class=\"\">Remote code execution is not allowed; only JS in extension packages can run.</li>\n<li class=\"\">Promises have been added to many methods and callbacks are still supported.</li>\n<li class=\"\">Browser Action API and Page Action API are unified into a single Action API.</li>\n<li class=\"\">Web-accessible resources are limited to specified sites and extensions.</li>\n<li class=\"\">Content Security Policy (CSP) allows specifying separate CSPs for different execution contexts, where executeScript can only run script files and functions, not arbitrary strings.</li>\n</ul>\n<p>Manifest V3 represents a significant shift from V1 and V2, driven by Chrome's commitment to improving privacy, security, and overall extension performance. Unlike previous versions, Manifest V3 prioritizes resource efficiency, addressing concerns about Chrome's historically high resource usage. Its core goal is to optimize browser performance by limiting system resource consumption through extensions. While imposing additional restrictions, Manifest V3 introduces significant benefits. The ServiceWorker feature allows extensions to operate without constantly residing in the background, enabling the recycling of extension resources and effectively reducing overall browser overhead. Restrictions on rule calculations serve as a control mechanism to ensure that individual extensions do not excessively consume resources. These changes collectively contribute to a smoother browsing experience in Chrome, meeting users' expectations for improved browser efficiency.</p>\n<p>When migrating from V2 to V3, due to the absence of background.html for configuring page backgrounds, XMLHttpRequest on the Windows object is no longer applicable for constructing AJAX requests in background.html as it was in the V2 version. Instead, data must be retrieved using extraction methods.</p>\n<p>Furthermore, the short lifespan of service workers and their termination during periods of inactivity leading to occasional startups, runs, and terminations throughout the plugin lifecycle introduce instability. In MV2 global variables were used directly for storing data; therefore modifications are required in backound.js logic to enhance stability and functionality under these circumstances. Additionally transitioning from webRequest API to statativeNetRequest API necessitates substantial code refactoring.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"43-main-components-of-chrome-extensions\">4.3 Main Components of Chrome Extensions<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#43-main-components-of-chrome-extensions\" class=\"hash-link\" aria-label=\"Direct link to 4.3 Main Components of Chrome Extensions\" title=\"Direct link to 4.3 Main Components of Chrome Extensions\" translate=\"no\">​</a></h4>\n<p><strong>4.3.1 manifest file</strong></p>\n<p>The manifest.json file is very important for Chrome extensions located in the root directory. It is used to configure all plugin settings, with basic parameters such as Manif_version, name, and version.</p>\n<p>An example of Manifest V2 is as follows:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">button </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-copy p-1 bg-gray-300 dark:bg-black\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Copy</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">button</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">merlin</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">component id</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"merlin-code-summarizer\"</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"merlin-code-summarizer\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">merlin</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">component</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">code </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"overflow-x-auto mt-1 language-json bg-gray-100 dark:bg-gray-900 hljs\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"manifest_version\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-number\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">2</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin name&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"name\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin version&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"version\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"1.0.0\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin description&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"description\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"icons\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"16\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon16.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"48\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon48.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"128\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon128.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Persistent background JS or background page&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"background\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"scripts\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"js/background.js\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Browser icon settings ：browser_action, page_action, app&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"browser_action\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_icon\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_title\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_popup\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"popup.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Icon displayed only when specific pages are open&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"page_action\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_icon\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_title\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_popup\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"popup.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// JS directly injected into pages&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"content_scripts\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"matches\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"&amp;lt;all_urls&amp;gt;\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"js\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"js/content-script.js\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"css\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"css/custom.css\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Code injection timing, default is document_idle&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"run_at\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"document_start\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Permissions requested&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"permissions\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"contextMenus\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Right-click menu&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"tabs\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Tabs&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"notifications\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Notifications&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"webRequest\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Web requests&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"webRequestBlocking\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"storage\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin local storage&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"https://*/*\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Websites accessible via executeScript or insertCSS&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// List of plugin resources directly accessible by normal pages  \"web_accessible_resources\": [\"js/inject.js\"],&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"homepage_url\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin homepage&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"chrome_url_overrides\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Override browser default pages&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"newtab\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"newtab.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"options_ui\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Plugin options page&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"page\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"options.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"chrome_style\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-literal\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-keyword\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token boolean\" style=\"color:hsl(29, 54%, 61%)\">true</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"omnibox\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"keyword\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Register a keyword in the address bar for search suggestions, only one keyword can be set&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_locale\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"en\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Default language&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"devtools_page\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"devtools.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Devtools page entry, can only point to an HTML file    \"content_security_policy\": \"...\", // Security policy&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"web_accessible_resources\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-comment\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token comment\" style=\"color:hsl(220, 10%, 40%)\">// Loadable resources&lt;/span&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"RESOURCE_PATHS\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><br></div></code></pre></div></div>\n<p>An example of Manifest V3 is as follows:</p>\n<div class=\"language-javascript codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-javascript codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">button </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-copy p-1 bg-gray-300 dark:bg-black\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token maybe-class-name\" style=\"color:hsl(29, 54%, 61%)\">Copy</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">button</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">merlin</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">component id</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"merlin-code-summarizer\"</span><span class=\"token plain\"> </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"merlin-code-summarizer\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">merlin</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">-</span><span class=\"token plain\">component</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">code </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"overflow-x-auto mt-1 language-json bg-gray-100 dark:bg-gray-900 hljs\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"manifest_version\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-number\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">3</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"name\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"version\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"1.0.0\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"description\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"icons\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"16\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon16.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"48\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon48.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"128\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon128.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"background\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"service_worker\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"js/background.js\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"action\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_icon\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"img/icon.png\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_title\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_popup\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"popup.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"content_security_policy\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"extension_pages\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"sandbox\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"web_accessible_resources\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">      </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"resources\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"RESOURCE_PATHS\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"permissions\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"contextMenus\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"tabs\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"notifications\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"webRequest\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"webRequestBlocking\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"storage\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"https://*/*\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"web_accessible_resources\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"js/inject.js\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"homepage_url\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"chrome_url_overrides\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"newtab\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"newtab.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"options_ui\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"page\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"options.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"chrome_style\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-literal\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-keyword\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token boolean\" style=\"color:hsl(29, 54%, 61%)\">true</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"omnibox\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">{</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">    </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"keyword\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"default_locale\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"zh_CN\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"devtools_page\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"devtools.html\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"content_security_policy\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"...\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">,</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">  </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-attr\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"web_accessible_resources\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">:</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"> </span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">[</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-string\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"RESOURCE_PATHS\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">]</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token plain\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token plain\">span </span><span class=\"token keyword\" style=\"color:hsl(286, 60%, 67%)\">class</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">=</span><span class=\"token string\" style=\"color:hsl(95, 38%, 62%)\">\"hljs-punctuation\"</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token punctuation\" style=\"color:hsl(220, 14%, 71%)\">}</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">span</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&lt;</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">/</span><span class=\"token plain\">code</span><span class=\"token operator\" style=\"color:hsl(207, 82%, 66%)\">&gt;</span><br></div></code></pre></div></div>\n<p><strong>4.3.2 Content Script</strong></p>\n<p>Content scripts in Chrome extensions inject JS and CSS into specified pages through configuration. They share the DOM with the original page but not JavaScript. Accessing page JS variables requires injecting JS. Content scripts cannot access most Chrome APIs, except for:</p>\n<ul>\n<li class=\"\">chrome. extension</li>\n<li class=\"\">chrome.i18n</li>\n<li class=\"\">chrome. runtime</li>\n<li class=\"\">chrome.storage</li>\n</ul>\n<p>For other APIs, communication needs to be done with the background or service worker.</p>\n<p><strong>4.3.3 Background Script</strong></p>\n<p>The background scripts in Chrome extensions have the longest lifespan and run continuously when the browser is open. They have extensive permissions, allowing access to most Chrome extension APIs and cross-origin requests without CORS restrictions. In Manifest V3, background pages are replaced by service workers with shorter lifespans and event-based execution, making them unsuitable for storing global variables.</p>\n<p><strong>4.3.4 Pop-up window</strong></p>\n<p>A pop-up window is a small window on a webpage that appears when clicking on an icon in the top right corner. It quickly closes when the user interacts outside of the webpage. Typically used for temporary interactions, its permission level is similar to the background but with a shorter lifespan.</p>\n<p><strong>4.3.5 Inject Script</strong></p>\n<p>Developers coined the term \"injection script\" during Chrome extension development. It refers to JavaScript injected into a page through DOM manipulation. Although content scripts can manipulate the DOM, they cannot be directly accessed due to access restrictions. This limitation is particularly evident in event binding. To meet the common requirement of adding a button to trigger the plugin on a web page, developers have adopted script insertion.</p>\n<h4 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"44-communication-mechanism-of-chrome-extensions\">4.4 Communication Mechanism of Chrome Extensions<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#44-communication-mechanism-of-chrome-extensions\" class=\"hash-link\" aria-label=\"Direct link to 4.4 Communication Mechanism of Chrome Extensions\" title=\"Direct link to 4.4 Communication Mechanism of Chrome Extensions\" translate=\"no\">​</a></h4>\n<p>In Chrome extensions, communication relies on five types of scripts:</p>\n<ol>\n<li class=\"\">Injection script, representing a script dynamically injected into the webpage, usually relying on <code>window.postMessage</code>.</li>\n<li class=\"\">Content script, a script executed in a specific webpage context, utilizing <code>window.postMessage</code>, <code>chrome.runtime.sendMessage</code> and <code>chrome.runtime.connect</code> for inter-script communication.</li>\n<li class=\"\">Popup script, associated with the plugin's pop-up interface, typically using <code>chrome.tabs.sendMessage</code> and <code>chrome.tabs.connect</code> for communication.</li>\n<li class=\"\">Background script, a standalone script running in the background involving various methods such as \"<code>chrome.tabs.sendMessage</code>\", <code>chrome.tabs.connect</code>, <code>chrome.extension.getBackgroundPage</code> and <code>chrome.extension.getViews</code>.</li>\n<li class=\"\">DevTools, additional functionalities of development tools that interact using specific APIs like <code>chrome.devtools.inspectedWindow.eval</code> and <code>chrome.runtime.sendMessage</code>.</li>\n</ol>\n<p>Each script has different permissions emphasizing the importance of their communication. This interaction is crucial for enabling extensive plugin functionality.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"written-at-end\">Written at end<a href=\"https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture#written-at-end\" class=\"hash-link\" aria-label=\"Direct link to Written at end\" title=\"Direct link to Written at end\" translate=\"no\">​</a></h3>\n<p>Reviewing the past to learn new things, browser architecture, as the cornerstone of the modern Internet, has gone through multiple iterations and innovations, always serving as a bridge between users and web content. Looking back at its development history, from the early days of single rendering engines to today's multi-process, multi-threaded architecture, each change has brought about a smoother and more secure browsing experience. Looking ahead, browser architecture will continue to deepen its performance optimization and security enhancement to bring users an even better web browsing experience.</p>",
            "url": "https://blogs.pranjalkumar.in/blog/past-and-present-browser-architecture",
            "title": "The past and present of browser architecture",
            "summary": "How browser architecture evolved from single-process to multi-process - covering Chrome's rendering, GPU, network, and plugin process decomposition, IPC, sandboxing, and the Manifest V1 to V3 transition.",
            "date_modified": "2024-03-20T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "browser",
                "programming",
                "javascript"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/docker-image-guide",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o2jy675uu0n48fpq4fx1.png\" alt=\"Dockfolio Docker image build workflow\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"introduction\">Introduction<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#introduction\" class=\"hash-link\" aria-label=\"Direct link to Introduction\" title=\"Direct link to Introduction\" translate=\"no\">​</a></h2>\n<p>Prepare for an exhilarating journey into the world of \"dockfolio,\" a comprehensive Docker image created to simplify <code>Portfolio creation for developers</code>. This article is your personalized roadmap, guiding you through every step, command, and thrill involved in curating and distributing a Docker image.</p>\n<p><strong>The Birth of Dockfolio:</strong> The genesis of \"dockfolio\" emerged from a passionate pursuit to streamline the intricate process of web development deployment of a Developer Portfolio. It's a brainchild designed to be your all-in-one, hassle-free toolkit, blending a medley of essential tools to supercharge your development environment.</p>\n<p><strong>Crafting the Container:</strong></p>\n<ul>\n<li class=\"\"><strong>Creating the Dockerfile:</strong> To give life to \"dockfolio,\" start by crafting your Dockerfile. Open the door to your imagination with commands like:<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">mkdir</span><span class=\"token plain\"> dockfolio</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token builtin class-name\" style=\"color:hsl(29, 54%, 61%)\">cd</span><span class=\"token plain\"> dockfolio</span><br></div></code></pre></div></div>\n</li>\n<li class=\"\">Add desired files into your this repo, add your web-dev files into it. <em>(HTML, CSS, Js, etc.)</em></li>\n<li class=\"\">Compress and archive it into a tar ball using: <code>tar</code> &amp; <code>gzip</code>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">tar</span><span class=\"token plain\"> czvf dockfolio.tar.gz dockfolio/*</span><br></div></code></pre></div></div>\n</li>\n<li class=\"\">Create dockerfile with dependencies and configuration.<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">touch</span><span class=\"token plain\"> Dockerfile</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">vim</span><span class=\"token plain\"> Dockerfile</span><br></div></code></pre></div></div>\n<img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1702374832676/8dd6fb2a-3d6e-458c-84f3-ebaa72f71cbe.png\" alt=\"Making changes into Dockerfile  | Dockfolio | @pranjal-kumar\" class=\"img_ev3q\"></li>\n<li class=\"\">Weave a tapestry of configurations-Apache service-to build the perfect environment.</li>\n<li class=\"\"><strong>Building the Image:</strong> With a flick of a command:<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> build </span><span class=\"token parameter variable\" style=\"color:hsl(207, 82%, 66%)\">-t</span><span class=\"token plain\"> pranjalbarnwal/dockfolio </span><span class=\"token builtin class-name\" style=\"color:hsl(29, 54%, 61%)\">.</span><br></div></code></pre></div></div>\n<img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1702374391910/56d50482-01da-4bb3-a513-78e6b3bcd4d7.png\" alt=\"Build process for our docker image  | Dockfolio | @pranjal-kumar\" class=\"img_ev3q\"></li>\n<li class=\"\">Watch as your masterpiece comes to life, each line of code infused with purpose and precision.</li>\n</ul>\n<p><strong>Navigating Challenges, Embracing Victories:</strong></p>\n<ul>\n<li class=\"\"><strong>Overcoming Configuration Hurdles:</strong> A journey fraught with challenges! But fear not, for every configuration tweak brings a step closer to harmony among components.</li>\n<li class=\"\"><strong>Fine-Tuning Performance:</strong> The quest for excellence doesn’t stop. Optimize your image for lightning-fast efficiency, ensuring it performs like a well-oiled machine.</li>\n</ul>\n<p><strong>Publishing on Docker Hub:</strong></p>\n<ul>\n<li class=\"\"><strong>Docker Hub Login:</strong> Enter the gateway to the Docker universe:<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> login</span><br></div></code></pre></div></div>\n<!-- -->Claim your spot among fellow creators.</li>\n<li class=\"\"><strong>Tagging and Pushing:</strong> Give your creation wings by tagging it:<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> tag dockfolio pranjalbarnwal/dockfolio:latest</span><br></div></code></pre></div></div>\n<!-- -->Set it free into the world:<!-- -->\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> push pranjalbarnwal/dockfolio:latest</span><br></div></code></pre></div></div>\n</li>\n</ul>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1702374187200/34d55858-5e74-4cdb-8f55-ec6e3544aa96.png\" alt=\"Push digest and process shown here | Dockfolio | @pranjal-kumar\" class=\"img_ev3q\"></p>\n<p>With this, our image is live and public at Docker Hub.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1702367467166/4fdf8bcc-c657-4902-982e-d2e04f243720.png\" alt=\"Image on Docker Hub | Dockfolio | @pranjal-kumar\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"running-image-from-docker-hub\">Running image from Docker Hub<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#running-image-from-docker-hub\" class=\"hash-link\" aria-label=\"Direct link to Running image from Docker Hub\" title=\"Direct link to Running image from Docker Hub\" translate=\"no\">​</a></h2>\n<p>Now anyone will be able to fetch the image and run the same image using below commands</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> pull pranjalbarnwal/dockfolio</span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\" style=\"display:inline-block\"></span><br></div><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\"></span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">docker</span><span class=\"token plain\"> run </span><span class=\"token parameter variable\" style=\"color:hsl(207, 82%, 66%)\">-d</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(207, 82%, 66%)\">-p</span><span class=\"token plain\"> </span><span class=\"token number\" style=\"color:hsl(29, 54%, 61%)\">8080</span><span class=\"token plain\">:80 pranjalbarnwal/dockfolio</span><br></div></code></pre></div></div>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"see-it-in-action\">See it in action<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#see-it-in-action\" class=\"hash-link\" aria-label=\"Direct link to See it in action\" title=\"Direct link to See it in action\" translate=\"no\">​</a></h3>\n<!-- -->\n<div>Loading terminal recording...</div>\n<!-- -->\n<blockquote>\n<p>Once done, website will be live at: <a href=\"http://localhost:8080/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">localhost:8080</a></p>\n<p><strong>NOTE</strong>: if you're running Docker on server, then replace <a href=\"http://localhost/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">localhost</a> above with your ip address ex: <a href=\"http://54.80.107.150:8080/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\"><code>http://54.80.107.150:8080</code></a></p>\n</blockquote>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1702367398185/496e4ee7-b075-4a80-8a65-53ce6fef8898.png\" alt=\"Deployment of Dockfolio\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"engagement-and-improvement\">Engagement and Improvement<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#engagement-and-improvement\" class=\"hash-link\" aria-label=\"Direct link to Engagement and Improvement\" title=\"Direct link to Engagement and Improvement\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>Joining the Docker Community:</strong> Dive into vibrant discussions, seek counsel, and share insights to grow together within the nurturing Docker community.</li>\n<li class=\"\"><strong>Iterative Enhancements:</strong> Feedback is a gift! Continuously enhance <code>dockfolio</code> based on community suggestions, evolving it into a tool that resonates with developers worldwide.\nFeel free to bring improvements and dive into the sea of <strong>Open-source</strong>: <a href=\"https://github.com/pranjal-barnwal/dockfolio\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\"><strong>Repo</strong></a></li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"charting-the-future\">Charting the Future<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#charting-the-future\" class=\"hash-link\" aria-label=\"Direct link to Charting the Future\" title=\"Direct link to Charting the Future\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>Evolving \"Dockfolio\":</strong> The journey doesn’t end here! As we move forward, envision endless possibilities-innovative integrations, enhanced functionalities-enriching the landscape of development efficiency.</li>\n</ul>\n<p><strong>Conclusion:</strong> \"Dockfolio\" encapsulates a voyage-beyond just an image-of persistence, learning, and community camaraderie. Dive into its world, contribute, and immerse yourself in the transformative domain of containerization and efficient development workflows.</p>\n<p><strong>Final Thoughts:</strong> As this chapter concludes, heartfelt gratitude is extended to the vibrant Docker community for their unwavering support and collective wisdom. Remember, every Docker command, every interaction, fosters collaboration and fuels innovation.</p>\n<hr>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"references\">References<a href=\"https://blogs.pranjalkumar.in/blog/docker-image-guide#references\" class=\"hash-link\" aria-label=\"Direct link to References\" title=\"Direct link to References\" translate=\"no\">​</a></h2>\n<ul>\n<li class=\"\"><strong>Docker Image:</strong> <a href=\"https://hub.docker.com/repository/docker/pranjalbarnwal/dockfolio\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">pranjalbarnwal/dockfolio</a></li>\n<li class=\"\"><strong>Repo:</strong> <a href=\"https://github.com/pranjal-barnwal/dockfolio\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">github.com/pranjal-barnwal/dockfolio</a></li>\n<li class=\"\"><strong>Docker docs:</strong> <a href=\"https://docs.docker.com/build/building/base-images\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"\">docs.docker.com</a></li>\n</ul>",
            "url": "https://blogs.pranjalkumar.in/blog/docker-image-guide",
            "title": "Dockfolio: guide to creating and sharing a Docker image",
            "summary": "A step-by-step walkthrough of building a custom Docker image for developer portfolios - from writing the Dockerfile to publishing on Docker Hub.",
            "date_modified": "2023-12-23T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "docker",
                "docker-image"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/understanding-line-breaks",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1q91urxsd6tfphio44tc.jpg\" alt=\"Line break types comparison\" class=\"img_ev3q\"></p>\n<p>Line breaks play an essential role in text formatting, yet they are often overlooked in the programming world. Operating systems and text editors have their conventions for line breaks, leading to variations in line break types. This article will explore the differences between three common line break types: CR LF, LF, and CR.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cr-lf-carriage-return-line-feed\">CR LF (Carriage Return Line Feed)<a href=\"https://blogs.pranjalkumar.in/blog/understanding-line-breaks#cr-lf-carriage-return-line-feed\" class=\"hash-link\" aria-label=\"Direct link to CR LF (Carriage Return Line Feed)\" title=\"Direct link to CR LF (Carriage Return Line Feed)\" translate=\"no\">​</a></h2>\n<p>The CR LF line break type is commonly used in Windows operating systems and DOS-based text files. It combines two characters: Carriage Return (CR) and Line Feed (LF). Let’s delve into the significance of each of these characters:</p>\n<ul>\n<li class=\"\">\n<p><strong>Carriage Return (CR):</strong> Represented as \\r, this character moves the cursor to the beginning of the current line without advancing to the next line. It's like pushing the typewriter carriage back to the left.</p>\n</li>\n<li class=\"\">\n<p><strong>Line Feed (LF):</strong> Represented as \\n, this character moves the cursor down to the next line without affecting the horizontal position. It's like moving the typewriter carriage down to the next line.</p>\n</li>\n</ul>\n<p>In Windows and DOS text files, the combination of CR and LF characters indicates a line break. The CR LF sequence \\r\\n is commonly used to represent line breaks in these systems.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:482/1*_3VfbLPRpQpaTKgNtwdPMA.png\" alt=\"Line Breaks types\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"lf-line-feed\">LF (Line Feed)<a href=\"https://blogs.pranjalkumar.in/blog/understanding-line-breaks#lf-line-feed\" class=\"hash-link\" aria-label=\"Direct link to LF (Line Feed)\" title=\"Direct link to LF (Line Feed)\" translate=\"no\">​</a></h2>\n<p>The LF line break type is predominantly used in Unix, Linux, macOS, and modern text editors, including those for web development. In this convention, a single Line Feed character (\\n) represents a line break. Unlike CR LF, there is no preceding Carriage Return character. The LF line break type solely relies on the line feed character to move to the next line.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:191/1*yOUPzH_4vVs6oxnAF9PfWA.png\" alt=\"End of Line\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"cr-carriage-return\">CR (Carriage Return)<a href=\"https://blogs.pranjalkumar.in/blog/understanding-line-breaks#cr-carriage-return\" class=\"hash-link\" aria-label=\"Direct link to CR (Carriage Return)\" title=\"Direct link to CR (Carriage Return)\" translate=\"no\">​</a></h2>\n<p>The CR line break type is rarely used in modern systems but holds historical significance in older Macintosh operating systems. In this convention, a single Carriage Return character (\\r) represents a line break. Similar to LF, there is no subsequent Line Feed character in the CR line break type.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:608/1*J_MSqJ_zRPOIjAXqBWDH-Q.gif\" alt=\"Have a break? But what are breaks?\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"compatibility-and-cross-platform-considerations\">Compatibility and Cross-Platform Considerations<a href=\"https://blogs.pranjalkumar.in/blog/understanding-line-breaks#compatibility-and-cross-platform-considerations\" class=\"hash-link\" aria-label=\"Direct link to Compatibility and Cross-Platform Considerations\" title=\"Direct link to Compatibility and Cross-Platform Considerations\" translate=\"no\">​</a></h2>\n<p>Understanding the different line break types is crucial when working with text files intended for sharing across multiple platforms. It is essential to consider compatibility issues and ensure the intended systems correctly interpret the line break types.</p>\n<ul>\n<li class=\"\">\n<p>Windows applications and text editors generally handle CR LF line breaks correctly.</p>\n</li>\n<li class=\"\">\n<p>Unix, Linux, and macOS systems expect LF line breaks, and modern text editors seamlessly handle them.</p>\n</li>\n<li class=\"\">\n<p>Cross-platform projects or collaborations between different systems may require graceful handling of different line break types to avoid formatting issues.</p>\n</li>\n</ul>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"conclusion\">Conclusion<a href=\"https://blogs.pranjalkumar.in/blog/understanding-line-breaks#conclusion\" class=\"hash-link\" aria-label=\"Direct link to Conclusion\" title=\"Direct link to Conclusion\" translate=\"no\">​</a></h2>\n<p>While line breaks may appear insignificant, understanding the differences between CR LF, LF, and CR line break types is crucial for achieving seamless cross-platform compatibility. Whether you’re working on Windows, Unix, Linux, macOS, or modern text editors, being aware of line break conventions ensures consistent and accurate rendering of text files.</p>\n<p>By adopting best practices and selecting the appropriate line break type for your target platform, you can ensure optimal readability and portability of your text files.</p>\n<p>Now equipped with the knowledge of line break types, you can confidently handle text formatting and avoid any surprises in your coding and development endeavors.</p>\n<blockquote>\n<p>Happy coding!</p>\n</blockquote>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:788/1*HfiLf5jlA2QuMX6N7mpKqw.gif\" alt=\"\" class=\"img_ev3q\"></p>",
            "url": "https://blogs.pranjalkumar.in/blog/understanding-line-breaks",
            "title": "Understanding line break types: CR LF, LF, and CR",
            "summary": "Why line breaks differ across operating systems, how CR LF, LF, and CR work at the byte level, and what it means for cross-platform development and version control.",
            "date_modified": "2023-07-16T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "programming"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/88u4offseko5xx3gmwi9.jpg\" alt=\"Flutter widget lifecycle diagram\" class=\"img_ev3q\"></p>\n<p>In Flutter, widgets have a lifecycle that determines how they are created, updated, and disposed of. Understanding the widget lifecycle is essential for managing state, performing side effects, and optimizing your Flutter application. Let’s dive into an overview of the widget lifecycle in Flutter:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://dev-to-uploads.s3.amazonaws.com/uploads/articles/al3bq7afxyvkblzyeby3.png\" alt=\"Widget Lifecycle\" class=\"img_ev3q\"></p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"construction\">Construction<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#construction\" class=\"hash-link\" aria-label=\"Direct link to Construction\" title=\"Direct link to Construction\" translate=\"no\">​</a></h2>\n<p>When you instantiate a widget by calling its constructor, the widget is created. During construction, you typically provide any required parameters and initialize the widget’s state. The constructor is called once for each instance of the widget.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"initialization\">Initialization<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#initialization\" class=\"hash-link\" aria-label=\"Direct link to Initialization\" title=\"Direct link to Initialization\" translate=\"no\">​</a></h2>\n<p>After construction, the framework calls the initState() method of the widget's corresponding State object. This is where you can perform any initialization tasks that require the widget to have access to its BuildContext. You can initialize variables, subscribe to streams, set up listeners, and perform other setup tasks.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"build\">Build<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#build\" class=\"hash-link\" aria-label=\"Direct link to Build\" title=\"Direct link to Build\" translate=\"no\">​</a></h2>\n<p>The build() method is called whenever the widget needs to be rendered or updated. This method returns a widget tree, describing how the UI should look based on the current state of the widget. The framework invokes build() initially and subsequently whenever the widget's state changes or when its parent requests a rebuild.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"state-updates\">State Updates<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#state-updates\" class=\"hash-link\" aria-label=\"Direct link to State Updates\" title=\"Direct link to State Updates\" translate=\"no\">​</a></h2>\n<p>When the widget’s state changes, either through user interaction, data changes, or other events, the framework calls the setState() method of the widget's State object. This triggers a rebuild of the widget, causing the framework to call build() again. By calling setState(), you signal that the widget's state has changed and should be reflected in the UI.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"rebuilding\">Rebuilding<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#rebuilding\" class=\"hash-link\" aria-label=\"Direct link to Rebuilding\" title=\"Direct link to Rebuilding\" translate=\"no\">​</a></h2>\n<p>When the framework determines that a widget needs to be rebuilt, it calls the build() method to obtain a new widget tree. The new tree is compared to the previous tree, and the framework applies the necessary updates to the UI to reflect the changes. The rebuild process is efficient because Flutter uses a diffing algorithm to determine the minimal changes required to update the UI.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"deactivation\">Deactivation<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#deactivation\" class=\"hash-link\" aria-label=\"Direct link to Deactivation\" title=\"Direct link to Deactivation\" translate=\"no\">​</a></h2>\n<p>If a widget is removed from the widget tree but might be added back later, the framework calls the deactivate() method of the widget's State object. This method allows the widget to clean up any resources it no longer needs while preserving its state. For example, you can pause animations, cancel subscriptions, or release resources.</p>\n<h2 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"disposal\">Disposal<a href=\"https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter#disposal\" class=\"hash-link\" aria-label=\"Direct link to Disposal\" title=\"Direct link to Disposal\" translate=\"no\">​</a></h2>\n<p>When a widget is removed from the widget tree permanently, the framework calls the dispose() method of the widget's State object. This is the final opportunity for the widget to release resources, cancel subscriptions, or perform any cleanup tasks. After dispose() is called, the widget and its state are no longer usable.</p>\n<p>It’s important to note that widgets in Flutter are immutable. When a widget’s state changes, Flutter rebuilds the widget tree, creating a new set of widgets with the updated state. This approach allows for efficient UI updates and helps maintain a declarative programming style.</p>\n<p>Understanding the widget lifecycle enables you to manage state appropriately, handle asynchronous operations, and optimize your Flutter app’s performance by minimizing unnecessary rebuilds and resource usage.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:788/1*gZraN2IEy8I1VqxbZF_zyA.png\" alt=\"Flutter Widget Lifecycle\" class=\"img_ev3q\"></p>\n<h1>Seven Cycles of StatefulWidget</h1>\n<p>The lifecycle of a stateful widget in Flutter consists of seven cycles. Understanding these cycles is essential for managing the state and controlling the behavior of the widget. Let’s explore each cycle:</p>\n<ul>\n<li class=\"\">\n<p><strong>createState():</strong> This method is required and creates a State object for the widget. It holds all the mutable state for that widget. The State object is associated with the BuildContext by setting the mounted property to true.</p>\n</li>\n<li class=\"\">\n<p><strong>initState():</strong> This method is automatically called after the widget is inserted into the tree. It is executed only once when the state object is created for the first time. Use this method for initializing variables and subscribing to data sources.</p>\n</li>\n<li class=\"\">\n<p><strong>didChangeDependencies():</strong> The framework calls this method immediately after initState(). It is also called when an object that the widget depends on changes. Use this method to handle changes in dependencies, but it is rarely needed as the build method is always called after this.</p>\n</li>\n<li class=\"\">\n<p><strong>build():</strong> This method is required and is called many times during the lifecycle. It is called after didChangeDependencies() and whenever the widget needs to be rebuilt. Update the UI of the widget in this method.</p>\n</li>\n<li class=\"\">\n<p><strong>didUpdateWidget():</strong> This method is called when the parent widget changes its configuration and requires the widget to rebuild. It receives the old widget as an argument, allowing you to compare it with the new widget. Use this method to handle changes in the widget's configuration.</p>\n</li>\n<li class=\"\">\n<p><strong>setState():</strong> The setState() method notifies the framework that the internal state of the widget has changed and needs to be updated. Whenever you modify the state, use this method to trigger a rebuild of the widget's UI.</p>\n</li>\n<li class=\"\">\n<p><strong>deactivate():</strong> This method is called when the widget is removed from the widget tree but can be reinserted before the current frame changes are finished. Use this method for any cleanup or pausing ongoing operations.</p>\n</li>\n<li class=\"\">\n<p><strong>dispose():</strong> This method is called when the State object is permanently removed from the widget tree. Use this method for cleaning up resources, such as data listeners or closing connections.</p>\n</li>\n</ul>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://miro.medium.com/v2/resize:fit:539/1*2JKqkXKuRptjg3zm6X0r4Q.png\" alt=\"Order of execution\" class=\"img_ev3q\"></p>\n<p>After the <strong><code>dispose()</code></strong> method, the State object is no longer in the tree, and the mounted property is set to false. The state object cannot be remounted.</p>\n<p>Understanding these lifecycle cycles helps in managing state changes, handling dependencies, and updating the UI effectively in stateful widgets.</p>\n<p>Note: The constructor function is not part of the lifecycle as the state of the widget property is empty during that time.</p>\n<p>Now that you have a comprehensive understanding of the widget lifecycle in Flutter, you can harness its power to create robust and efficient Flutter applications.</p>",
            "url": "https://blogs.pranjalkumar.in/blog/widget-lifecycle-flutter",
            "title": "The journey of a widget: understanding the lifecycle in Flutter",
            "summary": "How Flutter widgets are created, updated, and disposed - a walkthrough of the stateful widget lifecycle, state management hooks, and performance implications.",
            "date_modified": "2023-05-29T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "flutter",
                "android"
            ]
        },
        {
            "id": "https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore",
            "content_html": "<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671905247518/9c2bcdf1-2f6c-40fc-acc5-82640c2a599b.jpeg\" alt=\"React and Firebase deployment workflow\" class=\"img_ev3q\"></p>\n<p>Unlock the power of Firebase and Firestore integration to seamlessly deploy your React projects. Streamline your development workflow and harness the scalability of Firebase for efficient deployment.</p>\n<p>Before starting with anything make sure you have created your project in FireBase &amp; you have used the same Firebase Config in your `firebase.js` file in your local react project folder</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"1-create-a-build-folder-using\">1. Create a build folder using:<a href=\"https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore#1-create-a-build-folder-using\" class=\"hash-link\" aria-label=\"Direct link to 1. Create a build folder using:\" title=\"Direct link to 1. Create a build folder using:\" translate=\"no\">​</a></h3>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">npm</span><span class=\"token plain\"> run build</span><br></div></code></pre></div></div>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671902084976/77c99ea9-f4dd-4c8e-acbd-d9c6bcd79b9d.png\" alt=\"Building the slug | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>This in turn will create a build folder in the root of your project folder.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671902782212/f3c67aee-7837-48c2-99b9-ef8b70ca294c.png\" alt=\"Folder hierarchy | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>Basically the build files are optimized for production, where there are no ongoing changes in code every now &amp; then.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"2-install-the-firebase-cli-tools-using\">2. Install the Firebase CLI Tools using:<a href=\"https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore#2-install-the-firebase-cli-tools-using\" class=\"hash-link\" aria-label=\"Direct link to 2. Install the Firebase CLI Tools using:\" title=\"Direct link to 2. Install the Firebase CLI Tools using:\" translate=\"no\">​</a></h3>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">npm</span><span class=\"token plain\"> </span><span class=\"token function\" style=\"color:hsl(207, 82%, 66%)\">install</span><span class=\"token plain\"> </span><span class=\"token parameter variable\" style=\"color:hsl(207, 82%, 66%)\">-g</span><span class=\"token plain\"> firebase-tools</span><br></div></code></pre></div></div>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671902182782/63e161e6-ad4f-4fa3-826d-efa8ebfc7ed7.png\" alt=\"Installing the firebase tools | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>`-g` flag is used here to install it globally, so it can be accessed easily from any project.</p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"3-sign-in--initialize\">3. Sign in &amp; initialize<a href=\"https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore#3-sign-in--initialize\" class=\"hash-link\" aria-label=\"Direct link to 3. Sign in &amp; initialize\" title=\"Direct link to 3. Sign in &amp; initialize\" translate=\"no\">​</a></h3>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">firebase login</span><br></div></code></pre></div></div>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671902368435/dc6c5d46-028b-4ce7-bc59-036343589ed5.png\" alt=\"Logged into firebase | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>For logging in, you will be redirected to browser window, there you simply have to login using your FireBase credentials.</p>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">firebase init</span><br></div></code></pre></div></div>\n<!-- -->\n<div>Loading terminal recording...</div>\n<!-- -->\n<p>You will be asked loads &amp; loads of questions while in `firebase init` but don't worry, I will guide you here:</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671902954507/03d58c8d-edb4-466c-8a01-8f5e9c60a031.png\" alt=\"Firebase setup initiated | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<ol>\n<li class=\"\">\n<p>Are you ready to proceed?</p>\n<p>Type `y`, since we want to continue.</p>\n</li>\n<li class=\"\">\n<p>Which Firebase features do you want to set up for this directory? Press Space to select features, then Enter to confirm your choices.</p>\n</li>\n<li class=\"\">\n<p>Here, you need to select all features which you included in your project, it may be, you needed nothing &amp; you are just using it for free Hosting. :) In my case, I used Firestore &amp; Storage both in my project &amp; also needed Hosting so, I'm selecting these 3 using space &amp; then press enter.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671905433004/1563a5cf-7170-4492-ba47-1f11e0cc1b98.png\" alt=\"Select the desired option | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>Make sure to choose the Firebase Hosting, where Github actions are optional.(Refer green stars on above picture).</p>\n<p>When prompted for Firebase rules and other similar stuff, then go with default options.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671904330866/041b8619-bb08-498e-b2d8-2a1f8298ad29.png\" alt=\"Continue selecting the options | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>For choosing public directory, make sure you choose the <code>build</code> folder</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671904645045/722ca2fe-8586-4fd8-ae5c-708de194bca7.png\" alt=\"Crosscheck the selection | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>Go with these options. Make sure you don't overwrite <code>buid/index.html</code>.</p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671904709223/bfc85f34-558f-4ee3-aefe-815e0d4ac003.png\" alt=\"Select storage rules | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<h3 class=\"anchor anchorTargetStickyNavbar_Vzrq\" id=\"4-deploying-our-web-app\">4. Deploying our web app<a href=\"https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore#4-deploying-our-web-app\" class=\"hash-link\" aria-label=\"Direct link to 4. Deploying our web app\" title=\"Direct link to 4. Deploying our web app\" translate=\"no\">​</a></h3>\n<div class=\"language-bash codeBlockContainer_Ckt0 theme-code-block\" style=\"--prism-background-color:hsl(220, 13%, 18%);--prism-color:hsl(220, 14%, 71%)\"><div class=\"codeBlockContent_QJqH\"><pre tabindex=\"0\" class=\"prism-code language-bash codeBlock_bY9V thin-scrollbar\" style=\"background-color:hsl(220, 13%, 18%);color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><code class=\"codeBlockLines_e6Vv\"><div class=\"token-line\" style=\"color:hsl(220, 14%, 71%);text-shadow:0 1px rgba(0, 0, 0, 0.3)\"><span class=\"token plain\">firebase deploy</span><br></div></code></pre></div></div>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671904878075/6eddb40a-14a6-41dd-a966-f7c970571e8b.png\" alt=\"Building and deploying | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p><img decoding=\"async\" loading=\"lazy\" src=\"https://cdn.hashnode.com/res/hashnode/image/upload/v1671904911421/12d9c020-4d17-453a-b6a6-840ac597f45b.png\" alt=\"Build completed and deployed successfully | Pranjal Blogs | Pranjal Kumar, Hazaribag Jharkhand | SWE Bentley Systems | Software Engineer | Developer | Architect | System Design\" class=\"img_ev3q\"></p>\n<p>That's it we're done</p>\n<p>Link for the Deployed application will be in the Terminal</p>\n</li>\n</ol>",
            "url": "https://blogs.pranjalkumar.in/blog/deploy-firestore-in-react-on-firestore",
            "title": "Deploying a React project to Firebase with Firestore",
            "summary": "How to deploy a React application to Firebase Hosting with Firestore integration - covering project setup, database configuration, and production deployment.",
            "date_modified": "2022-11-13T00:00:00.000Z",
            "author": {
                "name": "Pranjal Kumar",
                "url": "https://www.linkedin.com/in/pranjal--kumar"
            },
            "tags": [
                "react",
                "firebase"
            ]
        }
    ]
}