<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>The Missing Level</title>
    <link>https://themissinglevel.dev/</link>
    <atom:link href="https://themissinglevel.dev/rss.xml" rel="self" type="application/rss+xml"/>
    <description>Plain-English deep dives into how the web actually works: caching, sessions, password hashing and more. The missing level between mid-level developer and senior.</description>
    <language>en</language>
    <lastBuildDate>Sun, 12 Jul 2026 00:00:00 GMT</lastBuildDate>
    <item>
      <title>Why websites can't tell you your password</title>
      <link>https://themissinglevel.dev/why-websites-cant-tell-you-your-password/</link>
      <guid isPermaLink="true">https://themissinglevel.dev/why-websites-cant-tell-you-your-password/</guid>
      <pubDate>Sun, 12 Jul 2026 00:00:00 GMT</pubDate>
      <description>A properly designed website doesn't know your password — and it can still check that you typed it right. The elegant idea behind hashing, explained without a CS degree.</description>
      <category>Security</category>
      <content:encoded><![CDATA[<p>I still remember the first time someone told me that a properly designed website doesn't actually know my password.</p>
<p>My first reaction was disbelief. If the server doesn't know my password, then how does it know whether I typed the correct one when I log in tomorrow? It felt like one of those statements developers repeat because it sounds clever, but the more I thought about it, the less sense it made.</p>
<p>As it turns out, it wasn't a trick at all. The explanation is surprisingly elegant, and once you understand it, you begin to appreciate how much thought has gone into protecting something as simple as a login form.</p>
<p>The interesting part is that this isn't some cutting-edge security feature used only by banks or large technology companies. It's a principle that every modern web application should follow, whether it's a small personal project or a platform serving millions of users.</p>
<h2 id="the-obvious-solution-would-actually-be-the-worst-one">The obvious solution would actually be the worst one</h2>
<p>Imagine you're building your first website.</p>
<p>Users need accounts, so you create a <code>users</code> table in your database with an email address and a password column. Whenever someone signs up, you simply store whatever they typed. The next time they log in, you compare the password they entered with the one stored in the database.</p>
<p>From a programming perspective, it sounds perfectly reasonable.</p>
<p>From a security perspective, it's a disaster waiting to happen.</p>
<p>If someone gains access to your database, they immediately gain access to everyone's passwords. Even worse, many people reuse the same password across multiple websites. A single breach could allow attackers to access email accounts, social media profiles, online stores, and countless other services.</p>
<p>That's why storing passwords in plain text is considered one of the biggest mistakes a developer can make.</p>
<h2 id="so-what-does-the-server-store-instead">So what does the server store instead?</h2>
<p>Instead of storing the password itself, the server stores the result of a <strong>hash function</strong>.</p>
<p>You can think of a hash as a digital fingerprint. Every time you provide the same input, you get exactly the same output. However, unlike encryption, the process isn't designed to be reversed.</p>
<p>For example, imagine a user chooses the password:</p>
<div class="code-block"><button type="button" data-copy-code aria-label="Copy code" aria-live="polite">Copy</button><pre class="shiki github-dark" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span>myPassword123</span></span></code></pre></div>
<p>After being processed by a hashing algorithm, it could become something like:</p>
<div class="code-block"><button type="button" data-copy-code aria-label="Copy code" aria-live="polite">Copy</button><pre class="shiki github-dark" style="background-color:#24292e;color:#e1e4e8" tabindex="0"><code><span class="line"><span>a336f671080fb420c27461fcf4f2c8d1d87b8a5f6d6f8b5f8f13c2b7d5ad7168</span></span></code></pre></div>
<p>That's what gets stored in the database.</p>
<p>If you look at that string, there's nothing that hints at the original password. It's just a long sequence of characters that appears completely random.</p>
<p>Modern applications typically use password hashing algorithms such as <strong>bcrypt</strong> or <strong>Argon2</strong>, which are specifically designed to make password cracking as difficult as possible. The important idea, though, is much simpler than the algorithms themselves. The server stores the transformed value, not the password you originally typed.</p>
<h2 id="but-how-can-the-website-verify-my-password">But how can the website verify my password?</h2>
<p>This was the part that confused me the most.</p>
<p>If the original password is gone, how can the server possibly know whether I typed it correctly the next day?</p>
<p>The trick is that it never tries to recover the original password.</p>
<p>Instead, when you log in, the server takes the password you just entered and runs it through the exact same hashing algorithm. If the newly generated hash matches the one already stored in the database, then the passwords must have been identical.</p>
<p>The server never compares passwords.</p>
<p>It compares hashes.</p>
<p>That's a subtle difference, but it's one of the reasons modern authentication is so secure.</p>
<h2 id="then-why-can-i-reset-my-password">Then why can I reset my password?</h2>
<p>At this point another question naturally appears.</p>
<p>If websites don't know my password anymore, why can I click <strong>Forgot Password</strong> and get back into my account?</p>
<p>Many people assume the website simply emails them the password it has stored.</p>
<p>A properly designed website can't do that, because it doesn't have the password anymore.</p>
<p>Instead, it generates a temporary reset token that's valid for a limited amount of time. That token proves you requested a password reset. After you choose a new password, the old hash is discarded, a new hash is generated, and the temporary token becomes useless.</p>
<p>This is also why you should immediately become suspicious if a website ever emails you your existing password.</p>
<p>If it can send your password back to you, it probably stored it in a readable form. That's a huge warning sign.</p>
<h2 id="what-if-someone-steals-the-database">What if someone steals the database?</h2>
<p>You might wonder whether hashing makes data breaches harmless.</p>
<p>Not quite.</p>
<p>If attackers steal a database containing password hashes, they can't immediately read everyone's passwords, but they can still try to guess them. They do this by hashing millions of common passwords and comparing the results with the stolen hashes.</p>
<p>This is exactly why modern password hashing algorithms are intentionally slow. While a normal user only logs in occasionally, an attacker might need to test billions of password guesses. Making every guess take significantly longer turns a practical attack into one that can become prohibitively expensive.</p>
<p>Hashing doesn't eliminate risk.</p>
<p>It dramatically raises the cost of attacking the system.</p>
<h2 id="one-small-design-decision-with-enormous-consequences">One small design decision with enormous consequences</h2>
<p>One of the things I enjoy most about software engineering is discovering solutions that feel almost backwards.</p>
<p>Our instinct is often to collect more information because we think it will make the system more capable. In reality, good engineering is often about deciding what information you should never keep in the first place.</p>
<p>A website doesn't need to remember your password forever. It only needs a reliable way to verify that the password you enter tomorrow is the same one you chose today.</p>
<p>That single design decision protects millions of users every day without them ever noticing.</p>
<p>The next time you sign into a website, it's worth remembering that your password probably isn't sitting in a database somewhere waiting to be read. In a well-designed system, it disappeared the moment you created your account, leaving behind only a mathematical fingerprint that proves you know the secret without revealing the secret itself.</p>
<p>In my opinion, that's one of those elegant ideas that makes software engineering so fascinating. Once you understand it, you'll never look at a login form in quite the same way again.</p>]]></content:encoded>
    </item>
    <item>
      <title>What happens after you press Enter</title>
      <link>https://themissinglevel.dev/what-happens-after-you-press-enter/</link>
      <guid isPermaLink="true">https://themissinglevel.dev/what-happens-after-you-press-enter/</guid>
      <pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate>
      <description>DNS, TCP, TLS, HTML parsing, rendering: the journey from typing a URL to seeing the first pixel on screen.</description>
      <category>How the Web Works</category>
      <content:encoded><![CDATA[<p>There is a classic interview question: "what happens when you type a URL and press Enter?" For years my honest answer would have been "the page loads". I knew the acronyms, DNS and TCP and TLS, but only as names. What I was missing was the story, the actual sequence of events between the keypress and the first pixel on screen. Once I learned it, many performance problems that used to confuse me suddenly had clear explanations.</p>
<p>So here is the story, told the way I wish someone had told me. You type an address, you press Enter, and for the next few hundred milliseconds your browser works through a checklist that has not really changed in thirty years: find the server, open a connection, secure the connection, ask for the page, then turn a wall of text into pixels. Every step is a place where time can quietly disappear, and that is exactly why the steps are worth knowing.</p>
<h2 id="first-find-the-server">First, find the server</h2>
<p>The address you typed is a name, and names mean nothing to the network. The internet moves traffic between numeric IP addresses, so before anything else, the browser has to translate <code>example.com</code> into something like <code>93.184.216.34</code>. That translation system is DNS. The simplest way to describe it is a phone book spread across thousands of servers around the world.</p>
<p>A full lookup happens in several steps. Your machine asks a resolver, which is usually run by your internet provider or a public service like Google or Cloudflare. If the resolver does not already know the answer, it asks other DNS servers, level by level, until it reaches the servers responsible for that domain. The good news is that answers get cached at every step, in your browser, in your operating system and in the resolver itself, and each copy expires after a set time. A popular site usually resolves instantly from a nearby cache. An unknown site might need a real trip across the world before the browser even knows where to send the request.</p>
<h2 id="second-open-a-connection">Second, open a connection</h2>
<p>With an IP address in hand, the browser can finally talk to the server, but it cannot simply shout "give me the page" right away. First the two machines set up a TCP connection, and they do it with a short exchange called the three-way handshake. Your machine says "I would like to talk", the server answers "I hear you, go ahead", and your machine confirms "great, starting now". Three messages, and only then does a reliable channel exist between them.</p>
<p>This exchange sounds like something you could skip, but you cannot, because TCP is what makes the internet dependable. The network underneath drops packets, duplicates them and delivers them in the wrong order. TCP hides all of that by numbering every piece of data and resending whatever gets lost. The handshake is how the two sides agree on the starting numbers, so the counting works. The cost is one full round trip before any real data flows. This is why physical distance to the server still matters, even with a fast connection. It is also why CDNs place servers near users: you cannot make light travel faster, but you can make the trip shorter.</p>
<h2 id="third-secure-the-connection">Third, secure the connection</h2>
<p>For an <code>https</code> address there is one more negotiation before the first real byte. It is called the TLS handshake, and it has two jobs. The first job is proving that you are talking to the right server. The server presents a certificate, which is a signed statement from an organization your browser already trusts, saying that this server really does speak for that domain. Your browser checks the signatures, and this check is the machinery behind every certificate warning you have ever clicked through, hopefully after reading it.</p>
<p>The second job is agreeing on encryption keys. The two sides perform a key exchange, which is clever math that lets them arrive at a shared secret even while someone watches every message between them. From that point on, everything they send is encrypted. All of this costs roughly one more round trip, and then, at last, the browser can ask for what you wanted.</p>
<h2 id="fourth-ask-for-the-page">Fourth, ask for the page</h2>
<p>The request itself is very simple after all that setup. The browser sends an HTTP request, which is plain text that says, more or less, "GET / and here is who is asking". The server replies with a status code, response headers and the HTML itself. After three phases of pure plumbing, this is the first moment the conversation is about actual content.</p>
<p>It is also the moment where the server can be slow. Everything up to now was network delay, but the gap between request and response is your application: routing, database queries, template rendering, all of it happening while the browser waits. When developers talk about server response time or "time to first byte", this pause is the thing they are measuring.</p>
<h2 id="fifth-turn-text-into-pixels">Fifth, turn text into pixels</h2>
<p>Now the browser has HTML, and the most interesting work starts. It parses the document from top to bottom, building a tree of elements called the DOM. As it reads, it keeps finding more things it needs. A stylesheet link, an image, a script tag: each one triggers another download, and some of them change how the browser behaves.</p>
<p>Two of these downloads are special because they can pause everything. CSS blocks rendering, because the browser refuses to paint anything before it knows how the page should look. A flash of unstyled content would be worse than a short wait. Classic script tags are even more disruptive, because JavaScript can rewrite the document while it is being parsed. So the parser must stop, fetch the script, run it, and only then continue. This is why "put CSS early, load scripts with <code>defer</code>" became standard performance advice long ago. Fonts have their own version of this problem, where browsers hide or swap text while the real font downloads.</p>
<p>Once the browser has the DOM and the styling information, it runs layout, calculating where every element sits and how big it is. Then it paints, filling in actual pixels and combining the layers into a frame. That frame, the first one with real content in it, is the moment this whole story has been building toward. From keypress to this point is often under a second, and inside that second there was a distributed name lookup, two negotiated handshakes, an application doing real work and a rendering engine laying out a document.</p>
<h2 id="why-the-story-is-worth-knowing">Why the story is worth knowing</h2>
<p>The practical value is that "the site is slow" stops being one big mystery and becomes five small questions. Slow for everyone or only for far-away users? Look at network round trips and CDN placement. Long wait before the first byte? That is the server's part, so go look at the backend. Page arrives fast but appears late? Now you are hunting render-blocking CSS and scripts. Each phase leaves its own kind of evidence, and the waterfall chart in DevTools will show you exactly which one is taking the time.</p>
<p>And the next time someone asks you the interview question, you will have something better than acronyms. You will have the story: find the server, open a connection, secure it, ask for the page, then build the page from text. Everything else in web performance is a detail on top of those five steps.</p>]]></content:encoded>
    </item>
  </channel>
</rss>