<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Giorgi Kobaidze</title>
    <description>The latest articles on DEV Community by Giorgi Kobaidze (@georgekobaidze).</description>
    <link>https://dev.to/georgekobaidze</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg</url>
      <title>DEV Community: Giorgi Kobaidze</title>
      <link>https://dev.to/georgekobaidze</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/georgekobaidze"/>
    <language>en</language>
    <item>
      <title>Vim's Swan Song: Is It Time to :q!?</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Fri, 25 Sep 2026 19:01:14 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/vims-swan-song-is-it-time-to-q-eek</link>
      <guid>https://dev.to/georgekobaidze/vims-swan-song-is-it-time-to-q-eek</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Hotel California&lt;/li&gt;
&lt;li&gt;Hands Off the Mouse&lt;/li&gt;
&lt;li&gt;Vim Was Never About Typing Speed&lt;/li&gt;
&lt;li&gt;The Case for :q!&lt;/li&gt;
&lt;li&gt;Plot Twist: The Terminal Strikes Back&lt;/li&gt;
&lt;li&gt;The Last 10% Is Where Vim Lives&lt;/li&gt;
&lt;li&gt;The Editor Might Leave, The Motions Won't&lt;/li&gt;
&lt;li&gt;So... :q! or :w?&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Hotel California
&lt;/h2&gt;

&lt;p&gt;There's an old joke that the hardest part of learning Vim is figuring out how to leave it. &lt;a href="https://stackoverflow.com/questions/11828270/how-do-i-exit-vim" rel="noopener noreferrer"&gt;The Stack Overflow question&lt;/a&gt; about exiting Vim is one of the most viewed questions on the site, and the answer has become a meme: &lt;code&gt;:q!&lt;/code&gt;.&lt;/p&gt;

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




&lt;h2&gt;
  
  
  Hands Off the Mouse
&lt;/h2&gt;

&lt;p&gt;For decades, Vim's pitch has been simple: keep your hands on the keyboard and do everything faster. No mouse, no menus, no reaching for arrow keys. Just you, the home row, and a text editor that feels like an extension of your fingers.&lt;/p&gt;

&lt;p&gt;I've never been a Vim power user. But I've always been a big believer in treating the keyboard as an extension of your hands. Reaching for the mouse only takes a fraction of a second, but when you're deep in focus, that tiny interruption is enough to break your train of thought. So while I'm not a Vim enthusiast, I still think keyboard shortcuts are essential. Not for speed, but for focus.&lt;/p&gt;

&lt;p&gt;Then AI showed up and started writing our code. So, the question is, do we still need Vim? Or maybe it's time to type &lt;code&gt;:q!&lt;/code&gt; and walk away for good?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The answer is much more nuanced than a yes or no.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Vim Was Never About Typing Speed
&lt;/h2&gt;

&lt;p&gt;Here's the thing most people get wrong about Vim: it was never really about typing speed. You can type just as fast in Notepad.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Alright, 🔥Hot take🔥, folks:&lt;/strong&gt; does fast typing make you a better programmer?&lt;/p&gt;

&lt;p&gt;My take? &lt;strong&gt;Absolutely not! Come on!&lt;/strong&gt; Look, the typing is the easiest part of our job. The hard part is figuring out what to type, and no amount of words per minute is going to help you there. Average speed? You're golden. Trust me.&lt;/p&gt;

&lt;p&gt;Vim's real superpower is that it gives you a language for editing. Instead of pressing keys to move a cursor around and delete characters one by one, you describe what you want to happen:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ci"&lt;/code&gt; means change inside quotes&lt;br&gt;
&lt;code&gt;dap&lt;/code&gt; means delete a paragraph&lt;br&gt;
&lt;code&gt;.&lt;/code&gt; means do that again&lt;/p&gt;

&lt;p&gt;You're not pushing characters around, you're expressing intent, and the editor carries it out.&lt;/p&gt;

&lt;p&gt;That matters because even before AI, most of our time wasn't spent writing new code. It was spent reading, navigating, and changing code that already existed. Keep that in mind, because it's about to become very important.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Case for :q!
&lt;/h2&gt;

&lt;p&gt;Let's be fair and give the "Vim is done" side its best shot, because it makes some good points.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Learning Curve is Harder to Justify
&lt;/h3&gt;

&lt;p&gt;Learning Vim means weeks of feeling slower than before. That investment made sense when you spent eight hours a day writing code by hand. If AI writes most of it now, the payoff shrinks.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-First Tools Aren't Built for Modes
&lt;/h3&gt;

&lt;p&gt;The modern AI workflow revolves around chat panels, inline suggestions, diff views, and an "Accept" button. When your main interaction is describing what you want in plain English, switching between normal and insert mode can feel like friction rather than power.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Next Generation May Never Need It
&lt;/h3&gt;

&lt;p&gt;Developers starting out today might never write enough code by hand to build the muscle memory Vim demands. If your fingers spend the day writing prompts instead of for-loops, &lt;code&gt;hjkl&lt;/code&gt; starts to look like a hobby.&lt;/p&gt;

&lt;p&gt;These are pretty solid arguments. But they miss a plot twist.&lt;/p&gt;




&lt;h2&gt;
  
  
  Plot Twist: The Terminal Strikes Back
&lt;/h2&gt;

&lt;p&gt;Here's the irony nobody predicted: the AI era sent developers back to the terminal.&lt;/p&gt;

&lt;p&gt;Some of the most capable AI coding tools today, like Claude Code and GitHub Copilot CLI, live right there in the command line. When I built &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0"&gt;Metal Birds Watch&lt;/a&gt; for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI challenge&lt;/a&gt;, a big part of my back-and-forth with the AI happened in a terminal window, not a fancy IDE.&lt;/p&gt;

&lt;p&gt;And the terminal was never really gone for developers anyway. SSH into a server, open a shell in a container, fix a config file in production at 2 AM, and there's a good chance Vim (or its ancestor, vi) is the only editor waiting for you, judging your skills.&lt;/p&gt;

&lt;p&gt;So while AI was supposed to pull us further from the keyboard-driven world, it actually made the terminal feel modern again. And Vim has always been the terminal's native tongue.&lt;/p&gt;

&lt;p&gt;Gosh... our industry is basically the Daytona 500: we just keep going in circles. The question is, are you Richard Petty, or the guy he just lapped... twice.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Last 10% Is Where Vim Lives
&lt;/h2&gt;

&lt;p&gt;This is the part that changes everything.&lt;/p&gt;

&lt;p&gt;AI is fantastic at getting you 90% of the way there. But anyone who has shipped AI-generated code knows what the last 10% looks like: rename this variable, delete that redundant block, move this method up, fix the off-by-one error, swap these two arguments.&lt;/p&gt;

&lt;p&gt;Those aren't typing tasks. They're editing tasks, small, precise, surgical changes in code you didn't write yourself.&lt;/p&gt;

&lt;p&gt;Your job is quietly shifting from writing code to reviewing and shaping code. You read a diff, jump to the suspicious part, search for where something is used, change one thing, and move on. That's navigation and editing, which is exactly what Vim was designed for all along.&lt;/p&gt;

&lt;p&gt;AI took the typing. It left the editing. &lt;strong&gt;And editing was always Vim's real job.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Editor Might Leave, The Motions Won't
&lt;/h2&gt;

&lt;p&gt;There's an important distinction here: Vim the program and Vim the way of editing are two different things.&lt;/p&gt;

&lt;p&gt;Vim the program may well stay a niche choice. Plenty of developers will happily live in AI-first editors with chat panels and never open a raw terminal editor.&lt;/p&gt;

&lt;p&gt;But Vim's motions have escaped the editor. They're in VS Code through an extension, in Rider and every other JetBrains IDE through IdeaVim, in Neovim with its huge modern ecosystem and even in your browser through extensions like Vimium. You can use the shiniest AI-powered editor available and still edit like a Vim user.&lt;/p&gt;




&lt;h2&gt;
  
  
  So... :q! or :w?
&lt;/h2&gt;

&lt;p&gt;Is this Vim's swan song? I don't think so. I think we have to keep it as an option. Can't say it's absolutely essential, but it never was to be fair.&lt;/p&gt;

&lt;p&gt;Vim the editor is optional, as it always has been. But Vim as a way of editing becomes more valuable, not less, when your job shifts from writing code to shaping it. &lt;strong&gt;The less you type, the more every edit counts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you already know Vim, keep it. Hold onto it. If you're new, don't learn it to type faster, AI has that covered. Learn the motions to edit faster, because that's the part of the job that isn't going anywhere.&lt;/p&gt;

&lt;p&gt;So maybe it's not time for &lt;code&gt;:q!&lt;/code&gt;. Maybe it's just time for &lt;code&gt;:w&lt;/code&gt; save what works and keep going.&lt;/p&gt;

&lt;p&gt;What about you? Still using Vim or Vim motions, or has AI made you drop them? Let's discuss.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this write-up? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>tools</category>
      <category>vim</category>
      <category>discuss</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Double Engine Failure: Back to the Hangar After Two Data Providers Changed Course</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Thu, 24 Sep 2026 18:00:16 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/double-engine-failure-back-to-the-hangar-after-two-data-providers-changed-course-3o3</link>
      <guid>https://dev.to/georgekobaidze/double-engine-failure-back-to-the-hangar-after-two-data-providers-changed-course-3o3</guid>
      <description>&lt;p&gt;&lt;em&gt;Two providers changed the rules, and my app went back to the hangar&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Showtime on the Balcony (Gone Wrong)
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"I like planes too. I wish I had an app that showed me the planes nearby and their details. That'd be so cool."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;One of my buddy's buddy's buddies said this at a party, while we were out on the balcony getting some fresh air. Well, &lt;strong&gt;I&lt;/strong&gt; was getting fresh air. He was smoking the whole time.&lt;/p&gt;

&lt;p&gt;That was my moment to shine. He was describing, almost word for word, the app I'd won my first hackathon with. So I thought to myself: &lt;em&gt;"It's showtime!"&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I have just the thing for ya" &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I said with a slight smirk, pulled out my phone, typed &lt;code&gt;metalbirdswatch.pilotronica.com&lt;/code&gt; into the browser... only to get this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F724p32p4wna1k3m8qe6c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F724p32p4wna1k3m8qe6c.png" alt="Watermarked Map" width="800" height="1697"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My smirk turned into a "what the hell is this bull shirt" face in about half a second. Obviously I wasn't going to show anyone my app in that state.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Well... umm... yeah... some kind of problem, probably browser-related. I'll show you later."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;It wasn't browser-related.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I knew that for sure. I figured CARTO, the service that draws my map, had changed something in their API or made it paid. Either way it'd be a quick fix, and that'd be it. Easy.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I'll fix it tomorrow and send you the link so you can check it out"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I said.&lt;/p&gt;

&lt;p&gt;Little did I know I was about to find out that the planes were gone too. Metal Birds Watch without the metal birds? Doesn't sound great, does it?&lt;/p&gt;




&lt;h2&gt;
  
  
  A Quick Layover
&lt;/h2&gt;

&lt;p&gt;But let's not get ahead of ourselves. What's the point of explaining anything without proper storytelling? Storytelling on a technical write-up is like a good ragù on tagliatelle. Sure, you can eat the tagliatelle plain, but the sauce makes it so much better.&lt;/p&gt;

&lt;p&gt;Otherwise I'd just drop a link to the release notes and call it a day. Easy, simple. But let's not do that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This One Is Personal
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;By the way, this is me proudly holding a &lt;code&gt;Boeing 737-800&lt;/code&gt; model while recording the project video.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;...and yes, the plane was more camera-friendly than I was.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxhpppd8fc0zmfnyvfbro.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxhpppd8fc0zmfnyvfbro.jpeg" alt="A Man Holding a Plane" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0"&gt;Metal Birds Watch&lt;/a&gt; for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt; on DEV. It was the first hackathon of my life, and I started it on hard mode: the competition was brutal, with over &lt;strong&gt;400 participants&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But I won.&lt;/p&gt;

&lt;p&gt;While building it I had every obstacle in the world, including back, neck and arm pain from shoveling my driveway for hours non-stop. (Pro tip: don't shovel an entire driveway in one go right before a hackathon.)&lt;/p&gt;

&lt;p&gt;I could barely sit up straight while writing the whole thing. My back was killing me.&lt;/p&gt;

&lt;p&gt;So yeah, as you can imagine, this app is pretty special to me. It's my baby.&lt;/p&gt;




&lt;h2&gt;
  
  
  Engine #1: The Map That Said No
&lt;/h2&gt;

&lt;p&gt;The morning after the party. I poured a cup of dark coffee, sat down at my desk, put on some music (RHCP, as usual), and got to work. Time to fix this thing.&lt;/p&gt;

&lt;p&gt;the first job was to figure out why on earth the map looked like that.&lt;/p&gt;

&lt;p&gt;It turned out CARTO had changed its policy around &lt;strong&gt;28 August 2026&lt;/strong&gt;. Their free basemaps now require an API key, and requests without one get tiles with &lt;strong&gt;"API KEY REQUIRED"&lt;/strong&gt; stamped diagonally across them.&lt;/p&gt;

&lt;p&gt;I didn't have a CARTO account, so they had no email address to warn me, and I'm sure plenty of other users were in the same position. Their best way to tell us was to cover our maps with the message. Fair enough.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Quick Patch on the Tarmac
&lt;/h3&gt;

&lt;p&gt;This was the easy part. I requested a free key, which allows 5 million tile requests per month, and added it to the tile URL. My map URLs live in CSS custom properties, one per theme:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="c"&gt;/* variables.css, before */&lt;/span&gt;
&lt;span class="nt"&gt;--map-tiles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="c"&gt;/* after */&lt;/span&gt;
&lt;span class="nt"&gt;--map-tiles&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png?key=YOUR_KEY'&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That was the whole change: &lt;strong&gt;not a single line of JavaScript&lt;/strong&gt;. The map reads its tile URL from CSS on startup and again on every theme switch, so both picked up the key automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tileUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--map-tiles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;'"&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;tileLayer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;L&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tileLayer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tileUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;addTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Past me, thank you for that architecture decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pre-Flight Checklist
&lt;/h3&gt;

&lt;p&gt;There were a few details to think through, though.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Should the key be committed to a public repo?&lt;/strong&gt; My first instinct was "never commit keys." But a map tile key &lt;em&gt;can't&lt;/em&gt; be secret: the browser sends it with every tile request, and anyone can see it in DevTools. What protects it is a &lt;strong&gt;domain restriction&lt;/strong&gt; set in CARTO's dashboard, so the key only works on my production domain. Committing it was fine.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. A CSP trap.&lt;/strong&gt; CARTO's current docs show the apex domain, &lt;code&gt;basemaps.cartocdn.com&lt;/code&gt;. My Content Security Policy only allows &lt;code&gt;https://*.basemaps.cartocdn.com&lt;/code&gt;, and that wildcard doesn't match the apex domain. If I'd copied the URL from the docs, the tiles would have been silently blocked by my own CSP. Keeping the &lt;code&gt;{s}.&lt;/code&gt; subdomain form avoided a second outage in the same fix.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The domain restriction backfired locally.&lt;/strong&gt; Because the key only works on production, every tile on &lt;code&gt;localhost&lt;/code&gt; returned &lt;strong&gt;403&lt;/strong&gt;, and my local map went completely grey. I later added a small helper that swaps the key on localhost for a personal development key stored in the browser, or removes it entirely:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTileUrl&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getComputedStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;documentElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getPropertyValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;--map-tiles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;'"&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isLocalhost&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// production: unchanged&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;devKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;carto-dev-key&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;devKey&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/key=&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`key=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;devKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// your own dev key&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;?&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;key=&lt;/span&gt;&lt;span class="se"&gt;[^&lt;/span&gt;&lt;span class="sr"&gt;&amp;amp;&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// no key: watermark, but it works&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My development key lives in my browser, not in a file, so it can never be committed by accident.&lt;/p&gt;

&lt;p&gt;I added the key, tested it, and everything was back to normal. I was so happy to see my favorite app, my baby, running smoothly again.&lt;/p&gt;

&lt;p&gt;Time to deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Engine #2: Where Did All the Birds Go?
&lt;/h2&gt;

&lt;p&gt;I ran the pipeline, and it deployed. Alright, let me check production.&lt;/p&gt;

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

&lt;p&gt;OK, whoa whoa whoa whoa. What do you mean, &lt;em&gt;Failed to fetch plane data: API error: 503 Service Unavailable&lt;/em&gt;?&lt;/p&gt;

&lt;p&gt;The map was clean, and it was also completely empty. No planes. The status indicator said &lt;strong&gt;OFFLINE&lt;/strong&gt;, and an error toast showed up every 20 seconds or so like clockwork: the frontend asked for planes, waited about 10 seconds, got a &lt;strong&gt;503&lt;/strong&gt;, then tried again.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Instrument That Lied
&lt;/h3&gt;

&lt;p&gt;The backend logs were very clear about the problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Authentication failed - check OpenSky credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Makes sense. My flight data comes from OpenSky Network, and the backend authenticates with OAuth client credentials before fetching aircraft. Maybe the credentials had expired, or been revoked.&lt;/p&gt;

&lt;p&gt;So I rotated them. It didn't help.&lt;/p&gt;

&lt;p&gt;So I rotated them &lt;em&gt;again&lt;/em&gt;. It didn't help either.&lt;/p&gt;

&lt;p&gt;Two credential rotations and several hours later, I finally looked closely at the code that produced the message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;tokenRefreshPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getAccessToken&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Failed to get OAuth token:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authentication failed - check OpenSky credentials&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;})();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Can you see it? &lt;strong&gt;Every&lt;/strong&gt; failure became "Authentication failed": network timeouts, DNS errors, HTTP errors, &lt;em&gt;and&lt;/em&gt; genuine credential problems. The code swallowed the real error and replaced it with a confident, specific and completely wrong diagnosis.&lt;/p&gt;

&lt;p&gt;The error message had been lying to me all along, and I'd written it myself. That hurt.&lt;/p&gt;

&lt;h3&gt;
  
  
  Opening Up the Engine
&lt;/h3&gt;

&lt;p&gt;Enough guessing. If the error message wasn't going to tell me the truth, I'd make the error tell me itself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: log everything.&lt;/strong&gt; Instead of trusting my own summary, I logged every detail of the raw error: its &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;syscall&lt;/code&gt;, &lt;code&gt;address&lt;/code&gt;, &lt;code&gt;port&lt;/code&gt;, and most importantly its &lt;code&gt;cause&lt;/code&gt;. That's how you tell a DNS failure from a TCP failure, a TLS failure or an actual HTTP error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OpenSky auth error details:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cause&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I deployed, waited, and the logs finally told the truth. It wasn't an authentication failure at all. It was a &lt;strong&gt;TCP connect timeout&lt;/strong&gt; to OpenSky's auth server. My backend never got as far as sending the credentials I'd rotated twice, because it couldn't even open a connection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: be patient.&lt;/strong&gt; A timeout? Maybe OpenSky's server was just slow to respond from Railway's network. So I increased the auth request timeout to 30 seconds:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I deployed, waited, and got exactly the same error, still after &lt;strong&gt;10 seconds&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Wait, what? I'd just set it to 30.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: find out where the 10 seconds came from.&lt;/strong&gt; Node's &lt;code&gt;fetch&lt;/code&gt; is built on &lt;strong&gt;undici&lt;/strong&gt;, and undici has its own separate &lt;strong&gt;10-second limit for opening a TCP connection&lt;/strong&gt;. That limit applies before any request timeout you set yourself. So my 30-second timeout never got a chance to run; undici gave up first.&lt;/p&gt;

&lt;p&gt;To change it, you pass fetch a custom undici &lt;code&gt;Agent&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undici&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;authDispatcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30000&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// give the TCP handshake 30s instead of 10s&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;OPENSKY_AUTH_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="na"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;authDispatcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;My theory was that the TCP handshake from Railway to OpenSky was just slow and would get there eventually if I gave it enough time.&lt;/p&gt;

&lt;p&gt;I deployed, waited, and waited some more.&lt;/p&gt;

&lt;p&gt;Reader, it did not get there eventually. I gave it 30 seconds. I could have given it 30 minutes. A connection that isn't slow but &lt;strong&gt;ignored&lt;/strong&gt; will never complete, however long you wait.&lt;/p&gt;

&lt;h3&gt;
  
  
  Silence on the Frequency
&lt;/h3&gt;

&lt;p&gt;This was the turning point, so it's worth a short technical detour.&lt;/p&gt;

&lt;p&gt;When you try to connect to a server, there are roughly two ways it can go wrong:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Connection refused:&lt;/strong&gt; the server's machine answers and says "nobody's listening on that port". It's fast and polite.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connection timeout:&lt;/strong&gt; nothing answers at all. Your packets leave, and nothing comes back.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A timeout on a server that's otherwise up and working for everyone else usually means one thing: &lt;strong&gt;something is dropping your packets on purpose&lt;/strong&gt;, typically a firewall. And the only unusual thing about my backend's packets was where they came from: a cloud provider's IP range.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tower, Do You Copy?
&lt;/h3&gt;

&lt;p&gt;So I asked OpenSky directly:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Do you block hosting and cloud provider IP ranges?&lt;/strong&gt;&lt;br&gt;
"Yes."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can a specific address be allowlisted?&lt;/strong&gt;&lt;br&gt;
"No."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What's the recommended approach for hosted apps?&lt;/strong&gt;&lt;br&gt;
They're considering a paid option to handle the requests coming from cloud providers.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So that was that. The blocking is deliberate, exceptions aren't possible, and a paid option might come someday. &lt;strong&gt;There's currently no supported way to use OpenSky from a hosted backend.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's a bummer. Real bummer. I really liked OpenSky's service.&lt;/p&gt;

&lt;p&gt;To be fair to OpenSky, I get it. They run a free, community-driven service, and they're being flooded by automated traffic from cloud servers.&lt;/p&gt;




&lt;h2&gt;
  
  
  Back to the Hangar
&lt;/h2&gt;

&lt;p&gt;So it was time to land the plane. I fixed one engine mid-air, but I couldn't do it for the second one. So I had to land and go back into the hangar.&lt;/p&gt;

&lt;p&gt;Adding an API key is easy, especially a public one. Researching and integrating a new flight data provider is not something you do in a few minutes, or even a few hours.&lt;/p&gt;

&lt;p&gt;So I put the app into &lt;strong&gt;maintenance mode&lt;/strong&gt;. It'll take a while to find the right provider, but hey, great things take time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxu94hx8ddmm14mop3o0.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foxu94hx8ddmm14mop3o0.jpeg" alt="Maintenance Page" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ten Seconds of Doubt
&lt;/h3&gt;

&lt;p&gt;That was my first idea, and it's a trap. The backend takes &lt;strong&gt;about 10 seconds&lt;/strong&gt; to return that 503. A banner that appears &lt;em&gt;after&lt;/em&gt; the failed request leaves users staring at an empty map for 10 seconds first. That's exactly when they decide the app is broken, or that there just aren't any planes overhead.&lt;/p&gt;

&lt;p&gt;So the maintenance page is &lt;strong&gt;unconditional&lt;/strong&gt;. It appears immediately and doesn't wait for anything to fail. One flag controls it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;MAINTENANCE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;ACTIVE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                  &lt;span class="c1"&gt;// Set to false once the new data provider is live&lt;/span&gt;
  &lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;opensky-2026-09&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;SINCE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-09-20&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// Used for the "day N" counter&lt;/span&gt;
  &lt;span class="nx"&gt;ISSUE_URL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://github.com/georgekobaidze/metal-birds-watch/issues/98&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When it's on, the map doesn't load, the browser doesn't ask for your location, and polling never starts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;startPolling&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Skip polling during maintenance - the backend can't reach the data provider,&lt;/span&gt;
  &lt;span class="c1"&gt;// so every request would time out and show an error toast&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;CONFIG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAINTENANCE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ACTIVE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No more doomed requests, no more error toasts every 20 seconds, and no more "is it me?"&lt;/p&gt;

&lt;h3&gt;
  
  
  Speaking Fluent Aviation
&lt;/h3&gt;

&lt;p&gt;Since this is an aviation app, the maintenance page talks like one:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A NOTAM-style notice.&lt;/strong&gt; A NOTAM ("Notice to Air Missions") is how pilots are told about closures and outages. The notice sits over a full-screen photo of a plane being repaired in a hangar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A radio call:&lt;/strong&gt; &lt;em&gt;"All stations, all stations: Metal Birds Watch is out of service for unscheduled maintenance until further notice."&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A counter:&lt;/strong&gt; &lt;em&gt;"Grounded since 20 Sep 2026 · day N"&lt;/em&gt;, updated automatically.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ask the Tower:&lt;/strong&gt; a small panel that answers the questions people actually have, such as &lt;em&gt;Is it something on my end?&lt;/em&gt; ("Negative."), &lt;em&gt;Is my logbook safe?&lt;/em&gt; ("Affirmative. It lives in your own browser.") and &lt;em&gt;When will it be fixed?&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4z9cvbklp2b7fukb1uxk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4z9cvbklp2b7fukb1uxk.png" alt="Ask the Tower" width="800" height="1254"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's no AI in the Tower, which felt right given the circumstances. It's a list of pre-written questions and answers with a typing indicator for effect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;logbook&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;question&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Is my logbook safe?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;answer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Affirmative. Your logbook lives in your own browser, not on our servers, so the &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;outage can&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;t touch it. Open it anytime with the 📖 button up top.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;followUps&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stillWorks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Looking for a New Engine
&lt;/h2&gt;

&lt;p&gt;Replacing the data provider is tracked in &lt;a href="https://github.com/georgekobaidze/metal-birds-watch/issues/98" rel="noopener noreferrer"&gt;issue #98&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The good news is that my OpenSky code is already an isolated adapter. It converts OpenSky's response into my own data format, and nothing above it knows where the data comes from. A new provider is one new service file behind the same interface. The routes, the cache and the entire frontend stay the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading the Black Box
&lt;/h2&gt;

&lt;p&gt;If I had to summarize the flight recorder:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Silent failures are the worst failures.&lt;/strong&gt; An HTTP 200 containing a watermark and a 503 nobody was watching both went unnoticed for about three weeks. I found out at a party, from a phone, while trying to show off. Some basic monitoring would have found them for me.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Your error messages are part of your debugging tools.&lt;/strong&gt; A misleading one costs hours. Mine cost two credential rotations and an afternoon.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A timeout and a refusal tell you different things.&lt;/strong&gt; A refusal means nobody is listening. A timeout, when the server works for everyone else, usually means someone chose not to answer you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free services can change their rules at any time.&lt;/strong&gt; That's not a complaint. They don't owe anyone anything. But design for it: isolate your providers behind adapters, and have a plan for the day one disappears.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;When you can't fix it right away, say so clearly and immediately.&lt;/strong&gt; An honest maintenance page is better than an empty map that makes people think the app is broken.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Final Approach
&lt;/h2&gt;

&lt;p&gt;As for my buddy's buddy's buddy: I still owe him that link. It's coming, I promise, with planes on it.&lt;/p&gt;

&lt;p&gt;Until then, Metal Birds Watch is in the hangar, the mechanics are at work, and the new engine is on order.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We promise we'll be flying again together soon.&lt;/strong&gt; 🛫&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Follow the progress in &lt;a href="https://github.com/georgekobaidze/metal-birds-watch/issues/98" rel="noopener noreferrer"&gt;issue #98&lt;/a&gt;, or read the &lt;a href="https://github.com/georgekobaidze/metal-birds-watch/releases/tag/v1.0.2" rel="noopener noreferrer"&gt;v1.0.2 release notes&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this write-up? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>debugging</category>
      <category>showdev</category>
      <category>webdev</category>
      <category>node</category>
    </item>
    <item>
      <title>Real Talk: You Don't Miss Engineering. You Miss Typing</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Mon, 21 Sep 2026 20:36:39 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/real-talk-you-dont-miss-engineering-you-miss-typing-1bc3</link>
      <guid>https://dev.to/georgekobaidze/real-talk-you-dont-miss-engineering-you-miss-typing-1bc3</guid>
      <description>&lt;h2&gt;
  
  
  A Sci-Fi Scenario Come True
&lt;/h2&gt;

&lt;p&gt;As a kid, when I watched sci-fi movies about computers with human-like thinking, I was completely sure they'd never exist. That was in the early 2000s. Now we live alongside them. Engineering isn't ending. It's starting.&lt;/p&gt;




&lt;h2&gt;
  
  
  Nostalgia Isn't an Argument
&lt;/h2&gt;

&lt;p&gt;Lately I keep seeing engineers declare that "real engineering is gone," that "they're done with this s...," that "it's all AI now," and that they miss typing every line themselves. I understand the feeling, but I think it confuses nostalgia with how engineering and science work in general.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Most Dynamic Era to Be an Engineer
&lt;/h2&gt;

&lt;p&gt;I feel bad for engineers who can't see that this is one of the best times, if not the best time, to be an engineer. Look around: things change almost overnight. For most of human history, life changed slowly, with generations living in roughly the same world as their parents, grandparents, or great-grandparents. We're living through one of the most dynamic eras ever.&lt;/p&gt;

&lt;p&gt;Sure, I still have a soft spot for '80s vibes, even though I wasn't even born yet. But there's no need to invent a problem and suffer over it when there are so many things to catch up with.&lt;/p&gt;

&lt;p&gt;Just ask yourself how many things you don't know that you want to know.&lt;/p&gt;




&lt;h2&gt;
  
  
  We've Been Here Before
&lt;/h2&gt;

&lt;p&gt;Tech and science don't give a damn about the good ol' days. It's always been like this.&lt;/p&gt;

&lt;p&gt;When Grace Hopper built early compilers, skeptics doubted "automatic programming" was serious work. When FORTRAN arrived, programmers doubted compiled code could match hand-written assembly.&lt;/p&gt;

&lt;p&gt;High-level languages, frameworks, and package managers all triggered the same fear, and each time the industry grew. AI is the next rung on the same ladder.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Hard Part Was Never the Typing
&lt;/h2&gt;

&lt;p&gt;Never. You spend exponentially more time thinking about the problem than typing the code that expresses your thoughts.&lt;/p&gt;

&lt;p&gt;The real program is the understanding in the engineers' heads, not the source code. AI can generate thousands of lines, but someone still has to hold the theory of why the system works the way it does.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottleneck Moves
&lt;/h2&gt;

&lt;p&gt;Speeding up one step only helps as much as that step mattered. Make code generation instant, and the constraints shift to requirements, design, review, and debugging. Generating code is getting cheap; verifying it is not. That judgment is engineering.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cheaper Software Means More Software
&lt;/h2&gt;

&lt;p&gt;Every time software got cheaper to build, we built far more of it. Lower costs unlock problems that were never worth solving before.&lt;/p&gt;




&lt;h2&gt;
  
  
  Coding Was Never the Point
&lt;/h2&gt;

&lt;p&gt;What matters is who does the engineering: you, the AI, or both of you together. My bet is on the engineers who choose both and keep the thinking for themselves.&lt;/p&gt;

&lt;p&gt;So please, just stop dwelling on things that are inevitable and focus on the real problems, and the real opportunities will show up.&lt;/p&gt;

&lt;p&gt;Just don't vibe code, please! That's not engineering and nobody can change my mind about that.&lt;/p&gt;

&lt;p&gt;I hope this little note helps a bit.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this brief note? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>software</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Clean Code Is Not the Same as Clear Code: Comments Were Never the Problem</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Mon, 21 Sep 2026 18:07:10 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/clean-code-is-not-the-same-as-clear-code-comments-were-never-the-problem-42n</link>
      <guid>https://dev.to/georgekobaidze/clean-code-is-not-the-same-as-clear-code-comments-were-never-the-problem-42n</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A Line That Does Nothing... Except Keep Production Alive&lt;/li&gt;
&lt;li&gt;Some Code Can't Explain Itself&lt;/li&gt;
&lt;li&gt;The Code Knows What. Only You Know Why&lt;/li&gt;
&lt;li&gt;"Just Put It in the Commit Message"&lt;/li&gt;
&lt;li&gt;So What's the Worst That Can Happen?&lt;/li&gt;
&lt;li&gt;How Not to Write Comments&lt;/li&gt;
&lt;li&gt;Clean Gets You Halfway&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  A Line That Does Nothing... Except Keep Production Alive
&lt;/h2&gt;

&lt;p&gt;Somewhere along the way, our industry decided that writing a comment means you've failed as an engineer and need to "git good" (don't try that in the terminal, it's not a git command). If your code needs explaining, the logic goes, your code isn't good enough.&lt;/p&gt;

&lt;p&gt;I won't lie, I really like the idea. I'd love every codebase to be so clean that you open a file, read it once, and think "yep, got it." Everything logical, everything obvious.&lt;/p&gt;

&lt;p&gt;But...&lt;/p&gt;

&lt;p&gt;I'd also love roads so well designed they don't need signs. But even the most beautifully engineered mountain road has a "sharp bend ahead" sign, and not because the engineers failed. It's there because you can't see the bend until you're already in it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fag6antb5razcrjz6dsz4.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fag6antb5razcrjz6dsz4.jpeg" alt="Sharp Bend" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So here's the quick reality check:&lt;/strong&gt; not every function can explain what it's doing. Not now, not tomorrow, not ever. There will always be code that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Was never written with structure in mind, so nobody understands it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is written just beautifully, but solves a problem so complex that you still need five hours staring at one function to follow it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Is simple, clean, and perfectly readable, yet does something for a reason that isn't visible anywhere in the code.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Some Code Can't Explain Itself
&lt;/h2&gt;

&lt;p&gt;Here's a perfectly clean piece of C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;FlightNumbers&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GeneratedRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"^([A-Z]{2}|[A-Z]\d|\d[A-Z])(\d{1,4})([A-Z]?)$"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="n"&gt;Regex&lt;/span&gt; &lt;span class="nf"&gt;FlightNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nf"&gt;FlightNumber&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToUpperInvariant&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good names. Modern, source-generated regex. Nothing to refactor, nothing to rename.&lt;/p&gt;

&lt;p&gt;Now, quick quiz. Which of these are valid?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;FlightNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"BA123"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;FlightNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"U21234"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;FlightNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"9W5A"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;FlightNumbers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"99123"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unless you're an aviation nerd like me, or someone who reads regex fluently (if you do, my goodness, more power to you), you have no idea what this method is actually checking.&lt;/p&gt;

&lt;p&gt;Sure, you can look it up. Sure, you can read the documentation. And sure, there must be unit tests that describe exactly what's valid and what isn't. Right?!&lt;/p&gt;

&lt;p&gt;Well, yes, on paper, however "on paper" and "actually" can be like the burger in the ad and the burger in the box.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd9a2wcfb9pxiclxe0vi.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnd9a2wcfb9pxiclxe0vi.jpeg" alt="Burger" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes there's no documentation. Sometimes there are no unit tests. Sometimes there's just you, the regex, and a growing sense of dread.&lt;/p&gt;

&lt;p&gt;But even when the docs and tests exist, why should you have to derail your train of thought, open three tabs, and go on a scavenger hunt, when a single comment could be sitting right there on top of the code, waiting for you?&lt;/p&gt;

&lt;p&gt;Let me show you. Then tell me this isn't infinitely better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// IATA flight number, e.g. "BA123", "U21234", "9W5A".&lt;/span&gt;
&lt;span class="c1"&gt;// Airline code is 2 chars: two letters, or a letter-digit mix (U2 = easyJet).&lt;/span&gt;
&lt;span class="c1"&gt;// Then a 1-4 digit flight number and an optional operational suffix letter.&lt;/span&gt;
&lt;span class="c1"&gt;// Uppercase only, no spaces: normalize input before matching.&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;GeneratedRegex&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@"^([A-Z]{2}|[A-Z]\d|\d[A-Z])(\d{1,4})([A-Z]?)$"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="n"&gt;Regex&lt;/span&gt; &lt;span class="nf"&gt;FlightNumber&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plus, you also learn things the code could never tell you.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Code Knows What. Only You Know Why
&lt;/h2&gt;

&lt;p&gt;The regex was a translation problem: the code was correct, it just spoke a language most humans don't. But there's a second kind of comment, and it's arguably even more valuable, because it covers something the code can't express in any language.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxConcurrentRequests&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;47&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clean. Named. A constant, not a magic number buried in a loop. Textbook.&lt;/p&gt;

&lt;p&gt;And yet every developer who sees it has the same thought: why 47? It's not a round number. It's not a power of two. It looks like someone's lucky number, or a typo, or the result of a very long night. The provider's documentation says the limit is 50, so surely this is just a mistake.&lt;/p&gt;

&lt;p&gt;So somebody changes it to 50. And a few weeks later, under real traffic, the provider starts rejecting requests at random, and nobody can reproduce it.&lt;/p&gt;

&lt;p&gt;Here's what was missing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 47, not 50. The provider documents 50 requests per second, but their&lt;/span&gt;
&lt;span class="c1"&gt;// limiter measures bursts over a 1.2s window, so retries at 50 trip it.&lt;/span&gt;
&lt;span class="c1"&gt;// Recheck if they publish new limits.&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxConcurrentRequests&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;47&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the part of the code that lives only in the head of whoever wrote it. The code records the decision. The comment records the reasoning. Lose the reasoning, and the decision looks like a bug.&lt;/p&gt;

&lt;p&gt;So, in practice, a good comment does one of four jobs:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Translates
&lt;/h4&gt;

&lt;p&gt;Dense code like a regex, a bit trick, or a math formula, where the what isn't obvious even when the code is perfect.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. Explains
&lt;/h4&gt;

&lt;p&gt;The reason behind a choice that looks wrong, arbitrary, or unnecessary.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Warns
&lt;/h4&gt;

&lt;p&gt;What breaks if you change this, and how badly.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. Records
&lt;/h4&gt;

&lt;p&gt;A decision with an expiry date. What was tried, what didn't work, and when it's worth revisiting.&lt;/p&gt;

&lt;p&gt;If a comment doesn't do one of those four jobs, it probably shouldn't exist. But if it does, deleting it for the sake of "clean code" isn't cleaning.&lt;/p&gt;

&lt;p&gt;By the way, these are extremely simple examples, in practice, you'll come across much more complex scenarios.&lt;/p&gt;




&lt;h2&gt;
  
  
  "Just Put It in the Commit Message"
&lt;/h2&gt;

&lt;p&gt;At this point, someone in the back raises their hand: the reasoning belongs in git history. Write a good commit message, keep the source clean. That's what version control is for.&lt;/p&gt;

&lt;p&gt;Again, on paper, it sounds disciplined. But in practice, go run git log on any file that's older than a year. I'll wait.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;...
a91f3c2  apply editorconfig
7d2e8b1  fix
3c4f9a0  fix again
e81b7d4  PR feedback
b02c6f5  final fix
f5a1e93  final fix (actually)
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Somewhere in there is the reason &lt;code&gt;MaxConcurrentRequests&lt;/code&gt; is 47. Good luck. Let me know when you find it.&lt;/p&gt;

&lt;p&gt;And what if you don't? You're just going to sit and blame everything and everyone? Or just be pragmatic and write a short comment that'll solve problems for other developers and future you? &lt;strong&gt;Maybe if past you hadn't been so dogmatic you'd have been exponentially happier now?&lt;/strong&gt; Have you thought about that?&lt;/p&gt;

&lt;p&gt;And by the way even if your team writes beautiful commit messages, the approach still breaks down for a few boring, practical reasons.&lt;/p&gt;

&lt;h4&gt;
  
  
  Nobody runs &lt;code&gt;git blame&lt;/code&gt; on code that looks fine
&lt;/h4&gt;

&lt;p&gt;This is the big one. You don't go looking for a reason when you don't know there is one. A constant set to 47 looks like a typo, not like a mystery worth investigating. A comment interrupts you before you make the mistake. Git history only answers questions you already thought to ask.&lt;/p&gt;

&lt;h4&gt;
  
  
  Blame decays
&lt;/h4&gt;

&lt;p&gt;One reformat, one rename, one file split, one squash merge, and the line now points to a commit titled "apply editorconfig." The original reason is still in there somewhere, buried under years of unrelated changes. Finding it is no longer a lookup. It's archaeology. Archaeology takes time and effort.&lt;/p&gt;

&lt;h4&gt;
  
  
  People leave
&lt;/h4&gt;

&lt;p&gt;Sometimes the real documentation isn't the commit history at all. It's Bill. Bill knows why it's 47. Bill also left for a new company two years ago and won't pick up the phone, because he knows you're going to bother him with those questions.&lt;/p&gt;

&lt;p&gt;Commit messages are great at explaining a change: what was different about this commit and why. They're terrible at explaining a current state, because the current state is the sum of dozens of changes, and nobody is going to reconstruct it by reading them in order.&lt;/p&gt;

&lt;p&gt;The comment is the only place that describes the code as it is right now, right where you're looking at it.&lt;/p&gt;




&lt;h2&gt;
  
  
  So What's the Worst That Can Happen?
&lt;/h2&gt;

&lt;p&gt;Let's flip the question. Say you write a comment. What's the worst-case scenario?&lt;/p&gt;

&lt;p&gt;The most common argument I hear is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;"if you change the code, you have to change the comment too."&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;And... so what?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Seriously. How hard is it? The comment is right there. Not in a wiki, not in a Confluence page nobody has opened since 2021, not in a separate repository. It's one line above the code you're already editing. If you can change 47 to 50, you can change the sentence directly on top of it. You're literally looking at it.&lt;/p&gt;

&lt;p&gt;The argument assumes there's some rule that a change should touch only the code and leave everything around it untouched. There isn't. When you change a method's behavior, you update its tests. When you rename a parameter, you update its callers. Updating the comment that describes the thing you just changed is the same kind of work. It's not overhead. It's the job.&lt;/p&gt;

&lt;p&gt;This is part of a bigger pattern: taking a good guideline and following it so strictly that it starts hurting the code it was supposed to help.&lt;/p&gt;

&lt;p&gt;Take DRY. That's a topic for another episode of this series, but ask yourself honestly: does strictly following DRY always make your code better?&lt;/p&gt;

&lt;p&gt;Nuh-uh.&lt;/p&gt;

&lt;p&gt;Sometimes two pieces of code look similar, so someone extracts a shared function to avoid the "duplication." Then the two use cases drift apart a little, so the function grows a parameter. Then another. Then a couple of flags. And six months later you're reading this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="nf"&gt;ProcessOrder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"legacy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;skipValidation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Congratulations, the code is DRY. The only downside is that nobody knows what it does. Not even future you, by the way.&lt;/p&gt;

&lt;p&gt;Don't tell me you haven't seen, or better yet, written a function/method like this. I have, when I was junior/mid-level developer. And it made my life miserable.&lt;/p&gt;

&lt;p&gt;Sometimes it's perfectly fine to repeat a few lines in two places, because keeping each piece readable on its own matters more than eliminating every repeated pattern. Duplication isn't automatically bad, and abstraction isn't automatically good. Everything is a tradeoff, and knowing which side to pick is exactly the kind of instinct that separates a good developer from someone following a checklist.&lt;/p&gt;

&lt;p&gt;Comments work the same way. "Never write comments" and "comment everything" are both checklists. The right answer is to write the comment when it carries something the code can't, and to keep it updated the same way you keep everything else updated: because it's right there.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Not to Write Comments
&lt;/h2&gt;

&lt;p&gt;Now, before anyone runs off and starts commenting every line: none of this is permission to narrate your code. Bad comments are real, and they're a big part of why comments got a bad reputation in the first place. Here's the hall of shame.&lt;/p&gt;

&lt;h4&gt;
  
  
  The echo
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Increment the retry count&lt;/span&gt;
&lt;span class="n"&gt;retryCount&lt;/span&gt;&lt;span class="p"&gt;++;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The XML doc that says absolutely nothing
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// Gets the user&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;param name="id"&amp;gt;The id.&amp;lt;/param&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;/// &amp;lt;returns&amp;gt;The user&amp;lt;/returns&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;User&lt;/span&gt; &lt;span class="nf"&gt;GetUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Six lines of ceremony and zero information. Every .NET codebase has thousands of these, usually generated by a tool to make a warning go away. If you're going to write a doc comment, tell me something the signature doesn't.&lt;/p&gt;

&lt;h4&gt;
  
  
  The liar
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Retry up to 3 times&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;MaxRetries&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  The eternal "temporary" fix.
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// TODO: temporary workaround, remove later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Later when? Remove it how? Under what conditions? This comment was written in 2019 and it will outlive us all. If something is temporary, say what it's waiting for: a ticket, a version, a date.&lt;/p&gt;

&lt;h4&gt;
  
  
  The graveyard
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// var result = await _legacyService.CalculateAsync(order);&lt;/span&gt;
&lt;span class="c1"&gt;// if (result.IsValid) { ... }&lt;/span&gt;
&lt;span class="c1"&gt;// var result2 = await _newService.CalculateAsync(order);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commented-out code tells the reader nothing except that someone was scared to delete it. Delete it. If you ever need it again, you won't.&lt;/p&gt;

&lt;h4&gt;
  
  
  The novel
&lt;/h4&gt;

&lt;p&gt;A thirty-line method with a three-paragraph comment on top explaining how it works. Sometimes that's necessary. Often it's a sign the code should be rewritten, and the comment is compensating. Try the refactor first. Then comment whatever complexity is left.&lt;/p&gt;




&lt;h2&gt;
  
  
  Clean Gets You Halfway
&lt;/h2&gt;

&lt;p&gt;Clean code is a great goal. Good names, small methods, clear structure: keep doing all of it. But clean code answers one question, what does this do?, and a real codebase keeps asking more. Why is it like this? What happens if I change it? Is this weird thing a bug or a scar?&lt;/p&gt;

&lt;p&gt;Those answers don't live in the syntax. They live in the head of whoever wrote the code, and heads are terrible storage. They change jobs, they go on vacation, and they forget things by Tuesday.&lt;/p&gt;

&lt;p&gt;So here's the rule I actually follow, and it fits in one sentence:&lt;/p&gt;

&lt;p&gt;If I had to stop and think before writing a line, I write down what I thought.&lt;/p&gt;

&lt;p&gt;If the line was obvious, I leave it alone. No echoes, no ceremony, no dragons. But if there was a moment where I went "hmm, careful here," that moment goes into a comment, because the next reader is going to have the exact same "hmm," just without the answer.&lt;/p&gt;

&lt;p&gt;Clean code tells the reader what you did. A good comment tells them what you knew. You need both.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this write-up? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>programming</category>
      <category>discuss</category>
      <category>documentation</category>
      <category>coding</category>
    </item>
    <item>
      <title>Vibe Coding Isn't the Problem. Calling It Engineering Is</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 13 Sep 2026 07:06:59 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/vibe-coding-isnt-the-problem-calling-it-engineering-is-lm1</link>
      <guid>https://dev.to/georgekobaidze/vibe-coding-isnt-the-problem-calling-it-engineering-is-lm1</guid>
      <description>&lt;h2&gt;
  
  
  Let's Address the Elephant in the Room Again
&lt;/h2&gt;

&lt;p&gt;Vibe coding has always been a weird topic to talk about. Lately it's gotten even weirder.&lt;/p&gt;

&lt;p&gt;Say &lt;strong&gt;"vibe coding is a creative process, but it's not engineering"&lt;/strong&gt; and people get defensive immediately, calling you a gatekeeper and all those interesting terms.&lt;/p&gt;

&lt;p&gt;So I decided to write this brief article to answer those opinions in a short and precise manner, without too much sugarcoating or dancing around.&lt;/p&gt;




&lt;h2&gt;
  
  
  Engineering is Part of Creation
&lt;/h2&gt;

&lt;p&gt;There's a real difference between the two. Creation is much broader term. engineering is part of the creation process. It's also part of maintenance, debugging, refactoring, and most of what engineers actually spend their days doing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7t681uth32jlzai5iv3v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7t681uth32jlzai5iv3v.jpg" alt="Diagram" width="502" height="550"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So the question worth asking is: during the creation process, who does the engineering? You? Your coding agent? Both of you?&lt;/p&gt;

&lt;h2&gt;
  
  
  Definitions Matter Here, Critically
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Vibe Coding
&lt;/h3&gt;

&lt;p&gt;You write a prompt and hand it to the AI. &lt;strong&gt;You don't edit the code and you don't review it.&lt;/strong&gt; You might not know the first thing about programming and still ship something.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-Assisting
&lt;/h3&gt;

&lt;p&gt;AI-generated, human-reviewed. The AI writes all of it, you read all of it. &lt;strong&gt;THIS IS NOT VIBE CODING&lt;/strong&gt;, it takes enough skill to tell good code from bad.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI-assisted
&lt;/h3&gt;

&lt;p&gt;You and the AI write the code together, and you're the one driving. AI gives you speed, a second opinion, and the edge cases you'd have missed. &lt;strong&gt;ALSO NOT VIBE CODING&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where This is Going
&lt;/h2&gt;

&lt;p&gt;The trend is toward more semantics and more abstraction. It's been that way since assembly. Vibe coding is the next step on that line, and it will keep taking over more of the work. Maybe one day the job is 95% writing prompts, and to be honest, I'll welcome it, that makes my life easier too.&lt;/p&gt;

&lt;p&gt;But the question right now is whether we're ready to build financial systems, health apps, and anything else touching sensitive data without analyzing the code.&lt;/p&gt;

&lt;p&gt;We're not. Doing it anyway to prove your point will cause absolute chaos.&lt;/p&gt;

&lt;p&gt;The line I'd draw:&lt;/p&gt;

&lt;p&gt;Building something for yourself, for fun? Vibe code all of it. It's genuinely a good time.&lt;/p&gt;

&lt;p&gt;Building something real, something that processes people's personal data, handles money, and turns a profit and vibe coding it from start to finish? That tells me one of three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;You're not willing to spend two to four weeks learning the absolute basics of coding, security, and best practices.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You don't care about the quality of your own product, and ultimately other people's personal data and security.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You're not curious about how any of it works under the hood. And if you're calling yourself an engineer, you should be eager to understand the mechanics of software engineering and coding.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All three happen constantly now, and that's the sad part.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Actually Do?
&lt;/h2&gt;

&lt;p&gt;I've been a software engineer for ten years. Even so, when I need to build something in a language I'm not fluent in, I still spend a day or two on the language reference, the docs, the basic mechanics, enough that I can understand what the AI produces.&lt;/p&gt;

&lt;p&gt;Then I review everything it generates and ask so many follow-up questions that &lt;strong&gt;I probably spend more tokens interrogating the code than creating the project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Every strong engineer I know works this way. We use AI extensively, every single day. We also take everything it gives us with a grain of salt.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2oc2s9nt7r1ijuwgy8xq.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2oc2s9nt7r1ijuwgy8xq.jpeg" alt="A Grain of Salt Next to a Keyboard and Rubber Duck" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So what's stopping you from doing the same?&lt;/p&gt;

&lt;p&gt;We'll get to the point where you can let go of the steering wheel. We're not there yet. Keep holding the wheel to make sure you don't go off the road.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this write-up? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>coding</category>
      <category>development</category>
    </item>
    <item>
      <title>Show Me the Article You're Most Proud Of And I'll Read Every Single One of Them</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Thu, 10 Sep 2026 19:30:37 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/show-me-the-article-youre-most-proud-of-and-ill-read-every-single-one-of-them-1l53</link>
      <guid>https://dev.to/georgekobaidze/show-me-the-article-youre-most-proud-of-and-ill-read-every-single-one-of-them-1l53</guid>
      <description>&lt;h2&gt;
  
  
  I Write More Than I Read
&lt;/h2&gt;

&lt;p&gt;I used to read a lot on DEV. Then I started writing my own articles, and somewhere along the way I stopped reading nearly as much as I used to.&lt;/p&gt;

&lt;p&gt;I want to fix that. There are so many good writers on here that it's genuinely overwhelming, and I'd rather be reading them than not.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Rules
&lt;/h2&gt;

&lt;p&gt;Doesn't matter if you're a veteran tech writer or you published your first post last week.&lt;/p&gt;

&lt;p&gt;👉 Pick one article you're most proud of. &lt;strong&gt;Just one.&lt;/strong&gt; It doesn't have to be the community favorite or the one with the most reactions, pick the one you love the most.&lt;br&gt;
👉 Drop the link in the comments.&lt;br&gt;
👉 Optional: tell me why it's special to you. One paragraph is plenty.&lt;/p&gt;

&lt;p&gt;I'll read it and give you my honest feedback. I promise! 🤝&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Bother
&lt;/h2&gt;

&lt;p&gt;Maybe your favorite post never got the attention you thought it deserved. Maybe it got plenty, and you'd just like an excuse to share it again.&lt;/p&gt;

&lt;p&gt;Either way, it's sitting in your archive and nobody's read it in months. This is a chance to put it back in front of people.&lt;/p&gt;

&lt;p&gt;And it works both ways, read what other people drop in the comments. That's the whole point.&lt;/p&gt;

&lt;p&gt;Showcase your work, appreciate everyone else's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's build a hall of fame of DEV's best work! 🌟&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>community</category>
      <category>discuss</category>
      <category>showdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>The Same Day, 180 Times: How Does the Unglamorous Machinery of Locking In Actually Work?</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 06 Sep 2026 17:36:04 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/the-same-day-180-times-how-does-the-unglamorous-machinery-of-locking-in-actually-work-4n0l</link>
      <guid>https://dev.to/georgekobaidze/the-same-day-180-times-how-does-the-unglamorous-machinery-of-locking-in-actually-work-4n0l</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Inspiration is for amateurs, the rest of us just show up and get to work."&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;em&gt;— Chuck Close&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;This Wasn't Supposed to Be the Next Article&lt;/li&gt;
&lt;li&gt;
What Locking In Actually Means

&lt;ul&gt;
&lt;li&gt;The Longer You Practice Consistency, The More Consistent You Get&lt;/li&gt;
&lt;li&gt;The Rule of 100: The Compounding Effect of Life&lt;/li&gt;
&lt;li&gt;Vacations Happen Roughly Once Every Six Months&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
It's Day One of 180. So What Do You Do?

&lt;ul&gt;
&lt;li&gt;Just Plan Things&lt;/li&gt;
&lt;li&gt;Sharpen Your Tools&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Now That You're Well Into The Camp Everything Matters

&lt;ul&gt;
&lt;li&gt;The System Is the Point&lt;/li&gt;
&lt;li&gt;Same Hours, Every Day&lt;/li&gt;
&lt;li&gt;Clock Out Twice&lt;/li&gt;
&lt;li&gt;Put Your Phone Away&lt;/li&gt;
&lt;li&gt;The Body Is Part of the System&lt;/li&gt;
&lt;li&gt;Day Five Is Usually When It Turns&lt;/li&gt;
&lt;li&gt;Checkpoints Get You Through the Gap&lt;/li&gt;
&lt;li&gt;Recharge on Purpose&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;How to Deal With Bad Days&lt;/li&gt;
&lt;li&gt;Commit to More Than One Thing, Just Not at Once&lt;/li&gt;
&lt;li&gt;
My Suggestion to You

&lt;ul&gt;
&lt;li&gt;Congratulations&lt;/li&gt;
&lt;li&gt;Start Slow&lt;/li&gt;
&lt;li&gt;Lonesome Is a State of Mind&lt;/li&gt;
&lt;li&gt;By The Way&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  This Wasn't Supposed to Be the Next Article
&lt;/h2&gt;

&lt;p&gt;It's 6:00 AM on a Sunday. I haven't had coffee yet, and I thought about fixing that before I started. I didn't. The longer I do this, the more I think the pre-coffee excuse is just a licence to do something badly and call it circumstance.&lt;/p&gt;

&lt;p&gt;I hadn't planned to write this one either. My last piece on this topic &lt;a href="https://dev.to/georgekobaidze/a-new-personal-best-what-six-months-of-locking-in-can-do-p3k"&gt;A New Personal Best: What Six Months of Locking In Can Do&lt;/a&gt; got more engagement than I ever expected, which included praise and a handful of healthy critiques. I had a stack of technical articles queued up behind it. They can wait.&lt;/p&gt;

&lt;p&gt;The questions were mostly the same question, asked different ways. That article was a list of outcomes: two hackathon wins, a new role, a charity donation, thirteen articles. What people wanted was the part I left out:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the days actually looked like.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So that's what this is. The routine, written down as it ran. Roughly the same day, 180 times. It is far less interesting than the results made it look. But if you're anything like me, you love to hear about the process even more than the results.&lt;/p&gt;

&lt;p&gt;Let's just get it done.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Locking In Actually Means
&lt;/h2&gt;

&lt;p&gt;Locking in sounds dramatic, and it isn't. I don't lock myself up in a room for six months and I don't go up a mountain to think about nothing but work while meditating for 12 hours a day. That stuff ain't for me.&lt;/p&gt;

&lt;p&gt;Quite the contrary.&lt;/p&gt;

&lt;p&gt;These are the stretches when I'm most active socially and most active on my own projects at the same time.&lt;/p&gt;

&lt;p&gt;Strip the phrase down and it's ordinary: sustained, hyperfocus on a goal and on the process that gets you to it. The only unusual part is how long I hold it. Six months. Quite a stretch, huh?&lt;/p&gt;

&lt;p&gt;There are reasons it has to run that long.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Longer You Practice Consistency, The More Consistent You Get
&lt;/h3&gt;

&lt;p&gt;That sounds obvious. The interesting part is why it happens.&lt;/p&gt;

&lt;p&gt;Your brain has that weird and useful feature to handle almost anything you hand it repeatedly. That includes things you actively disliked at the start: training, sitting with a hard problem, running errands, even organizing your desk. Do them often enough and they stop costing what they used to. Some of them start pulling at you instead.&lt;/p&gt;

&lt;p&gt;The mechanism isn't mysterious. Repetition makes a thing part of your baseline, and the baseline is what your brain treats as normal. Once something is in there, skipping it doesn't feel like a day off. It feels like a day with something missing from it.&lt;/p&gt;

&lt;p&gt;Here's roughly how that went for me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One week:&lt;/strong&gt; A good start and nothing more. Nothing is in the system yet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One month:&lt;/strong&gt; It's getting easier. You still have to decide to do it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Three months:&lt;/strong&gt; A habit. You notice when you skip it. It's significant.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Six months:&lt;/strong&gt; Part of you. Skipping it costs more than doing it, and your brain actively protests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two things amplify all of this when there's a reward waiting at the end: &lt;strong&gt;motivation and anticipation&lt;/strong&gt;.&lt;br&gt;
They aren't the same force and confusing them is why people stall around month two.&lt;/p&gt;

&lt;p&gt;Motivation starts you. It's whatever you're after: a skill, money, connections, a promotion, recognition, or everything together.&lt;/p&gt;

&lt;p&gt;Anticipation carries you. Same reward, different job. Motivation is spent the moment you begin, anticipation is what you run on for the six months after that.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Rule of 100: The Compounding Effect of Life
&lt;/h3&gt;

&lt;p&gt;I borrowed this from &lt;a href="https://en.wikipedia.org/wiki/Jesse_Itzler" rel="noopener noreferrer"&gt;Jesse Itzler&lt;/a&gt;, an American entrepreneur, who's also one of my favorite authors.&lt;/p&gt;

&lt;p&gt;The rule of 100 basically means the following:&lt;/p&gt;

&lt;p&gt;If you spend 100 hours a year on any discipline, about 17 minutes a day, you'll end up better than 95% of the world's population at that discipline.&lt;/p&gt;

&lt;p&gt;Pick any discipline you want: coding, playing basketball, playing guitar, boxing, riding a bike. It doesn't really matter which one.&lt;/p&gt;

&lt;p&gt;If you practice it for 17 minutes a day, within a year you'll be more skilled than most people in the world. This doesn't mean you'll become a boxing champion, an NBA player, or a professional software engineer. But you'll be pretty decent.&lt;/p&gt;

&lt;p&gt;Now imagine what you can achieve if you do something for hours a day. You can reach a professional level in a few years if you stay consistent. But keep in mind: consistency isn't measured in time alone. &lt;strong&gt;The hours only count if you put real effort into them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is called the compounding effect of life.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vacations Happen Roughly Once Every Six Months
&lt;/h3&gt;

&lt;p&gt;On average, people take a big vacation about once every six months, and I'm no different. When I take one, I always travel somewhere to clear my head. Traveling after six months of locking in is one of the most rewarding feelings there is. You know you got through that "six-month camp," you have results you're proud of, and now you're out in your favorite countries and cities. Oh gosh, there's nothing like it.&lt;/p&gt;

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

&lt;p&gt;If a trip falls inside a lock-in period, I try not to step away from the work completely. Even without my laptop, I'll research things on my phone on a plane or a train, where there's plenty of time anyway.&lt;/p&gt;




&lt;h2&gt;
  
  
  It's Day One of 180. So What Do You Do?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Just Plan Things
&lt;/h3&gt;

&lt;p&gt;Nothing dramatic. There's no starting gun. Day one is for preparation.&lt;/p&gt;

&lt;p&gt;I spend it on prerequisites: a rough map of what I'm doing over the next six months, and roughly when. It's the dullest day of the entire stretch and skipping it is the most expensive mistake on offer.&lt;/p&gt;

&lt;p&gt;Here's the thing about that map: &lt;strong&gt;it's wrong&lt;/strong&gt;. Some things slip, others land early. Even the most disciplined person alive doesn't hit the schedule they drew on day one, and I never have either.&lt;/p&gt;

&lt;p&gt;That's fine, because the dates were never the point.&lt;/p&gt;

&lt;p&gt;You're not trying to predict when you'll reach the goal, or even its sub-goals. You're deciding what you'll do every single day, repeatedly to get closer to it. &lt;strong&gt;Plan the input, not the outcome.&lt;/strong&gt; Input is something that you actually control, so make it precise. If you say: &lt;em&gt;"I'm going to spend 4 hours a day on this project"&lt;/em&gt;, &lt;strong&gt;mean it!&lt;/strong&gt; Making claims you don't follow through on will cost you trust in your own word. &lt;strong&gt;And there's nothing worse than not trusting yourself.&lt;/strong&gt; If you can't count on yourself, how can anyone (your team, your boss, your friends, your loved ones) count on you?&lt;/p&gt;

&lt;p&gt;So spend day one planning. If you're building something, decide which features come first, then break the work down until you're left with pieces small enough to estimate honestly. Usually there's more than one thing running at once - a project, articles, open source, competitions, whatever else you've signed up for. Deciding roughly when you'll do what is what stops those from collapsing into each other.&lt;/p&gt;

&lt;p&gt;The worse alternative is working on whatever you feel like that evening. And whatever you feel like, six months out, adds up to nothing. That'll just waste your time. Don't do that to yourself.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sharpen Your Tools
&lt;/h3&gt;

&lt;p&gt;Take a look around your workspace. Yes, right now. What does it look like? Messy or organized?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmhv1gj7gtedh14a7buz7.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmhv1gj7gtedh14a7buz7.jpeg" alt="Messy Desk" width="800" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If it's organized, congratulations, that box is already ticked.&lt;/p&gt;

&lt;p&gt;If it's messy, start there. Discipline isn't just saying "I'm going to review three pull requests today."&lt;/p&gt;

&lt;p&gt;A few weeks ago, when I started my current six-month lock-in period, do you know what the very first thing I did was?&lt;br&gt;
I washed my car. Then I cleaned my laptops and my keyboard. Sounds weird, right? It does, but it also works for me like a charm.&lt;/p&gt;

&lt;p&gt;Real discipline is the kind that's embedded in your whole system, your life, not just your projects. The broader it is, the more sustainable it is and the more it carries into everything else you do.&lt;/p&gt;

&lt;p&gt;If your car is full of garbage, soda cans and old receipts and your living room has last month's pizza boxes and empty bottles scattered around it, there's a good chance you're not consistent in your repositories either. Best practices, timely reviews, pruning dead branches and stale pull requests, all of it tends to be sloppy for the same reason. Not because you don't know better, but because discipline isn't a thing you switch on when the editor opens, or not even when your eyes open in the morning.&lt;/p&gt;

&lt;p&gt;So start with the basics. You'll be surprised how much it changes your attitude toward the actual work. You'll feel proud of yourself, and you'll trust yourself more.&lt;/p&gt;

&lt;p&gt;Once that's done, get specific. For example, if you're building a new app, make sure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every tool installed, configured, and updated&lt;/li&gt;
&lt;li&gt;Every dependency installed and resolving cleanly&lt;/li&gt;
&lt;li&gt;The latest version of your framework. You don't want to start on an old one unless there's a specific reason for it&lt;/li&gt;
&lt;li&gt;A repository that's ready on day one: README, license, .gitignore, branch naming, branch protection&lt;/li&gt;
&lt;li&gt;Formatting and linting rules committed, so you're not arguing with your editor in week three&lt;/li&gt;
&lt;li&gt;CI running green on an empty commit, before there's anything to break&lt;/li&gt;
&lt;li&gt;Secrets and environment variables sorted, documented, and out of source control&lt;/li&gt;
&lt;li&gt;Somewhere to track work: a board, issues, whatever you'll actually open (I usually use GitHub projects)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And many other things.&lt;/p&gt;

&lt;p&gt;Every item on that list is a small piece of friction you're removing now, while setting things up is still interesting, so that it can't stop you later. Because it will be day 56 at eleven at night, you'll have forty minutes and no energy, and the difference between doing something and doing nothing will come down to whether the build runs on the first try. Clear the obstacles while you're still enthusiastic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Now That You're Well Into The Camp Everything Matters
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The System Is the Point
&lt;/h3&gt;

&lt;p&gt;When I'm in the middle of a camp like this, which I am right now, the only thing that matters is following the system. Not feeling good about it. Not being perfect at it. Following it.&lt;/p&gt;

&lt;p&gt;You will not be perfect. Some days are slow, others are faster. Some days you'll do half of what you planned, and some days you'll do none of it. That's fine. A system you follow 80% of the time for six months will beat a system you follow perfectly for nine days and then abandon. The goal isn't a clean record. It's that the thing keeps running while you're tired, bored, annoyed, or unconvinced.&lt;/p&gt;

&lt;p&gt;One rule that's worth more than the rest: never miss twice. One missed day is noise. Two missed days is the new pattern - a very very bad bad pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Same Hours, Every Day
&lt;/h3&gt;

&lt;p&gt;Wake up at the same time. Go to sleep at the same time. Work in the same windows. It sounds joyless and it's the single highest-leverage thing on this list, because a fixed schedule means you stop spending willpower on when. The decision is already made, so all you have to do is show up.&lt;/p&gt;

&lt;p&gt;Find out how long you can actually concentrate before the quality drops, not how long you can sit at a desk, how long you can genuinely hold a problem in your head. For most people it's shorter than they'd like to admit. Build your blocks around that real number instead of the one you wish you had and then work on stretching it. &lt;strong&gt;Attention is trainable&lt;/strong&gt;, and it pays out in everything else you do.&lt;/p&gt;

&lt;p&gt;Protect the first block of the day for the hardest thing. Whatever gets your best hours is what actually gets done. And once you've gotten over with that hard part, the rest of the day is almost like coasting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Clock Out Twice
&lt;/h3&gt;

&lt;p&gt;Draw a hard line between your day job and your personal work. Not a soft one, a hard one, with a time on it. I know, it's much harder than it sounds, I'm speaking from experience, but it's not impossible. It'll actually make way more productive on both sides of the fence.&lt;/p&gt;

&lt;p&gt;You also need a marker for done. Decide in advance what finishing looks like today, and when you hit it, stop. Being unable to stop is not discipline, it's the thing that ends six-month runs early.&lt;/p&gt;

&lt;p&gt;Do one thing in a given time. Only one.&lt;/p&gt;

&lt;p&gt;I've watched people brag about working on four or five things at once, and I used to be one of them. Here's what I eventually understood: doing five things simultaneously mostly means screwing up all five things simultaneously, because none of them get the quality they need.&lt;/p&gt;

&lt;p&gt;There's a real cost to task switching, too. Every jump between contexts leaves part of your attention stuck on the last thing, and you pay that tax on every single switch. It doesn't feel like a cost, which is exactly what makes it expensive. Ten context switches an hour and you're already exhausted without getting any quality work done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Put Your Phone Away
&lt;/h3&gt;

&lt;p&gt;It goes without saying that you should stay the hell away from social media. I mean it, put the phone down.&lt;/p&gt;

&lt;p&gt;I don't think most people have honestly reckoned with what those stupid reels do to their ability to sit with a hard problem. You train your attention with whatever you feed it, and if you feed it seven-second clips all evening, then sit down to debug something that needs forty uninterrupted minutes, you're going to find the machinery doesn't work anymore. It isn't that you've lost the ability. It's that you've spent months practicing the exact opposite "skill".&lt;/p&gt;

&lt;p&gt;The fix is boring and it's mechanical: get the apps off the phone, or just don't touch the phone unless you absolutely need to. Willpower is not a strategy here, and you're not competing only against your own laziness. You're competing against companies who have spent billions figuring out how to win this specific fight.&lt;/p&gt;

&lt;p&gt;Think about how much pointless content you consume per day and how much great content you could've actually produce if you had used that time productively.&lt;/p&gt;

&lt;p&gt;I'm not saying cut it out entirely. I still watch videos to keep up with things I like during breaks and over lunch. But there's a line and it isn't blurry. When I sit back down, the phone is done for the next block.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Body Is Part of the System
&lt;/h3&gt;

&lt;p&gt;For me this was never only about the hours at the desk. The rest of your life either supports the goal or quietly undermines it.&lt;/p&gt;

&lt;p&gt;Think like a professional athlete.&lt;/p&gt;

&lt;p&gt;Sleep properly. You'll be tired at the end of every day and that's normal, but tired and under-slept aren't the same thing. Sleep is where the recovery actually happens and it's the first thing people sacrifice when they're behind. It's also the worst possible thing to sacrifice, because everything you're trying to do runs on the organ that sleep repairs - your brain.&lt;/p&gt;

&lt;p&gt;I used to stay up all night or two nights in a row, writing code, but it'd take 2 full days to recover after from that hardcore session, which isn't productive.&lt;/p&gt;

&lt;p&gt;Eat like it matters. It affects your thinking more than you'd expect. Junk food, sugar, fat, carbs don't just make you slower physically, they make the afternoons foggy, and foggy afternoons are where your six months quietly leak away.&lt;/p&gt;

&lt;p&gt;And obviously, stay away from alcohol and cigs. Not only because they'll cost you a productive evening, but because they'll cost you the brain and the body that your own life depends on. Well, unless you want to destroy both, your brain and body, for some reason.&lt;/p&gt;

&lt;p&gt;Move most days, preferrably every day. It doesn't have to be hard or complicated. Walking outside, or an hour on a treadmill, is enough. It's fine to do the bare minimum if being athlete-level fit isn't your goal. It pays back in ways that aren't obvious. Better sleep, steadier energy, fewer bad afternoons, and a real confidence boost that comes from doing a moderately unpleasant thing that most people skip.&lt;/p&gt;

&lt;p&gt;None of this is optimization for its own sake. It's maintenance on the machine that has to run for 180 days.&lt;/p&gt;

&lt;h3&gt;
  
  
  Day Five Is Usually When It Turns
&lt;/h3&gt;

&lt;p&gt;Here's the part nobody warns you about.&lt;/p&gt;

&lt;p&gt;Day one is great. You're excited, the plan is fresh, you have all the energy in the world. &lt;/p&gt;

&lt;p&gt;Day two, slightly less. &lt;/p&gt;

&lt;p&gt;By day five you absolutely hate it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F644xjhjbu9mwlolrzeol.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F644xjhjbu9mwlolrzeol.png" alt="Cowboy Riding a Carriage" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's not a sign you picked the wrong goal. The goal is fine. That's just what motivation does, it's a starting force, and it wears off.&lt;/p&gt;

&lt;p&gt;The problem is that this happens before discipline has had time to develop, so for a couple of weeks you're in a gap with no motivation left and no habit yet to carry you. That gap is where almost everyone quits. I've quit there myself a few times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fka3d35wq7u10x3k53ez4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fka3d35wq7u10x3k53ez4.png" alt="Motivation vs. Discipline" width="799" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Checkpoints Get You Through the Gap
&lt;/h3&gt;

&lt;p&gt;The technique that worked for me was scheduled checkpoints. Every two weeks, on a Monday, I'd stop and look at what's actually happened.&lt;/p&gt;

&lt;p&gt;Two things make it work. First, you look at the record instead of the feeling. The feeling on day twelve is "I'm getting nowhere." The record says you shipped four things, wrote 2 articles and the record is right. That's why it's worth keeping a rough log as you go, a checkpoint with no data is just a mood.&lt;/p&gt;

&lt;p&gt;Second, judge yourself on what you did, not on what it produced. Results arrive on their own schedule and mostly late. Whether you did the work is knowable today.&lt;/p&gt;

&lt;p&gt;Then treat the checkpoint as a small restart: readjust the plan, cut what isn't working, remind yourself what the end goal actually is, and go again. You keep doing that until the day you notice you don't need the checkpoints anymore, because the thing has become who you are. Now you're a disciplined guy or a girl.&lt;/p&gt;

&lt;p&gt;That's when it stops being hard.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recharge on Purpose
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flsa7twfkyr3ytk34xpab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flsa7twfkyr3ytk34xpab.png" alt="A Cowboy Taking Rest" width="799" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You have to let the system cool down every once in a while. Pick a day, let's say once every two weeks, or once a week if you need it, where you deliberately move slowly or do nothing at all. I mean the personal work, obviously. I'm not telling you to take the day off from your job.&lt;/p&gt;

&lt;p&gt;Spend that day on something you genuinely enjoy. This matters more than it sounds. If you don't feel like playing video games, don't play them just for the sake of "taking a break." If you don't feel like going out and socializing, don't go out because someone told you that's what fun looks like. It's fine to decline a casual invitation, the real friends will understand.&lt;/p&gt;

&lt;p&gt;One warning, though: make sure that day doesn't quietly turn into three. That's a new pattern forming, and it needs to be spotted and terminated early. One day restores your momentum. Three days end it.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Deal With Bad Days
&lt;/h2&gt;

&lt;p&gt;We've talked a lot about discipline and how it answers almost everything. But some days are just awful. Everyone gets them. Some stretches, most days are awful.&lt;/p&gt;

&lt;p&gt;I had one recently.&lt;/p&gt;

&lt;p&gt;Back in March I won the &lt;a href="https://dev.to/devteam/congrats-to-the-github-copilot-cli-challenge-winners-2240"&gt;GitHub Copilot CLI challenge&lt;/a&gt;, came first out of more than 400 participants with this project: &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0"&gt;Metal Birds Watch&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hlna5952bj9009osn2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8hlna5952bj9009osn2f.png" alt="Metal Birds Watch" width="800" height="409"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's still the biggest thing I've ever won, and it's special to me for a second reason: I used it to make a significant donation to charity.&lt;/p&gt;

&lt;p&gt;One of the prizes was a ticket to &lt;a href="https://githubuniverse.com/" rel="noopener noreferrer"&gt;GitHub Universe&lt;/a&gt; in San Francisco this October. I've been looking forward to it all year.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgfwuvbzn94chhg9a0ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvgfwuvbzn94chhg9a0ju.png" alt="GitHub Universe" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I just found out I'm not going to be able to go. The reason is completely outside my control.&lt;/p&gt;

&lt;p&gt;It sucks, right?&lt;/p&gt;

&lt;p&gt;It absolutely does. It especially sucks when you've done everything right and the thing standing in the way isn't yours to fix. That win was one of the high points of my life. This is one of the sharpest disappointments of it.&lt;/p&gt;

&lt;p&gt;But that's life. It's unfair, there's nothing new about that, and if I sit here and dwell on it the only thing I'll actually change is my own state of mind - for the absolute worse.&lt;/p&gt;

&lt;p&gt;So here's what happened on the evening I found out: I opened my editor and worked my a$$ off on one of my personal projects. Not heroically, not particularly well. I just did the block that was on the schedule.&lt;/p&gt;

&lt;p&gt;That's the whole argument for the system, and it's why this section isn't a detour from the rest of the article. On a good day, discipline is a nice-to-have, you'd have done the work anyway, because you wanted to. On a day like that one, it's the only thing standing between you and a week you don't get back. The routine doesn't ask how your news went. It just says it's eight o'clock.&lt;/p&gt;

&lt;p&gt;Something didn't work out for you? Fine. Try again, or try something else. Life is unfair sometimes, and it's also full of opportunities you haven't looked at yet. But don't wait until you feel better before you start moving again. Moving again is what makes you feel better.&lt;/p&gt;




&lt;h2&gt;
  
  
  Commit to More Than One Thing, Just Not at Once
&lt;/h2&gt;

&lt;p&gt;If you want to give the whole six months to a single thing because of its size or importance, go for it. But it helps to have somewhere else to put your attention when you're sick of staring at the same problem for the fourth day running and it's better if that somewhere is fundamentally different from the main work.&lt;/p&gt;

&lt;p&gt;Right now I've got the biggest personal project I've ever attempted. Realistically it's five or six months just to reach a basic, shippable version (or so I hope). Alongside it I'm still writing articles, recording videos, and entering challenges. And last but definitely not least, I've started learning German on my own, no teacher, no class, nobody. My argument is that I'm a software engineer and I know a thing or two about learning languages, I'm hoping to have the basics in about a year. So far I'm loving it.&lt;/p&gt;

&lt;p&gt;That sounds like it contradicts what I said earlier about doing one thing at a time. It doesn't, and the distinction is worth being precise about: multiple commitments, never simultaneous ones. Nothing on that list ever shares an hour with anything else on it. They share a week. That's the difference between variety and multitasking, and it's the whole game.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;So allocate days, not attention.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A lock-in period can also contain smaller lock-in periods inside it. You block off a week or two for something specific, finish it, and return to whatever you were doing before.&lt;/p&gt;

&lt;p&gt;Say you're deep in your main project and DEV Community posts a challenge you can't turn down. You pause the main work, lock in on the challenge for a couple of weeks, then lock back into the primary thing. It works like a function call stack, the last thing you pushed is the first thing that gets finished and then you unwind back down to where you were. LIFO.&lt;/p&gt;

&lt;p&gt;The catch is the same one you'd recognize in code. A stack only works if the frames actually return. Push something new on top every time a shinier thing appears and never pop any of it, and you don't have a system, you have a leak. Six months later there's nothing finished at the bottom of it.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Suggestion to You
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Congratulations
&lt;/h3&gt;

&lt;p&gt;If you've made it this far and you've read the whole thing, congratulations. This article turned out much longer than I anticipated, and reading it end to end in one sitting says something real about your attention span. That's not a throwaway compliment either, the ability to stay with something long after it stops being novel is the best predictor I know of whether you'll finish a six-month run or abandon it in week three.&lt;/p&gt;

&lt;h3&gt;
  
  
  Start Slow
&lt;/h3&gt;

&lt;p&gt;If you've never done anything like this, don't start at six months. Start at one, with something specific you want finished by the end of it. Then raise it to three. What you're really practicing is patience, attention, and the ability to finish what you started, those are real skills, and they can be trained like any other. Pull off three months and six is absolutely within reach. At that point it's just a decision.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lonesome Is a State of Mind
&lt;/h3&gt;

&lt;p&gt;This is actually a song by Djo - great song by the way. But the statement itself is also very true. Especially when it comes to this topic.&lt;/p&gt;

&lt;p&gt;Do it quietly. Tell nobody, or tell only the people closest to you. Two reasons for that. First, announcing a plan hands you a hit of almost the same satisfaction you'd get from actually doing the thing, you collect the congratulations up front, and the drive that was supposed to carry you leaks out through your own mouth.&lt;/p&gt;

&lt;p&gt;Second, very few people are going to come with you on a commitment this long. Be ready for that. If you're not a lone wolf type of person like I am, someone genuinely comfortable doing things alone, then you need to either find at least one person willing to run the same stretch alongside you, or get comfortable with the quiet.&lt;/p&gt;

&lt;p&gt;And finally, this isn't an F1 sprint race. It's the 24 Hours of Daytona, not an F1 sprint race. Nobody wins it in the first hour. You win it by still being on track when most of the field isn't.&lt;/p&gt;

&lt;h3&gt;
  
  
  By The Way
&lt;/h3&gt;

&lt;p&gt;This is also a song name this one's by Red Hot Chili Peppers. But it also fits the context.&lt;/p&gt;

&lt;p&gt;Speaking of F1. As I was writing this I realized I'd missed the race at Monza, Italy. Got so carried away that it went straight past me. It's fine, I'll watch the highlights.&lt;/p&gt;

&lt;p&gt;Let's get to that checkered flag!🏁&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this deep dive? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>community</category>
      <category>journey</category>
    </item>
    <item>
      <title>Backend Engineer (Me) Ships a Browser Game With One Unintentional System Requirement: My Monitor</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 09 Aug 2026 19:42:53 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/backend-engineer-me-ships-a-browser-game-with-one-unintentional-system-requirement-my-monitor-1ojd</link>
      <guid>https://dev.to/georgekobaidze/backend-engineer-me-ships-a-browser-game-with-one-unintentional-system-requirement-my-monitor-1ojd</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/bugsmash"&gt;DEV's Summer Bug Smash: Smash Stories&lt;/a&gt; powered by &lt;a href="https://sentry.io/" rel="noopener noreferrer"&gt;Sentry&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prefer Watching Instead?
&lt;/h2&gt;

&lt;p&gt;If reading isn't your thing, no worries, I've got you covered. You can watch the video below:&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/m1vRJxHabJw" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction: In What Universe Did I Think This Was a Good Idea?&lt;/li&gt;
&lt;li&gt;The Game&lt;/li&gt;
&lt;li&gt;The Game Loop&lt;/li&gt;
&lt;li&gt;The Game Physics&lt;/li&gt;
&lt;li&gt;It Worked on My Machine Goddammit&lt;/li&gt;
&lt;li&gt;Understanding the Root Cause&lt;/li&gt;
&lt;li&gt;The Fix: Delta Time&lt;/li&gt;
&lt;li&gt;
But There's a Catch: Not Everything Is Fixed With &lt;code&gt;× dt&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Pattern 1: Linear operations&lt;/li&gt;
&lt;li&gt;Pattern 2: Exponential decay&lt;/li&gt;
&lt;li&gt;Pattern 3: Lerp smoothing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Summary: The Three Patterns&lt;/li&gt;
&lt;li&gt;One More Thing: Re-tune Your Constants&lt;/li&gt;
&lt;li&gt;Pull Request&lt;/li&gt;
&lt;li&gt;The Takeaway&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction: In What Universe Did I Think This Was a Good Idea?
&lt;/h2&gt;

&lt;p&gt;It was a nice, calm day. Everything was going smoothly, I was just minding my own business.&lt;/p&gt;

&lt;p&gt;Out of nowhere, a notification from &lt;a class="mentioned-user" href="https://dev.to/jess"&gt;@jess&lt;/a&gt; popped up. And I see this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Good morning! Good afternoon! Good Evening!&lt;/p&gt;

&lt;p&gt;Welcome to our first DEV Weekend Challenge, a short focused challenge designed to fit into your weekend. Since submission window is tight, we've set the timing to ensure that no matter where you are in the world, you'll have the majority of your Saturday and Sunday to participate.&lt;/p&gt;

&lt;p&gt;Let's get started!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I don't know what's exactly wrong with me, but whenever I see a word "challenge", something clicks in my brain and it starts a multi-thousand thread process to think of an idea until the idea isn't generated. This time was no different. But in some ways, it really was quite different.&lt;/p&gt;

&lt;p&gt;Let me explain why. So here's my thinking process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OK I just have the weekend. 2 days tops, that's it. Well, sometimes just planning can take way more than that.&lt;/li&gt;
&lt;li&gt;I'm a full-stack engineer with extensive back-end background, so back-end is my primary comfort zone.&lt;/li&gt;
&lt;li&gt;Building something fun and flashy would be great, like a... browser game? Hell yeah!!! ... well, except, I ain't no game developer and I have never ever written a browser game.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;So I decided to build... drum rolls ... A BROWSER GAME!&lt;/p&gt;

&lt;p&gt;If you're not a technical person, a back-end developer building a browser game is an NFL player playing tennis.&lt;/p&gt;

&lt;p&gt;You already know this isn't gonna end well, don't ya?&lt;/p&gt;




&lt;h2&gt;
  
  
  The Game
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3mwy9c8nvyaflxc62dn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc3mwy9c8nvyaflxc62dn.png" alt="Game Screenshot" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You're probably wondering what kind of game I created. It's basically a driving simulator (well... kinda) - a synthwave 3D driving game where your DEV community articles appear as neon billboards along the endless highway. It fetches articles, stats, and things like that using the DEV Community by the username.&lt;/p&gt;

&lt;p&gt;If you'd like to give it a try before continuing, here are the relevant links:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sundaydevdrive.pilotronica.com/" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032"&gt;Submission article&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/georgekobaidze/sunday-dev-drive" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  The Game Loop
&lt;/h2&gt;

&lt;p&gt;Sunday DEV Drive is a browser game built on top of &lt;strong&gt;Three.js&lt;/strong&gt; - a JavaScript library that handles 3D rendering in the browser. The game runs entirely client-side: no server, no backend, no build step. Just HTML, JavaScript, and your DEV Community articles fetched from a public API.&lt;/p&gt;

&lt;p&gt;The game is built around a &lt;strong&gt;game loop&lt;/strong&gt;: a function that runs over and over, many times per second. On each iteration it does the same three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Read inputs&lt;/strong&gt; - is the player pressing the accelerator? Turning left?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update the world&lt;/strong&gt; - move the car, adjust the camera, apply physics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Draw the frame&lt;/strong&gt; - render everything to the screen&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the browser, the standard tool for this is &lt;code&gt;requestAnimationFrame&lt;/code&gt;. You give it a function, and the browser calls that function right before it repaints the screen — as fast as the display allows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "call me again next frame"&lt;/span&gt;

  &lt;span class="nf"&gt;updatePhysics&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;updateCamera&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;renderScene&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// start the loop&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like a flipbook. Each call to &lt;code&gt;animate()&lt;/code&gt; draws one page. The faster the pages flip, the smoother the motion looks. On a 60Hz monitor, the browser flips 60 pages per second. On a 165Hz monitor, 165 pages per second.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Game Physics
&lt;/h2&gt;

&lt;p&gt;The car's movement is simple Newtonian-ish math applied every frame, nothing exotic, just the kind of physics you vaguely remember from high school:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Throttle&lt;/strong&gt; → adds to the car's speed (acceleration)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt; → moves the car's position&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steering&lt;/strong&gt; → rotates the car's angle&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Friction&lt;/strong&gt; → slowly reduces speed when no input is held&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Camera&lt;/strong&gt; → smoothly follows the car from behind&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Simple stuff. Which is exactly why the bug hiding inside it was so easy to overlook.&lt;/p&gt;




&lt;h2&gt;
  
  
  It Worked on My Machine Goddammit
&lt;/h2&gt;

&lt;p&gt;I tested the game. Multiple times. Zero issues. The car moved naturally. Steering felt great. Acceleration was progressive. The brakes had a nice bite to them.&lt;/p&gt;

&lt;p&gt;Everything felt perfect.&lt;/p&gt;

&lt;p&gt;Well, until I tested it on another computer. Ladies and gentlemen, I need your attention, please: I don't care how certain you are that your code works:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ALWAYS TEST IT ON ANOTHER COMPUTER.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I decided to flex a little and show the game to my mom and brother. So I sent them the links.&lt;/p&gt;

&lt;p&gt;"Hey, check this out. I made a game."&lt;/p&gt;

&lt;p&gt;A few minutes later, they texted me back:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"The visuals are really good, but the car is barely moving. Is this by design?"&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Umm... whaddaya mean "barely moving?" I just tested it and it's fine. Are you sure you're pressing the gas?"&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I started troubleshooting.&lt;/p&gt;

&lt;p&gt;And troubleshooting.&lt;/p&gt;

&lt;p&gt;And troubleshooting some more.&lt;/p&gt;

&lt;p&gt;Nothing made sense.&lt;/p&gt;

&lt;p&gt;The controls were working. The game was running. There were no obvious errors. Yet somehow, on their machines, my beautifully engineered car had apparently decided to become a mobility scooter.&lt;/p&gt;

&lt;p&gt;I had no idea what was going on.&lt;/p&gt;

&lt;p&gt;So I did what any developer would do in this situation:&lt;/p&gt;

&lt;p&gt;I Googled&lt;br&gt;
I asked AI&lt;br&gt;
I stared at the code&lt;br&gt;
I sketched things out&lt;br&gt;
I questioned my architectural decisions.&lt;/p&gt;

&lt;p&gt;...&lt;/p&gt;

&lt;p&gt;I questioned my life choices.&lt;/p&gt;

&lt;p&gt;And then it just clicked.&lt;/p&gt;

&lt;p&gt;I had used the monitor's refresh rate as part of my movement calculations.&lt;/p&gt;

&lt;p&gt;Yep.&lt;/p&gt;

&lt;p&gt;My physics weren't actually frame-rate independent.&lt;/p&gt;

&lt;p&gt;My monitor was running at 165 Hz. Their monitor was running at 120 Hz.&lt;/p&gt;

&lt;p&gt;That's a 45 Hz difference.&lt;/p&gt;

&lt;p&gt;45 frames per second was enough to turn my perfectly drivable car into a perfectly drivable car, but in slow motion.&lt;/p&gt;

&lt;p&gt;The game wasn't broken on my machine. My monitor was secretly a system dependency.&lt;/p&gt;

&lt;p&gt;I had messed up... And badly.&lt;/p&gt;

&lt;p&gt;And now it was time to fix it.&lt;/p&gt;


&lt;h2&gt;
  
  
  Understanding the Root Cause
&lt;/h2&gt;

&lt;p&gt;My animate loop looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt; calls your function &lt;strong&gt;once per display refresh&lt;/strong&gt;. On my 165Hz monitor, that's 165 times per second. On a 120Hz monitor, 120 times.&lt;/p&gt;

&lt;p&gt;The problem: &lt;strong&gt;every physics value was per-frame, not per-second.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Look at what actually happens across different hardware:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frame Rate&lt;/th&gt;
&lt;th&gt;Updates/sec&lt;/th&gt;
&lt;th&gt;Effective speed/sec&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;165 fps (my machine)&lt;/td&gt;
&lt;td&gt;165&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.42 × 165 = 69.3&lt;/code&gt; ✅ feels right&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;120 fps&lt;/td&gt;
&lt;td&gt;120&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.42 × 120 = 50.4&lt;/code&gt; 🙂 73% of intended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60 fps&lt;/td&gt;
&lt;td&gt;60&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.42 × 60 = 25.2&lt;/code&gt; 😐 36% of intended&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30 fps&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;0.42 × 30 = 12.6&lt;/code&gt; 😩 18% of intended&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;I had unknowingly &lt;strong&gt;tuned the entire game for 165fps&lt;/strong&gt;. Everyone else was experiencing a completely different game.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Fix: Delta Time
&lt;/h2&gt;

&lt;p&gt;The solution is to measure the actual time elapsed between frames and use it to scale all physics updates. This is called &lt;strong&gt;delta time&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;THREE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Clock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;requestAnimationFrame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;clock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getDelta&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// real seconds since last frame&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;delta&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;         &lt;span class="c1"&gt;// normalized: 1.0 at 60fps baseline&lt;/span&gt;

  &lt;span class="c1"&gt;// Now multiply everything by dt&lt;/span&gt;
  &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;z&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;clock.getDelta()&lt;/code&gt; returns the real elapsed time in seconds. At 60fps that's &lt;code&gt;~0.0167s&lt;/code&gt;. &lt;br&gt;
At 165fps it's &lt;code&gt;~0.006s&lt;/code&gt;. &lt;br&gt;
At 30fps it's &lt;code&gt;~0.033s&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I multiply by 60 to normalize: &lt;code&gt;dt = delta * 60&lt;/code&gt;. This means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At 165fps → &lt;code&gt;dt ≈ 0.36&lt;/code&gt; (smaller steps per frame, same per second)&lt;/li&gt;
&lt;li&gt;At 60fps → &lt;code&gt;dt ≈ 1.0&lt;/code&gt; (baseline)&lt;/li&gt;
&lt;li&gt;At 30fps → &lt;code&gt;dt ≈ 2.0&lt;/code&gt; (larger steps per frame, same per second)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now the same distance is covered per second regardless of hardware:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frame Rate&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;dt&lt;/code&gt; per frame&lt;/th&gt;
&lt;th&gt;Movement per frame&lt;/th&gt;
&lt;th&gt;Movement per second&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;165 fps&lt;/td&gt;
&lt;td&gt;&lt;code&gt;≈ 0.36&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;speed × 0.36&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;speed × 60&lt;/code&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;60 fps&lt;/td&gt;
&lt;td&gt;&lt;code&gt;≈ 1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;speed × 1.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;speed × 60&lt;/code&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;30 fps&lt;/td&gt;
&lt;td&gt;&lt;code&gt;≈ 2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;speed × 2.0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;speed × 60&lt;/code&gt; ✅&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  But There's a Catch: Not Everything Is Fixed With &lt;code&gt;× dt&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Simple &lt;code&gt;* dt&lt;/code&gt; fixes linear operations. But a real game has more than just linear math. In this fix alone, there were three distinct patterns, each requiring a different approach.&lt;/p&gt;
&lt;h3&gt;
  
  
  Pattern 1: Linear operations
&lt;/h3&gt;

&lt;p&gt;The straightforward one. Any additive rate just gets multiplied by &lt;code&gt;dt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Frame-rate dependent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brakeForce&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;brake&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turnSpeed&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Frame-rate independent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;acceleration&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;throttle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;brakeForce&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;brake&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;car&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;angle&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;CAR&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;turnSpeed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're adding or subtracting a value per frame, multiply it by &lt;code&gt;dt&lt;/code&gt;. Done.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pattern 2: Exponential decay:
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;Math.pow(factor, dt)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This one is less obvious. When driving off-road, the car slows down using a multiplier applied each frame:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Frame-rate dependent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="mf"&gt;0.97&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// 3% drag per frame&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At 165fps this applies 3% drag 165 times per second. At 30fps, only 30 times. The off-road drag behaves completely differently depending on hardware.&lt;/p&gt;

&lt;p&gt;The naive fix: &lt;code&gt;carState.speed *= 0.97 * dt&lt;/code&gt; is &lt;strong&gt;wrong&lt;/strong&gt;. &lt;br&gt;
You can't linearly scale a multiplier. At &lt;code&gt;dt = 2&lt;/code&gt; you'd get &lt;code&gt;0.97 * 2 = 1.94&lt;/code&gt;, which would &lt;em&gt;accelerate&lt;/em&gt; the car instead of slowing it down.&lt;/p&gt;

&lt;p&gt;The correct fix uses exponentiation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Frame-rate independent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.97&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why does this work? Repeated multiplication is exponential decay. Consider what happens over one second:&lt;/p&gt;

&lt;p&gt;At 60fps (&lt;code&gt;dt = 1&lt;/code&gt;, 60 frames):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speed after 1s = speed × 0.97^60
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At 30fps (&lt;code&gt;dt = 2&lt;/code&gt;, 30 frames):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;speed after 1s = speed × (0.97^2)^30 = speed × 0.97^60 ✅ identical
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Math.pow(factor, dt)&lt;/code&gt; correctly scales the decay &lt;strong&gt;exponent&lt;/strong&gt; rather than the multiplier itself. The result over any given real-world time is always the same.&lt;/p&gt;

&lt;p&gt;The same pattern applies to smooth steering interpolation, instead of a fixed lerp coefficient, it uses the same exponential trick:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Frame-rate dependent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steerDir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// ✅ Frame-rate independent&lt;/span&gt;
&lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;steerDir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;carState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pattern 3: Lerp smoothing
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;1 - Math.pow(1 - alpha, dt)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The trickiest one. The camera smoothly follows the car using &lt;code&gt;lerp&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ Frame-rate dependent&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetPos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.08&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;lerp(target, alpha)&lt;/code&gt; moves &lt;code&gt;alpha&lt;/code&gt; percent of the remaining distance each frame. At 165fps the camera takes 165 small steps per second - buttery smooth. At 30fps it takes 30 steps - sluggish, visibly lagging.&lt;/p&gt;

&lt;p&gt;Again, &lt;code&gt;alpha * dt&lt;/code&gt; is the wrong fix. At &lt;code&gt;dt = 2&lt;/code&gt; you'd get &lt;code&gt;alpha = 0.16&lt;/code&gt;, which changes the feel, and at high enough values it would overshoot the target entirely.&lt;/p&gt;

&lt;p&gt;The correct formula:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Frame-rate independent&lt;/span&gt;
&lt;span class="nx"&gt;camera&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;position&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lerp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;targetPos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the intuition. After &lt;code&gt;n&lt;/code&gt; lerp steps at factor &lt;code&gt;alpha&lt;/code&gt;, the remaining distance is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remaining = (1 - alpha)^n
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make this time-independent, you want the same remaining distance after &lt;code&gt;n&lt;/code&gt; frames at &lt;code&gt;dt=1&lt;/code&gt; as after &lt;code&gt;n/2&lt;/code&gt; frames at &lt;code&gt;dt=2&lt;/code&gt;. The solution is to raise &lt;code&gt;(1 - alpha)&lt;/code&gt; to the power of &lt;code&gt;dt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;adjusted_alpha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="n"&gt;dt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Plugging in the numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At &lt;code&gt;dt = 1.0&lt;/code&gt; (60fps baseline): &lt;code&gt;1 - 0.8^1.0 = 0.200&lt;/code&gt; - original feel ✅&lt;/li&gt;
&lt;li&gt;At &lt;code&gt;dt = 0.36&lt;/code&gt; (165fps): &lt;code&gt;1 - 0.8^0.36 ≈ 0.083&lt;/code&gt; - smaller steps, same tracking speed ✅&lt;/li&gt;
&lt;li&gt;At &lt;code&gt;dt = 2.0&lt;/code&gt; (30fps): &lt;code&gt;1 - 0.8^2.0 = 0.360&lt;/code&gt; - larger steps, same tracking speed ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The camera now follows the car at the same real-world speed on any display.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: The Three Patterns
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Frame-rate dependent&lt;/th&gt;
&lt;th&gt;Frame-rate independent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Add/subtract per frame&lt;/td&gt;
&lt;td&gt;&lt;code&gt;value += rate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;value += rate * dt&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiply per frame (decay)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;value *= factor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;value *= Math.pow(factor, dt)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lerp toward target&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lerp(target, alpha)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;lerp(target, 1 - Math.pow(1-alpha, dt))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  One More Thing: Re-tune Your Constants
&lt;/h2&gt;

&lt;p&gt;After making physics frame-rate independent at a 60fps baseline, my original constants felt wrong, they were implicitly tuned for 165fps. I had to re-tune them for &lt;code&gt;dt = 1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before (accidentally tuned for 165fps)&lt;/span&gt;
&lt;span class="nx"&gt;maxSpeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;0.42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.0006&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;brakeForce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="mf"&gt;0.0015&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;friction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;0.00005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

&lt;span class="c1"&gt;// After (tuned for dt = 1 baseline at 60fps)&lt;/span&gt;
&lt;span class="nx"&gt;maxSpeed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;1.155&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;acceleration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.004538&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;brakeForce&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;   &lt;span class="mf"&gt;0.011344&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="nx"&gt;friction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;     &lt;span class="mf"&gt;0.000378&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're migrating an existing game, expect to spend time re-tuning. The physics will now be consistent across hardware, but the feel may shift from what you were used to on your own monitor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Pull Request
&lt;/h2&gt;

&lt;p&gt;Check out the pull request for this bug fix:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/georgekobaidze/sunday-dev-drive/pull/13/changes" rel="noopener noreferrer"&gt;Click Here to Check Out the Pull Request&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;If you're building a game or animation loop with &lt;code&gt;requestAnimationFrame&lt;/code&gt;, assume nothing about frame rate. Your players are on everything from 30fps integrated graphics to 240Hz gaming monitors.&lt;/p&gt;

&lt;p&gt;The fix isn't too complicated, but it's also not just "multiply everything by &lt;code&gt;dt&lt;/code&gt;." Linear operations, exponential decay, and lerp smoothing each need their own treatment. Get all three right and your game will feel identical whether it runs on a decade-old laptop or a high-refresh gaming rig.&lt;/p&gt;

&lt;p&gt;My car now drives the same on every machine. And I learned far more about frame-rate-independent math than I expected from what looked like a simple bug.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this deep dive? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>bugsmash</category>
    </item>
    <item>
      <title>Everyone Can Drive. Not Everyone Can Drive Well. Same Goes for AI-Assisted Coding</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Fri, 07 Aug 2026 22:01:11 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/everyone-can-drive-not-everyone-can-drive-well-same-goes-for-ai-assisted-coding-1oag</link>
      <guid>https://dev.to/georgekobaidze/everyone-can-drive-not-everyone-can-drive-well-same-goes-for-ai-assisted-coding-1oag</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;AI Didn't Remove the Skill, It Relocated the Skill&lt;/li&gt;
&lt;li&gt;Vibe Coding Is Easy. Doing It Well Isn't&lt;/li&gt;
&lt;li&gt;Everyone Can Drive. Not Everyone Can Drive Well.&lt;/li&gt;
&lt;li&gt;The same thing happens with AI&lt;/li&gt;
&lt;li&gt;It's Not Just About Prompting&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Lately, I've been writing a lot of technical-heavy articles and I noticed my articles got less popular.&lt;/p&gt;

&lt;p&gt;Well, what did I expect, technical articles can be a little... boooooring.&lt;/p&gt;

&lt;p&gt;So this time, let's take a different route. A lighter, more easy-going article, something less about complex concepts and more about sharing ideas, stories and perspectives.&lt;/p&gt;

&lt;p&gt;Time to win some readers' hearts back... But if you're a bad driver, you might hate me after that.&lt;/p&gt;




&lt;h2&gt;
  
  
  AI Didn't Remove the Skill, It Relocated the Skill
&lt;/h2&gt;

&lt;p&gt;I've heard people say that you don't need any skills to use AI to write code. &lt;br&gt;
❌ Errrrr... Wrong.&lt;/p&gt;

&lt;p&gt;Stick around. I'll explain it with a car-driving analogy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Vibe Coding Is Easy. Doing It Well Isn't
&lt;/h2&gt;

&lt;p&gt;Even if you're vibe coding, which is probably the most abstract way of creating software, you still need skills.&lt;/p&gt;

&lt;p&gt;Just a different kind of skills.&lt;/p&gt;

&lt;p&gt;You need to know how to use your tokens effectively so you can ship products faster, safer, with better quality, and without setting your wallet on fire.&lt;/p&gt;

&lt;p&gt;That's what I call "hypermiling your tokens".&lt;/p&gt;

&lt;p&gt;There are actual techniques for using your tokens intelligently rather than just throwing more of them at the problem. And those techniques are harder to master than you might think. Not because they're particularly complicated to understand, but because mastering them takes a ridiculous amount of experimentation.&lt;/p&gt;

&lt;p&gt;You try different approaches.&lt;/p&gt;

&lt;p&gt;Different prompts.&lt;/p&gt;

&lt;p&gt;Different models.&lt;/p&gt;

&lt;p&gt;Different levels of context.&lt;/p&gt;

&lt;p&gt;Different tasks.&lt;/p&gt;

&lt;p&gt;You screw things up (inevitable).&lt;/p&gt;

&lt;p&gt;You spend way too many tokens on something that should've taken half as many (also inevitable).&lt;/p&gt;

&lt;p&gt;You ask the model to fix something it didn't even break (probably with some attitude as well).&lt;/p&gt;

&lt;p&gt;Then you ask it to fix the fix (recursion anyone?).&lt;/p&gt;

&lt;p&gt;Then you realize the original code was fine (but your top-notch model has already inhaled your entire token budget).&lt;/p&gt;

&lt;p&gt;Congratulations. You just spent 200,000 tokens going in a circle.&lt;/p&gt;

&lt;p&gt;But, don't get discouraged, because you also started finding that sweet spot where you're getting the most output for the least amount of waste.&lt;/p&gt;

&lt;p&gt;And that's a skill. Anything that's earned through trial and failure, is a skill. Simple as that.&lt;/p&gt;




&lt;h2&gt;
  
  
  Everyone Can Drive. Not Everyone Can Drive Well.
&lt;/h2&gt;

&lt;p&gt;Who would you call a good, skilled driver?&lt;/p&gt;

&lt;p&gt;A skilled driver is someone who knows the rules and follows them, while also trying to be as efficient as possible.&lt;/p&gt;

&lt;p&gt;They don't overspeed.&lt;/p&gt;

&lt;p&gt;They park accurately, between the lines.&lt;/p&gt;

&lt;p&gt;They can drive inside a lane consistently.&lt;/p&gt;

&lt;p&gt;They use just enough fuel to get where they're going.&lt;/p&gt;

&lt;p&gt;They're predictable on the road.&lt;/p&gt;

&lt;p&gt;They care about the car.&lt;/p&gt;

&lt;p&gt;They care about other drivers.&lt;/p&gt;

&lt;p&gt;They don't floor the gas pedal from every single traffic light like they're in a drag race.&lt;/p&gt;

&lt;p&gt;And they don't slam on the brakes like they're playing Forza with a keyboard.&lt;/p&gt;

&lt;p&gt;A trully good driver knows how to be both safe and efficient. And they might even have no idea how engines or transmissions work and still be great drivers. I mean I'm not a mechanic, I've been driving for about 7 years now and I've never gotten a ticket, or maybe once, but that was unintentional and once I realized I'd crossed the wrong line, it was already late.&lt;/p&gt;

&lt;p&gt;And I've seen too many car mechanics who drive like they're gonna spawn again like an NPC after they crash.&lt;/p&gt;

&lt;p&gt;Now imagine the opposite.&lt;/p&gt;

&lt;p&gt;You go 30 km/h over the speed limit.&lt;/p&gt;

&lt;p&gt;Cut people off.&lt;/p&gt;

&lt;p&gt;Floor the accelerator the millisecond the light turns green.&lt;/p&gt;

&lt;p&gt;Brake so hard your passengers start reconsidering their life choices.&lt;/p&gt;

&lt;p&gt;Meanwhile, you're wearing out the car, burning fuel, and spending six times more money than you need to, while also being a danger to everyone around you.&lt;/p&gt;

&lt;p&gt;You're not a skilled driver. You're just driving recklessly.&lt;/p&gt;

&lt;p&gt;In fact, you probably have no idea what good driving actually is. What being a car operator actually is. &lt;strong&gt;What it actually means to be a human element in the equation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And that's an important distinction.&lt;/p&gt;




&lt;h2&gt;
  
  
  The same thing happens with AI
&lt;/h2&gt;

&lt;p&gt;Luckily, in vibe coding, being reckless with AI is considerably safer because, thankfully, your Claude session isn't going to rear-end a bus.&lt;/p&gt;

&lt;p&gt;The worst thing you're probably going to hit is your own token budget. But being reckless with tokens doesn't mean you're skilled.&lt;/p&gt;

&lt;p&gt;Everyone can be reckless. Whether you're driving or coding.&lt;/p&gt;

&lt;p&gt;The skill is knowing how to find that sweet spot between speed, quality, cost, and safety, and staying close to it while you're working.&lt;/p&gt;

&lt;p&gt;And that sweet spot isn't the same for every situation. Sometimes you need a huge amount of context, sometimes you don't.&lt;/p&gt;

&lt;p&gt;Sometimes a massive reasoning model is exactly what you need. Sometimes you're asking it to rename a variable and you've basically brought a semi-truck to the grocery store, not to deliver goods, but to buy them... for the day.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2befwpvoget0tpcljsgo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2befwpvoget0tpcljsgo.jpg" alt="Semi Taking Too Much Space" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sometimes you should let the AI explore the problem.&lt;/p&gt;

&lt;p&gt;Sometimes you should give it very strict boundaries.&lt;/p&gt;

&lt;p&gt;Sometimes you should ask it to implement something.&lt;/p&gt;

&lt;p&gt;Sometimes you should stop and think about the architecture yourself first.&lt;/p&gt;

&lt;p&gt;And sometimes the best prompt you can write is:&lt;/p&gt;

&lt;p&gt;"Don't change anything. Just tell me what's wrong."&lt;/p&gt;

&lt;p&gt;That's where the real skill starts showing up.&lt;/p&gt;




&lt;h2&gt;
  
  
  It's Not Just About Prompting
&lt;/h2&gt;

&lt;p&gt;I think this is where a lot of people misunderstand AI-assisted development.&lt;/p&gt;

&lt;p&gt;They reduce the skill to:&lt;/p&gt;

&lt;p&gt;"Can you write a good prompt?" - That's actually only one small part of it. You need to know how to scope a problem, how much context the model actually needs, when to split a task into smaller pieces.&lt;/p&gt;

&lt;p&gt;You need to recognize when the model is going down the wrong path and understand the output well enough to know whether it's actually good.&lt;/p&gt;

&lt;p&gt;And there's another skill: knowing when to stop. This is probably one of the most underrated parts of AI-assisted development (and driving too, some people just can't recognize huge red stop signs sometimes).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpg3nbu81evzkxhnmexnx.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpg3nbu81evzkxhnmexnx.jpg" alt="Person Not Stopping on a Stop Sign" width="799" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More tokens don't automatically mean better software.&lt;/p&gt;

&lt;p&gt;More iterations don't automatically mean better software.&lt;/p&gt;

&lt;p&gt;More context doesn't automatically mean better answers.&lt;/p&gt;

&lt;p&gt;Sometimes you're already 95% of the way there, and another twenty prompts are going to make things worse.&lt;/p&gt;

&lt;p&gt;You start optimizing things that don't matter or introduce abstractions nobody asked for.&lt;/p&gt;

&lt;p&gt;You refactor perfectly functional code because the model suddenly decided that your entire architecture needs to be "more scalable."&lt;/p&gt;

&lt;p&gt;You don't necessarily need to be the person manually turning every screw anymore. Not every driver should be a car mechanic or a mechanical engineer.&lt;/p&gt;

&lt;p&gt;You need to know which screws to turn, when to turn them, how hard to turn them, and when to stop touching things before you break something.&lt;/p&gt;

&lt;p&gt;And the better you become at working with AI, the less you'll think about "getting AI to write code" and the more you'll think about orchestrating a system that produces good software efficiently.&lt;/p&gt;

&lt;p&gt;Similarly to driving, you don't need to build the engine to drive the car. But you still need to know the rules of the road, you need to understand what the pedals do.&lt;/p&gt;

&lt;p&gt;You need to recognize when something sounds wrong. You need to know when to slow down and definitely need to know that flooring the accelerator doesn't make you a better driver (it actually makes you look like a terrible driver).&lt;/p&gt;

&lt;p&gt;The same applies to AI coding. Throwing more tokens at a problem isn't a skill nor is having the biggest context window or using the most powerful model for everything.&lt;/p&gt;

&lt;p&gt;Being able to consistently get the result you need with the least unnecessary wastem, while keeping quality and safety high, is. &lt;/p&gt;

&lt;p&gt;And the more time you spend operating around that sweet spot, the better you become at recognizing it.&lt;/p&gt;

&lt;p&gt;And that's why:&lt;/p&gt;

&lt;p&gt;"AI can write the code for me"&lt;/p&gt;

&lt;p&gt;doesn't mean:&lt;/p&gt;

&lt;p&gt;"I don't need skills anymore."&lt;/p&gt;

&lt;p&gt;The skill just moved.&lt;/p&gt;

&lt;p&gt;So yeah.&lt;/p&gt;

&lt;p&gt;Be efficient.&lt;/p&gt;

&lt;p&gt;Drive safe.&lt;/p&gt;

&lt;p&gt;Hypermile.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this deep dive? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>machinelearning</category>
      <category>programming</category>
    </item>
    <item>
      <title>TypeScript Just Got 10x Faster by Not Being TypeScript</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 02 Aug 2026 15:28:10 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/typescript-just-got-10x-faster-by-not-being-typescript-1n86</link>
      <guid>https://dev.to/georgekobaidze/typescript-just-got-10x-faster-by-not-being-typescript-1n86</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;Putting the 10x Claim Into Perspective&lt;/li&gt;
&lt;li&gt;
How Did We Get Here?

&lt;ul&gt;
&lt;li&gt;This Was an Extensive Evaluation&lt;/li&gt;
&lt;li&gt;The Priority Was Compatibility&lt;/li&gt;
&lt;li&gt;Why Not Rust?&lt;/li&gt;
&lt;li&gt;Why Not C#?&lt;/li&gt;
&lt;li&gt;Why Go Fit the Existing Compiler&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A Port, Not a Simple Translation&lt;/li&gt;
&lt;li&gt;
Where Does the Performance Come From?

&lt;ul&gt;
&lt;li&gt;Native Execution&lt;/li&gt;
&lt;li&gt;Parallel Processing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Memory Efficiency and Larger Projects&lt;/li&gt;
&lt;li&gt;
The Benchmarks

&lt;ul&gt;
&lt;li&gt;Memory Usage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The JavaScript API Trade Off&lt;/li&gt;
&lt;li&gt;
Is It Still TypeScript?

&lt;ul&gt;
&lt;li&gt;The F1 Analogy&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Large Companies Helped Test TypeScript 7&lt;/li&gt;
&lt;li&gt;Should You Upgrade?&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;At the end of March 2025, I published this article:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/go-ing-beyond-typescript-microsoft-picks-go-how-will-this-change-the-landscape-1p4h" class="crayons-story__hidden-navigation-link"&gt;Go-ing Beyond TypeScript: Microsoft Picks Go: How Will This Change the Landscape?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/georgekobaidze" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" alt="georgekobaidze profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/georgekobaidze" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Giorgi Kobaidze
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Giorgi Kobaidze
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-2369700" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/georgekobaidze" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Giorgi Kobaidze&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/georgekobaidze/go-ing-beyond-typescript-microsoft-picks-go-how-will-this-change-the-landscape-1p4h" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 31 '25&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/georgekobaidze/go-ing-beyond-typescript-microsoft-picks-go-how-will-this-change-the-landscape-1p4h" id="article-link-2369700"&gt;
          Go-ing Beyond TypeScript: Microsoft Picks Go: How Will This Change the Landscape?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/microsoft"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;microsoft&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/typescript"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;typescript&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/go"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;go&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/csharp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;csharp&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/georgekobaidze/go-ing-beyond-typescript-microsoft-picks-go-how-will-this-change-the-landscape-1p4h" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;1&lt;span class="hidden s:inline"&gt;&amp;nbsp;reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/go-ing-beyond-typescript-microsoft-picks-go-how-will-this-change-the-landscape-1p4h#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              2&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            12 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;At the time, Microsoft's decision to port the TypeScript compiler to Go sparked quite a bit of discussion and controversy. Many people questioned whether moving such a critical piece of the ecosystem away from TypeScript was the right choice.&lt;/p&gt;

&lt;p&gt;And boy, did Microsoft deliver what it promised: an order-of-magnitude performance improvement on some of the world's largest TypeScript codebases.&lt;/p&gt;

&lt;p&gt;The results are here, and the benchmarks speak for themselves.&lt;/p&gt;




&lt;h2&gt;
  
  
  Putting the 10x Claim Into Perspective
&lt;/h2&gt;

&lt;p&gt;The phrase "10x faster" describes the scale of the improvement Microsoft has demonstrated. It does not guarantee that every codebase will become exactly ten times faster.&lt;/p&gt;

&lt;p&gt;The results depend on the size of the project, the work being performed, and the available hardware. Some projects might see a 5x improvement, while others could reach 8x, 10x, 12x, or potentially even more.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No, this doesn't make every TypeScript developer a 10x developer&lt;/strong&gt;, But it does mean that compiling a TypeScript project, loading it in an editor, and receiving diagnostics could become dramatically faster after moving to the native toolchain. &lt;strong&gt;The word "dramatically" isn't an exaggeration at all in this context.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But hold on, there are still some important caveats. So before you open your editor and start upgrading an enterprise application to TypeScript 7, read this article all the way to the end.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Did We Get Here?
&lt;/h2&gt;

&lt;p&gt;When I first covered this initiative in 2025, Microsoft had just announced &lt;strong&gt;Project Corsa&lt;/strong&gt;, an effort to port the TypeScript compiler and tooling from TypeScript to native code written in Go.&lt;/p&gt;

&lt;p&gt;The announcement immediately triggered the controversy and hot takes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Why not Rust?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Why not C#?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is Microsoft abandoning its own technologies?&lt;/strong&gt; (Yeah, this one is particularly popular among Microsoft haters...)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real explanation was much less dramatic. This was a pragmatic engineering decision focused on performance, compatibility, and maintainability.&lt;/p&gt;

&lt;h3&gt;
  
  
  This Was an Extensive Evaluation
&lt;/h3&gt;

&lt;p&gt;The TypeScript team did not select Go after a superficial comparison. It evaluated several languages, built prototypes using different data representations, investigated hybrid architectures, and studied native TypeScript tools such as &lt;strong&gt;swc&lt;/strong&gt;, &lt;strong&gt;oxc&lt;/strong&gt;, and &lt;strong&gt;esbuild&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;One possible approach was to move only performance-critical components to a native language while leaving the core type-checking algorithms in JavaScript. Ultimately, the team concluded that a complete native port would provide greater benefits.&lt;/p&gt;

&lt;p&gt;That does not make Go the universally best language for compiler development. Several languages could have been excellent choices for a ground-up rewrite. Go performed best against the specific requirements of this project.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Priority Was Compatibility
&lt;/h3&gt;

&lt;p&gt;The most important requirement was not raw performance. It was compatibility.&lt;/p&gt;

&lt;p&gt;Microsoft expects the existing and native implementations to coexist for some time. During that period, fixes and features may need to move between both codebases. A language that permits a similar program structure makes that work considerably easier.&lt;/p&gt;

&lt;p&gt;A language requiring the team to rethink ownership, mutation, polymorphism, laziness, or fundamental data structures might produce an elegant new compiler, but it would no longer be a straightforward port. Idiomatic Go happens to resemble the function-and-data-oriented style already used throughout the TypeScript compiler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not Rust?
&lt;/h3&gt;

&lt;p&gt;Rust could have been a strong option for a new compiler designed from the ground up. That, however, was not the team's objective.&lt;/p&gt;

&lt;p&gt;The existing compiler relies heavily on automatic memory management and cyclic data structures. Rust's ownership model would have required the team to redesign those structures and rethink significant parts of the implementation. In Anders Hejlsberg's words, rewriting the compiler in Rust might have been possible, but faithfully porting it was not considered practical.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Not C#?
&lt;/h3&gt;

&lt;p&gt;C# was also evaluated. This is important because C# is Microsoft's primary language, and Anders Hejlsberg himself is its original designer.&lt;/p&gt;

&lt;p&gt;Hejlsberg described C# as a possible contender, but its higher-level, object-oriented model did not align as closely with the existing compiler. The TypeScript codebase follows a more procedural style built around functions and data structures. In fact, its core compiler does not use classes at all.&lt;/p&gt;

&lt;p&gt;He also noted that C# did not have a native-code generation story as mature as the alternatives the team was considering. Go, by comparison, had more than a decade of native deployment across all major platforms and closely matched the compiler's existing programming style.&lt;/p&gt;

&lt;p&gt;Microsoft did not choose Go because it had stopped trusting C#. It chose the tool that best matched this particular engineering problem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Go Fit the Existing Compiler
&lt;/h3&gt;

&lt;p&gt;Go provides garbage collection, supports cyclic and pointer-heavy data structures, offers control over memory layout and allocation, and enables shared-memory concurrency.&lt;/p&gt;

&lt;p&gt;It is also a procedural language built primarily around functions and data structures. Go does not have traditional classes or inheritance, but it supports interfaces, first-class functions, closures, and other patterns used extensively throughout the JavaScript implementation.&lt;/p&gt;

&lt;p&gt;TypeScript also performs an unusually large amount of graph processing, including upward and downward traversal through trees of polymorphic nodes. Go supports these patterns while allowing the native implementation to remain recognizably similar to its JavaScript counterpart.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Port, Not a Simple Translation
&lt;/h2&gt;

&lt;p&gt;Calling this work a simple translation would be misleading.&lt;/p&gt;

&lt;p&gt;The team developed tooling to convert some TypeScript syntax into Go, but important structures, including abstract syntax tree nodes, symbols, types, and control-flow data, still required substantial engineering.&lt;/p&gt;

&lt;p&gt;Compatibility remains the priority. The native compiler's behavior and output are continuously compared with the existing implementation through approximately &lt;strong&gt;100,000 tests&lt;/strong&gt;. The goal is to preserve TypeScript's semantics, diagnostics, and years of carefully developed optimizations rather than reinventing the language.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where Does the Performance Come From?
&lt;/h2&gt;

&lt;p&gt;The widely advertised 10x improvement comes from two major sources: native execution and parallel processing.&lt;/p&gt;




&lt;h3&gt;
  
  
  Native Execution
&lt;/h3&gt;

&lt;p&gt;Native code removes much of JavaScript's startup, JIT-compilation, allocation, and runtime overhead.&lt;/p&gt;

&lt;p&gt;In one demonstration, compiling roughly 250,000 lines took around seven seconds with the existing compiler. The single-threaded native implementation completed the same work in approximately two seconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  Parallel Processing
&lt;/h3&gt;

&lt;p&gt;Go then allows operations such as parsing, binding, emitting, and parts of type checking to run concurrently. After parallelization was enabled, that same 250,000-line compilation completed in less than one second.&lt;/p&gt;

&lt;p&gt;On the much larger Visual Studio Code codebase, approximately 1.5 million lines, the compilation time dropped from more than a minute to around six seconds.&lt;/p&gt;

&lt;p&gt;Anders Hejlsberg described the overall gain as roughly half native-code efficiency and half parallelism, although the exact balance naturally depends on the project and available hardware.&lt;/p&gt;




&lt;h2&gt;
  
  
  Memory Efficiency and Larger Projects
&lt;/h2&gt;

&lt;p&gt;Memory management was another decisive factor in choosing Go.&lt;/p&gt;

&lt;p&gt;Go gives the team control over the layout of objects, fields, and allocations without forcing every part of the compiler to manage memory manually. Although Go uses garbage collection, its usual disadvantages are less relevant to TypeScript's workload.&lt;/p&gt;

&lt;p&gt;Batch compilations can allocate what they need and terminate before garbage collection becomes a major concern. In long-running processes, structures such as abstract syntax trees often survive for the lifetime of the program, and the compiler has enough domain knowledge to identify sensible moments for collection.&lt;/p&gt;

&lt;p&gt;Go's UTF-8 strings, allocation-free substring operations, compact data layouts, and object-pooling techniques further reduce memory pressure. These improvements matter because out-of-memory failures have historically been one of the compiler team's most common categories of reported problems.&lt;/p&gt;

&lt;p&gt;The result is not merely a faster compiler. It is a tool capable of processing projects that previously approached or exceeded the practical memory limits of the JavaScript implementation.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Benchmarks
&lt;/h2&gt;

&lt;p&gt;Microsoft published the following full-build benchmarks in the official &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/" rel="noopener noreferrer"&gt;TypeScript 7 announcement&lt;/a&gt;. Both versions were tested on the same machine, with TypeScript 7 using its default configuration of four type-checker workers.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Codebase&lt;/th&gt;
&lt;th&gt;TypeScript 6&lt;/th&gt;
&lt;th&gt;TypeScript 7&lt;/th&gt;
&lt;th&gt;Speedup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VS Code&lt;/td&gt;
&lt;td&gt;125.7s&lt;/td&gt;
&lt;td&gt;10.6s&lt;/td&gt;
&lt;td&gt;11.9x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentry&lt;/td&gt;
&lt;td&gt;139.8s&lt;/td&gt;
&lt;td&gt;15.7s&lt;/td&gt;
&lt;td&gt;8.9x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bluesky&lt;/td&gt;
&lt;td&gt;24.3s&lt;/td&gt;
&lt;td&gt;2.8s&lt;/td&gt;
&lt;td&gt;8.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright&lt;/td&gt;
&lt;td&gt;12.8s&lt;/td&gt;
&lt;td&gt;1.47s&lt;/td&gt;
&lt;td&gt;8.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tldraw&lt;/td&gt;
&lt;td&gt;11.2s&lt;/td&gt;
&lt;td&gt;1.46s&lt;/td&gt;
&lt;td&gt;7.7x&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;The largest relative improvement in this group comes from VS Code, where compilation drops from 125.7 seconds to 10.6 seconds, an 11.9x speedup. Sentry sees the greatest absolute reduction, saving more than two minutes on a single run.&lt;/p&gt;

&lt;p&gt;These are not synthetic projects created to make the new compiler look good. They are large, mature codebases containing the complex type relationships, project structures, and dependency graphs that put real pressure on TypeScript.&lt;/p&gt;

&lt;p&gt;The results should still be interpreted carefully. They measure TypeScript tooling performance under a particular benchmark environment, they do not mean that the JavaScript produced by TypeScript 7 will execute 10x faster. Results will also vary depending on project configuration, hardware, available CPU cores, and how much of a build pipeline is spent outside the TypeScript compiler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Memory Usage
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Codebase&lt;/th&gt;
&lt;th&gt;TypeScript 6&lt;/th&gt;
&lt;th&gt;TypeScript 7&lt;/th&gt;
&lt;th&gt;Memory Delta&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;VS Code&lt;/td&gt;
&lt;td&gt;5.2GB&lt;/td&gt;
&lt;td&gt;4.2GB&lt;/td&gt;
&lt;td&gt;-18%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sentry&lt;/td&gt;
&lt;td&gt;4.9GB&lt;/td&gt;
&lt;td&gt;4.6GB&lt;/td&gt;
&lt;td&gt;-6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bluesky&lt;/td&gt;
&lt;td&gt;1.8GB&lt;/td&gt;
&lt;td&gt;1.3GB&lt;/td&gt;
&lt;td&gt;-26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Playwright&lt;/td&gt;
&lt;td&gt;1.0GB&lt;/td&gt;
&lt;td&gt;0.9GB&lt;/td&gt;
&lt;td&gt;-11%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;tldraw&lt;/td&gt;
&lt;td&gt;0.6GB&lt;/td&gt;
&lt;td&gt;0.5GB&lt;/td&gt;
&lt;td&gt;-15%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

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

&lt;p&gt;The memory improvements are less dramatic than the compilation-time gains, but they are still significant. Bluesky uses 26% less memory, while VS Code drops from 5.2GB to 4.2GB. On developer machines and CI agents running several jobs simultaneously, saving hundreds of megabytes, or even a full gigabyte, can make an important difference.&lt;/p&gt;

&lt;p&gt;The variation between projects is also expected. Parallel execution can require additional working memory, while Go's compact data layouts, UTF-8 strings, allocation strategy, and object pooling reduce it. The final result depends on the shape of each codebase and the amount of concurrency being used.&lt;/p&gt;

&lt;p&gt;Overall, the improvement is outstanding. I am especially looking forward to using VS Code with the native TypeScript language service. Faster startup, navigation, diagnostics, and type checking should make large projects feel considerably more responsive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The JavaScript API Trade Off
&lt;/h2&gt;

&lt;p&gt;One area where Go presents a genuine trade-off is JavaScript interoperability.&lt;/p&gt;

&lt;p&gt;The existing TypeScript API allows consumers to access and sometimes modify a large amount of compiler state directly inside the same process. That flexibility has also constrained the team's ability to change internal representations and introduce new optimizations.&lt;/p&gt;

&lt;p&gt;The native implementation cannot expose Go objects to JavaScript in the same way. For that reason, TypeScript 7.0 does not ship with a compiler API. Microsoft expects TypeScript 7.1 to introduce a new and deliberately designed API rather than reproducing unrestricted access to the old compiler's internal objects.&lt;/p&gt;

&lt;p&gt;Applications that depend heavily on the TypeScript compiler API or undocumented internals will need to adapt. Until the new API is available, Microsoft provides the &lt;code&gt;@typescript/typescript6&lt;/code&gt; compatibility package so tools can use the TypeScript 6 API alongside the TypeScript 7 compiler.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is It Still TypeScript?
&lt;/h2&gt;

&lt;p&gt;Yes. The programming language is still TypeScript, and you will continue writing the same code as before. What runs in the background is completely different, but there is nothing particularly strange or outrageous about that.&lt;/p&gt;

&lt;p&gt;As of August 2026, TypeScript 7.0 is stable and available through the standard &lt;code&gt;typescript&lt;/code&gt; package. This is still a port rather than a new programming language: developers continue writing the same TypeScript while the machinery behind compilation, diagnostics, and editor tooling has changed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The F1 Analogy
&lt;/h3&gt;

&lt;p&gt;If you are an F1 nerd like me, you might know that McLaren used Ford-Cosworth engines for much of the period between 1968 and 1983. That partnership helped McLaren win its first Constructors' Championship in 1974, along with Drivers' Championships in 1974 and 1976.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffnwu8b1s5q55zr9w4u5g.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffnwu8b1s5q55zr9w4u5g.jpeg" alt="Mclaren-Ford"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The car was still a McLaren. Its chassis, aerodynamics, controls, strategy, and overall identity belonged to the McLaren team. The engine, the main component that turned all of that engineering into motion, came from Ford because it was the right tool for the job. Not that McLaren couldn't build engines, but Ford's engines were exponentially better for F1 racing.&lt;/p&gt;

&lt;p&gt;TypeScript 7 follows a similar idea. The language, syntax, type system, and developer experience remain TypeScript. The engine running underneath them is being replaced because the native Go implementation is significantly better suited to the workload.&lt;/p&gt;

&lt;p&gt;This is not a language war, corporate rivalry, or evidence that Microsoft is ditching C# for Go. It is simply an engineering team choosing the right tool for a specific job.&lt;/p&gt;




&lt;h2&gt;
  
  
  Large Companies Helped Test TypeScript 7
&lt;/h2&gt;

&lt;p&gt;Microsoft did not rely only on its internal test suite. According to the official &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-7-0/" rel="noopener noreferrer"&gt;TypeScript 7 announcement&lt;/a&gt;, the team worked with companies including Bloomberg, Canva, Figma, Google, Linear, Miro, Notion, Sentry, Slack, Vanta, Vercel, and VoidZero. Internal Microsoft teams such as Loop, Office, Power BI, Teams, and Xbox also tested the compiler against their codebases.&lt;/p&gt;

&lt;p&gt;This testing exposed TypeScript 7 to complex monorepos, custom build pipelines, unusual module-resolution patterns, and workloads that are difficult to reproduce with isolated test cases.&lt;/p&gt;

&lt;p&gt;The results went beyond controlled benchmarks. Slack reduced type-checking time in CI from approximately 7.5 minutes to 1.25 minutes and reported a 40% reduction in merge-queue time. Canva reduced the time required to display the first editor error from around 58 seconds to 4.8 seconds.&lt;/p&gt;

&lt;p&gt;That kind of feedback matters because performance is only useful when the compiler remains stable and compatible under real production workloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Should You Upgrade?
&lt;/h2&gt;

&lt;p&gt;The short answer is: &lt;strong&gt;yes, but treat it as a major-version migration rather than a drop-in performance patch&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;TypeScript 7 is now available through the standard &lt;code&gt;typescript&lt;/code&gt; package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript@7
npx tsc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--save-dev&lt;/code&gt; flag, which can also be written as &lt;code&gt;-D&lt;/code&gt;, records TypeScript 7 as a development dependency. Running &lt;code&gt;npx tsc&lt;/code&gt; then uses the version installed locally in the project instead of relying on a global installation.&lt;/p&gt;

&lt;p&gt;Core features such as parsing, type checking, JavaScript emission, declaration emission, watch mode, incremental compilation, project references, and the language server are production-ready. However, the move to a native implementation still introduces compatibility considerations. TypeScript 7.0 does not ship with a compiler API, adopts TypeScript 6.0's new defaults and hard deprecations, and includes intentional differences in some JSDoc and JavaScript-specific behaviors.&lt;/p&gt;

&lt;p&gt;Projects that use TypeScript mainly through &lt;code&gt;tsc&lt;/code&gt; will probably have the easiest migration path. Projects that directly import the TypeScript compiler API, depend on undocumented internals, use custom language-service plugins, or rely heavily on legacy JavaScript and JSDoc behavior will need more careful testing or may need to run TypeScript 6 alongside TypeScript 7 temporarily.&lt;/p&gt;

&lt;p&gt;A sensible evaluation process is to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the existing TypeScript 6 build and record its diagnostics, output, execution time, and peak memory usage.&lt;/li&gt;
&lt;li&gt;Upgrade the project to TypeScript 7, run &lt;code&gt;npx tsc&lt;/code&gt;, and compare the results.&lt;/li&gt;
&lt;li&gt;Test watch mode, incremental builds, project references, and declaration generation separately.&lt;/li&gt;
&lt;li&gt;Enable TypeScript 7 support in your editor and test navigation, diagnostics, completions, and refactoring workflows.&lt;/li&gt;
&lt;li&gt;Keep the TypeScript 6 compatibility package available for tools that still require the old compiler API.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TypeScript 7 is clearly the future of the ecosystem, but a faster compiler is only valuable when it remains compatible with the workflows built around it. Upgrade deliberately, test the requirements of your actual codebase, and keep compatibility tooling where necessary, not simply because the headline says "10x faster."&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;When Microsoft announced Project Corsa, the 10x performance target sounded extremely ambitious. TypeScript 7 has now turned that promise into measurable results: faster builds, lower memory usage, and a more responsive development experience.&lt;/p&gt;

&lt;p&gt;The broader lesson is simple. Technologies are tools, not identities, and good engineering means choosing the right one for the job. TypeScript became faster by no longer being written in TypeScript, and there is nothing wrong with that, quite the contrary.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this deep dive? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>typescript</category>
      <category>go</category>
      <category>programming</category>
      <category>news</category>
    </item>
    <item>
      <title>HTTP QUERY Is Finally Here: Here's Why It Matters More Than You Think</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 12 Jul 2026 14:51:26 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/http-query-is-finally-here-heres-why-it-matters-more-than-you-think-5d5m</link>
      <guid>https://dev.to/georgekobaidze/http-query-is-finally-here-heres-why-it-matters-more-than-you-think-5d5m</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
The Long Road From GET to QUERY

&lt;ul&gt;
&lt;li&gt;HTTP/0.9&lt;/li&gt;
&lt;li&gt;HTTP/1.0&lt;/li&gt;
&lt;li&gt;HTTP/1.1&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
The HTTP Semantics That Absolutely Matter

&lt;ul&gt;
&lt;li&gt;Safety and Idempotence: The Foundations of HTTP Semantics&lt;/li&gt;
&lt;li&gt;Safety&lt;/li&gt;
&lt;li&gt;Idempotence&lt;/li&gt;
&lt;li&gt;Pizza Explains Everything&lt;/li&gt;
&lt;li&gt;Safety and Idempotence Table (Before QUERY)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Enter HTTP QUERY

&lt;ul&gt;
&lt;li&gt;Why Do We Need Another HTTP Method?&lt;/li&gt;
&lt;li&gt;HTTP QUERY for the Win&lt;/li&gt;
&lt;li&gt;How Do Clients Know a Server Supports QUERY?&lt;/li&gt;
&lt;li&gt;Giving a Query a URI&lt;/li&gt;
&lt;li&gt;A Few Things to Watch Out For&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Personal Take

&lt;ul&gt;
&lt;li&gt;A Step in the Right Direction&lt;/li&gt;
&lt;li&gt;Don't Rush&lt;/li&gt;
&lt;li&gt;GraphQL&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I've been waiting for this for a long time. Not because HTTP is broken, but because there has always been a subtle but awkward gap in the protocol. A gap that developers have been working around for years, usually by stretching &lt;code&gt;GET&lt;/code&gt; a little too far or by reaching for &lt;code&gt;POST&lt;/code&gt; even though its semantics never quite fit read-only queries.&lt;/p&gt;

&lt;p&gt;Every time I had to squeeze one more filter into a &lt;code&gt;GET&lt;/code&gt; request or use &lt;code&gt;POST&lt;/code&gt; for something that was obviously just fetching data, a voice in my head kept saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There has to be a better way."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And boy, do we have a better way now... finally!&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HTTP QUERY&lt;/code&gt; fills that gap.&lt;/p&gt;

&lt;p&gt;And this is no longer just an interesting proposal floating around the internet. In June 2026, it was officially published as &lt;a href="https://www.rfc-editor.org/rfc/rfc10008.html" rel="noopener noreferrer"&gt;RFC 10008&lt;/a&gt;, an IETF Standards Track document.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before we get into all of that, let's talk about why this article is worth your precious time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This isn't going to be one of those articles that simply says, "Here's a new HTTP method," and calls it a day. If we're going to talk about &lt;code&gt;QUERY&lt;/code&gt;, we first need to understand why it exists at all. That means taking a step back, looking at the history of HTTP, understanding the semantics behind its methods, and seeing how we even got here.&lt;/p&gt;

&lt;p&gt;By the end of this article, you won't just know what &lt;code&gt;QUERY&lt;/code&gt; is, you'll understand why adding a brand-new HTTP method was considered a better solution than continuing with the workarounds we've been using for decades.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Long Road From GET to QUERY
&lt;/h2&gt;

&lt;h3&gt;
  
  
  HTTP/0.9
&lt;/h3&gt;

&lt;p&gt;To understand why a new HTTP method like &lt;code&gt;QUERY&lt;/code&gt; matters, we first need to understand how HTTP methods came to exist in the first place.&lt;/p&gt;

&lt;p&gt;HTTP (Hypertext Transfer Protocol) was created in the early 1990s by Tim Berners-Lee while working at CERN. The original goal was simple: allow computers to exchange documents over the newly created World Wide Web.&lt;/p&gt;

&lt;p&gt;The earliest version of HTTP, later known as HTTP/0.9, was extremely minimal and simple. It supported only one operation: retrieving a document.&lt;/p&gt;

&lt;p&gt;A client would send a request like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /index.html
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server would respond with the contents of that file. There were no headers, no status codes, and no concept of different operations. The web at that time was essentially a collection of linked documents, so this simple model was enough.&lt;/p&gt;

&lt;p&gt;Those were simpler times, weren't they? I wasn't even born back then, so I can only imagine.&lt;/p&gt;

&lt;p&gt;But as the web grew, it became much more than a document-sharing system. Websites became applications. Users needed to submit forms, upload data, modify resources, and interact with servers in more complex ways.&lt;/p&gt;

&lt;p&gt;HTTP evolved to support these new requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP/1.0
&lt;/h3&gt;

&lt;p&gt;With HTTP/1.0, documented in &lt;a href="https://datatracker.ietf.org/doc/html/rfc1945" rel="noopener noreferrer"&gt;RFC 1945&lt;/a&gt; in 1996, the protocol introduced a richer request and response model, including status codes, headers, and two new methods alongside &lt;code&gt;GET&lt;/code&gt;: &lt;code&gt;HEAD&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt;. Interestingly, &lt;code&gt;PUT&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; appeared only in an appendix of RFC 1945 as "Additional Request Methods", they weren't part of the core specification yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP/1.1
&lt;/h3&gt;

&lt;p&gt;Then HTTP/1.1, standardized through &lt;a href="https://datatracker.ietf.org/doc/html/rfc2068" rel="noopener noreferrer"&gt;RFC 2068&lt;/a&gt; (1997) and &lt;a href="https://datatracker.ietf.org/doc/html/rfc2616" rel="noopener noreferrer"&gt;RFC 2616&lt;/a&gt; (1999), formally defined &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, &lt;code&gt;OPTIONS&lt;/code&gt;, and &lt;code&gt;TRACE&lt;/code&gt;, refined the semantics of all methods, and established principles that still define HTTP today. &lt;code&gt;PATCH&lt;/code&gt; arrived later through &lt;a href="https://datatracker.ietf.org/doc/html/rfc5789" rel="noopener noreferrer"&gt;RFC 5789&lt;/a&gt; in 2010. These core method definitions were later carried forward and polished in &lt;a href="https://datatracker.ietf.org/doc/html/rfc7231" rel="noopener noreferrer"&gt;RFC 7231&lt;/a&gt; (2014) and consolidated in &lt;a href="https://datatracker.ietf.org/doc/html/rfc9110" rel="noopener noreferrer"&gt;RFC 9110&lt;/a&gt; "HTTP Semantics" (2022), which remains the authoritative reference for general HTTP semantics.&lt;/p&gt;




&lt;h2&gt;
  
  
  The HTTP Semantics That Absolutely Matter
&lt;/h2&gt;

&lt;p&gt;If you've ever worked with web development, whether on the back end or the front end, this should already be familiar territory.&lt;/p&gt;

&lt;p&gt;However, this article is for everyone, not just web developers. So let's quickly recap the fundamentals.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Method&lt;/th&gt;
&lt;th&gt;The Official "RFC-Speak" Version&lt;/th&gt;
&lt;th&gt;The "Explain It Like I'm Human" Version&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Retrieve a representation of a resource.&lt;/td&gt;
&lt;td&gt;"Hey server, can I have this thing?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Submit data to be processed by the target resource.&lt;/td&gt;
&lt;td&gt;"Here is some data. Process it according to this resource's rules."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PUT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Create or replace a resource at the target URI.&lt;/td&gt;
&lt;td&gt;"Here is the complete version of this thing. Save it exactly here."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DELETE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Remove the resource identified by the target URI.&lt;/td&gt;
&lt;td&gt;"This thing is no longer needed. Remove it."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HEAD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Same as GET, but the server must not return response content.&lt;/td&gt;
&lt;td&gt;"Tell me about this thing, but don't send me the actual thing."&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OPTIONS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Describe the communication options available for the target resource.&lt;/td&gt;
&lt;td&gt;"Hey server, what can I do here?"&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PATCH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Apply partial modifications to a resource.&lt;/td&gt;
&lt;td&gt;"I don't need to replace everything, just change this small part."&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important idea is that HTTP methods are not just shortcuts for database operations. They define semantics: what a client is asking the server to do and what guarantees intermediaries can rely on.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safety and Idempotence: The Foundations of HTTP Semantics
&lt;/h3&gt;

&lt;p&gt;Safety and idempotence are two concepts that should always be taken into consideration when designing APIs. &lt;strong&gt;I cannot stress enough how important they are.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;API design is not only about making a request succeed or fail. It is about making sure everyone involved: clients, servers, proxies, caches, and automated systems can predict what happens when that request is sent, repeated, or retried.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safety
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Safety&lt;/strong&gt; means that the client neither requests nor expects a state change to the target resource. &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt;, &lt;code&gt;OPTIONS&lt;/code&gt;, and &lt;code&gt;TRACE&lt;/code&gt; are considered safe because their defined purposes are retrieval or diagnostics, not changing the target resource.&lt;/p&gt;

&lt;p&gt;Technically, you absolutely can change a resource with a &lt;code&gt;GET&lt;/code&gt; request. HTTP verbs don't really care what you implement in your back-end.&lt;/p&gt;

&lt;p&gt;You could create a &lt;code&gt;GET /users/{id}&lt;/code&gt; endpoint that wipes your entire database with a single request, instead of just retrieving the user.&lt;/p&gt;

&lt;p&gt;But because you &lt;strong&gt;CAN&lt;/strong&gt; doesn't mean you &lt;strong&gt;SHOULD&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;The purpose of HTTP method semantics is not to physically prevent developers from doing something. It is to communicate intent and create predictable behavior across the entire ecosystem. Browsers, caches, proxies, crawlers, and other tools rely on the assumption that &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt;, &lt;code&gt;Trace&lt;/code&gt; and &lt;code&gt;OPTIONS&lt;/code&gt; requests are safe.&lt;/p&gt;

&lt;p&gt;So if your application has a &lt;code&gt;GET&lt;/code&gt; endpoint whose purpose is to change business state... please stop. Seriously. You can be better than that!&lt;/p&gt;

&lt;h4&gt;
  
  
  OK, Now Before You Say "Actually..."
&lt;/h4&gt;

&lt;p&gt;Let's address a few important exceptions.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;GET&lt;/code&gt; a safe method does not mean that absolutely nothing is allowed to change on the server.&lt;/p&gt;

&lt;p&gt;In fact, a perfectly valid &lt;code&gt;GET&lt;/code&gt; request may still:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write access logs.&lt;/li&gt;
&lt;li&gt;Update analytics or page view counters.&lt;/li&gt;
&lt;li&gt;Populate or refresh server-side caches.&lt;/li&gt;
&lt;li&gt;Create a user session or issue a session cookie.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, these are all &lt;strong&gt;incidental side effects&lt;/strong&gt; of serving the request. They support the operation, but they are not the purpose of it.&lt;/p&gt;

&lt;p&gt;Check out the diagram below, which illustrates the main flow of a &lt;code&gt;GET&lt;/code&gt; request along with some of its possible incidental side effects.&lt;/p&gt;

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

&lt;p&gt;The key idea is that the client is asking to retrieve information, not to modify the application's business state.&lt;/p&gt;

&lt;p&gt;In other words, incidental changes to operational state can be acceptable. Making a business-state change the purpose of a safe request is not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Idempotence
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Idempotence&lt;/strong&gt; means that making the same request multiple times has the same intended effect on the server as making it once. Methods such as &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;HEAD&lt;/code&gt;, &lt;code&gt;PUT&lt;/code&gt;, &lt;code&gt;DELETE&lt;/code&gt;, &lt;code&gt;OPTIONS&lt;/code&gt;, and &lt;code&gt;TRACE&lt;/code&gt; are idempotent by definition, while &lt;code&gt;POST&lt;/code&gt; and &lt;code&gt;PATCH&lt;/code&gt; are not guaranteed to be.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before the "Actually" Squad Arrives Again...
&lt;/h4&gt;

&lt;p&gt;Just like with safety, there are some important exceptions and nuances.&lt;/p&gt;

&lt;p&gt;Idempotence does not mean that every repeated request produces the exact same response. The server is allowed to return different responses each time.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;DELETE /users/42
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first request might return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;204 No Content
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the user was successfully deleted.&lt;/p&gt;

&lt;p&gt;The second request might return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;404 Not Found
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because the user no longer exists. (Some might argue that the service should return &lt;code&gt;204 No Content&lt;/code&gt; even when the resource has already been deleted, but that discussion needs a separate article.)&lt;/p&gt;

&lt;p&gt;The operation is still considered idempotent because the intended result is the same: after the request completes, the user is gone.&lt;/p&gt;

&lt;p&gt;Idempotence also does not mean that the server has no side effects. A repeated &lt;code&gt;PUT&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt; request may still create logs, update metrics, or trigger internal processing. These are incidental effects, not changes to the intended resource state.&lt;/p&gt;

&lt;p&gt;The important question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Did absolutely nothing happen twice?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Did repeating the same request produce the same intended state?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That distinction is what allows HTTP infrastructure to safely retry certain requests when needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pizza Explains Everything
&lt;/h3&gt;

&lt;p&gt;A good pie of pepperoni pizza is the answer to everything in this world. This topic is no exception.&lt;/p&gt;

&lt;p&gt;Imagine ordering your favorite pizza.&lt;/p&gt;

&lt;p&gt;A safe operation is asking the pizza place: &lt;strong&gt;"What pizzas do you have?"&lt;/strong&gt; You get information, but nobody starts cooking anything.&lt;/p&gt;

&lt;p&gt;An idempotent operation is telling them: &lt;strong&gt;"Replace my order with one large pepperoni pizza."&lt;/strong&gt; If your phone accidentally sends the request five times, the result is still one large pepperoni pizza.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfi7vaoft84tp51bn1iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzfi7vaoft84tp51bn1iy.png" alt="Pizza 1" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In both scenarios, a new entry was created in the receptionist's call log. &lt;strong&gt;That's an incidental side effect, the business state is not affected.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A non-idempotent operation is saying:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Add another pizza to my order."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;or&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Add 10 more pepperoni slices to my pizza."&lt;/strong&gt; Mamma mia! That's the greatest non-idempotent operation I've ever seen!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvynn37b942ii6it7agkv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvynn37b942ii6it7agkv.jpg" alt="Pizza 2" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;...Now I want some pizza.&lt;/p&gt;

&lt;h3&gt;
  
  
  Safety and Idempotence Table (Before QUERY)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTTP Method&lt;/th&gt;
&lt;th&gt;Safe&lt;/th&gt;
&lt;th&gt;Idempotent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GET&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HEAD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OPTIONS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TRACE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PUT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DELETE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;POST&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;PATCH&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Enter HTTP QUERY
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Why Do We Need Another HTTP Method?
&lt;/h3&gt;

&lt;p&gt;Alright, enough with the prerequisites. Let's finally talk about &lt;code&gt;HTTP QUERY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As the name suggests, the &lt;code&gt;QUERY&lt;/code&gt; method is designed for querying resources... duh.&lt;/p&gt;

&lt;p&gt;Imagine you're building a large airport management system. It obviously has a vast number of data points and supports hundreds, if not thousands, of filtering options.&lt;/p&gt;

&lt;p&gt;If all you need is the basic information for a specific flight, a simple &lt;code&gt;GET&lt;/code&gt; request is exactly the right choice:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/flights/BA217&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.airport.example&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The server might respond with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Cache-Control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;max-age=60&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"flightNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BA217"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LHR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IAD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Boarding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"gate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A12"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing fancy here. Just a good old &lt;code&gt;HTTP GET&lt;/code&gt; request.&lt;/p&gt;

&lt;p&gt;Now, let's say you're not looking for one specific flight anymore. You want to build an operations dashboard that shows all flights matching certain conditions.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Flights departing from London Heathrow (LHR)&lt;/li&gt;
&lt;li&gt;Arriving at Washington Dulles (IAD)&lt;/li&gt;
&lt;li&gt;Between 6:00 PM and 10:00 PM&lt;/li&gt;
&lt;li&gt;Currently delayed&lt;/li&gt;
&lt;li&gt;Operated by British Airways&lt;/li&gt;
&lt;li&gt;With at least 200 passengers&lt;/li&gt;
&lt;li&gt;Sorted by delay duration&lt;/li&gt;
&lt;li&gt;Returning only the first 50 results&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A &lt;code&gt;GET&lt;/code&gt; request might become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;GET&lt;/span&gt; &lt;span class="nn"&gt;/flights?origin=LHR&amp;amp;destination=IAD&amp;amp;departureStart=18:00&amp;amp;departureEnd=22:00&amp;amp;status=delayed&amp;amp;airline=BA&amp;amp;minPassengers=200&amp;amp;sort=delayDuration&amp;amp;page=1&amp;amp;limit=50&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.airport.example&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a very realistic example of what a request like this might look like. At first glance, everything seems perfectly fine, and theoretically, there shouldn't be any issues. And for simple cases, that's absolutely true.&lt;/p&gt;

&lt;p&gt;However, things start to change in the real world. Once a query becomes too large or too complex, this approach begins to break down.&lt;/p&gt;

&lt;p&gt;There are several reasons for this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;URI length limits are unpredictable:&lt;/strong&gt; A request can pass through many systems: browsers, proxies, gateways, and servers, each with their own limits. The sender often cannot know the maximum supported size in advance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Some data is inefficient to encode in a URI:&lt;/strong&gt; Complex filters, nested conditions, sorting rules, and other structured data become difficult to represent and maintain once everything has to be serialized into a URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URIs are more exposed than request bodies:&lt;/strong&gt; URLs are commonly stored in logs, browser history, analytics tools, and bookmarks, which makes putting large or sensitive query data inside them undesirable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Every query representation becomes a distinct URI:&lt;/strong&gt; Different parameter orderings or serializations can create distinct resource identifiers even when they express the same logical query. This can fragment monitoring data and make one logical operation appear as many different request targets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I actually ran into a similar problem myself years ago while working with an API that required advanced sorting and filtering.&lt;/p&gt;

&lt;p&gt;I tried to follow HTTP conventions and use &lt;code&gt;GET&lt;/code&gt;, which seemed like the right approach at first. After all, I was only retrieving data, so &lt;code&gt;GET&lt;/code&gt; was the obvious choice.&lt;/p&gt;

&lt;p&gt;But as the number of filters, sorting options, and query parameters kept growing, the query strings started becoming massive.&lt;/p&gt;

&lt;p&gt;Eventually, they got so large that the server basically looked at my request and said: &lt;em&gt;"Nah, I ain't processing that."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And just like everyone else in this situation, I went with the most common &lt;strong&gt;workaround&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I am deliberately emphasizing the word &lt;em&gt;workaround&lt;/em&gt; here because it is not the same thing as a proper &lt;strong&gt;solution&lt;/strong&gt;. A solution addresses the underlying problem in the way the system was designed to work. A workaround simply gets the job done, but it may come with trade-offs and doesn't necessarily follow the original conventions.&lt;/p&gt;

&lt;p&gt;And that workaround? &lt;code&gt;HTTP POST&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's talk about why &lt;code&gt;POST&lt;/code&gt; isn't the best tool for the job either.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Technically, it works. You can simply put your large, complex query inside the request body of a &lt;code&gt;POST&lt;/code&gt; request, process it on the back end, and move on. Easy!&lt;/p&gt;

&lt;p&gt;The request would look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;POST&lt;/span&gt; &lt;span class="nn"&gt;/flights/search&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.airport.example&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LHR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IAD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"departureStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"departureEnd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"22:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delayed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"airline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minPassengers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delayDuration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But here's the catch. Well, actually, there are several catches.&lt;/p&gt;

&lt;h4&gt;
  
  
  The first catch is caching
&lt;/h4&gt;

&lt;p&gt;Unlike &lt;code&gt;GET&lt;/code&gt;, &lt;strong&gt;&lt;code&gt;POST&lt;/code&gt; responses are not reusable by caches in the usual way&lt;/strong&gt;. HTTP does allow a POST response to be cached when it includes explicit freshness information and a &lt;code&gt;Content-Location&lt;/code&gt; matching the POST request's target URI, but that cached response can be reused for later &lt;code&gt;GET&lt;/code&gt; or &lt;code&gt;HEAD&lt;/code&gt; requests, not another equivalent &lt;code&gt;POST&lt;/code&gt; request. Most browser caches, CDNs, and proxies do not implement this pattern automatically anyway.&lt;/p&gt;

&lt;p&gt;For complex queries, this can be a significant limitation. These requests often involve expensive filtering, sorting, database operations, or aggregations, and caching repeated results can save substantial processing time and improve performance.&lt;/p&gt;

&lt;p&gt;Of course, you can implement custom caching on top of POST. However, now you need to solve additional problems yourself, such as creating reliable cache keys, handling invalidation, and ensuring that cached responses correctly match the original request.&lt;/p&gt;

&lt;h4&gt;
  
  
  Another reason why POST is not an ideal fit for these operations comes down to the semantics of the method itself
&lt;/h4&gt;

&lt;p&gt;Remember what we discussed earlier about HTTP methods? &lt;code&gt;POST&lt;/code&gt; is defined as neither &lt;strong&gt;safe&lt;/strong&gt; nor &lt;strong&gt;idempotent&lt;/strong&gt;. It is intended for submitting data to be processed, often resulting in some kind of state change.&lt;/p&gt;

&lt;p&gt;A query operation is fundamentally different. When we are retrieving data, we are performing a read-only operation. We generally want it to be safe, repeatable, and compatible with HTTP's caching mechanisms.&lt;/p&gt;

&lt;p&gt;The semantics of &lt;code&gt;POST&lt;/code&gt; do not provide those guarantees. Along with methods like &lt;code&gt;PATCH&lt;/code&gt;, it is simply not the natural semantic fit for this type of operation.&lt;/p&gt;

&lt;p&gt;So why is it still commonly used for complex queries? Because &lt;code&gt;POST&lt;/code&gt; is widely supported, familiar, and flexible. When developers hit the limitations of &lt;code&gt;GET&lt;/code&gt;, &lt;code&gt;POST&lt;/code&gt; becomes the obvious workaround, even if it is not the perfect tool for the job.&lt;/p&gt;

&lt;h4&gt;
  
  
  Think about it
&lt;/h4&gt;

&lt;p&gt;If we can use &lt;code&gt;POST&lt;/code&gt; for querying data, why can't we use &lt;code&gt;PUT&lt;/code&gt; or &lt;code&gt;DELETE&lt;/code&gt; instead? After all, they are idempotent, so on paper they might seem like better candidates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But that still wouldn't make much sense.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Idempotence alone does not mean a method is suitable for reading data. &lt;code&gt;PUT&lt;/code&gt; and &lt;code&gt;DELETE&lt;/code&gt; are still designed for operations that modify resource state, replacing or removing resources respectively. They simply guarantee that repeating the same operation produces the same intended result.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;POST&lt;/code&gt; became the common workaround not because it is the perfect fit, but because it is flexible, widely supported, and allows clients to send complex data in the request body. Over time, using &lt;code&gt;POST&lt;/code&gt; for complex queries became such a common pattern that it started feeling natural, even though it doesn't perfectly match the semantics of a read-only operation.&lt;/p&gt;

&lt;h4&gt;
  
  
  GET with a request body?
&lt;/h4&gt;

&lt;p&gt;Some of you might ask the following question: instead of using &lt;code&gt;POST&lt;/code&gt;, why don't we just use GET? After all, the HTTP message format can technically carry content with a &lt;code&gt;GET&lt;/code&gt; request, just like it can with &lt;code&gt;POST&lt;/code&gt;, right?&lt;/p&gt;

&lt;p&gt;Well, yes, at the message-format level, that is possible. But HTTP does not define generally applicable semantics for content in a GET request. In other words, you can send it, but there is no universal agreement about what anyone should do with it.&lt;/p&gt;

&lt;p&gt;But as we've already seen several times, theory and real-world behavior are not always the same thing. Reality hits us with a left hook. Many existing systems, including some servers, proxies, and CDNs, do not reliably handle &lt;code&gt;GET&lt;/code&gt; request bodies. Some may ignore them, reject them, or just not forward them as expected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjbnqr09egpornb1fzq75.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fjbnqr09egpornb1fzq75.jpg" alt="Meme" width="500" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP QUERY for the Win
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;HTTP QUERY&lt;/code&gt; combines the best parts of both worlds. Like &lt;code&gt;GET&lt;/code&gt;, it is designed for safe, read-only operations. Like &lt;code&gt;POST&lt;/code&gt;, it allows clients to send structured data in the request body. Its responses are cacheable, and the method can be automatically retried after something like a connection failure because repeating it is not supposed to cause business-state changes.&lt;/p&gt;

&lt;p&gt;Here's the same example request as we had previously, but now using &lt;code&gt;HTTP QUERY&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;QUERY&lt;/span&gt; &lt;span class="nn"&gt;/flights&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.airport.example&lt;/span&gt;
&lt;span class="na"&gt;Accept&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LHR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IAD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"departureStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"18:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"departureEnd"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"22:00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delayed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"airline"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"minPassengers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"sort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"delayDuration"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"page"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important detail here is that &lt;code&gt;QUERY&lt;/code&gt; does not invent a universal query language. The body could contain JSON, SQL, JSONPath, form-encoded data, or another format understood by the resource. The request's &lt;code&gt;Content-Type&lt;/code&gt; tells the server how to interpret it, and RFC 10008 requires that field to be present and consistent with the content.&lt;/p&gt;

&lt;p&gt;Whatever format is used, processing the request must remain safe. Putting a state-changing instruction inside a &lt;code&gt;QUERY&lt;/code&gt; body does not magically make that operation safe, it would simply violate the method's semantics.&lt;/p&gt;

&lt;p&gt;That also gives servers a clear way to reject invalid requests:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;4xx&lt;/code&gt; response such as &lt;code&gt;400 Bad Request&lt;/code&gt; when the media type is missing.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;400 Bad Request&lt;/code&gt; when the declared media type is inconsistent with the content.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;415 Unsupported Media Type&lt;/code&gt; when the resource does not support that query format.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;422 Unprocessable Content&lt;/code&gt; when the format is valid but the query itself cannot be processed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;406 Not Acceptable&lt;/code&gt; when the server cannot produce a response in one of the formats requested through &lt;code&gt;Accept&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Based on these semantics, &lt;code&gt;QUERY&lt;/code&gt; is both &lt;strong&gt;safe&lt;/strong&gt; and &lt;strong&gt;idempotent&lt;/strong&gt;, making it a much better fit for complex read operations.&lt;/p&gt;

&lt;p&gt;Now, some might argue: instead of introducing an entirely new HTTP method, why not simply update &lt;code&gt;GET&lt;/code&gt; and officially allow request bodies?&lt;/p&gt;

&lt;p&gt;There are two major reasons why that approach is problematic.&lt;/p&gt;

&lt;p&gt;First, &lt;code&gt;GET&lt;/code&gt; already has a well-established meaning: retrieving a representation of the resource identified by the request target. A complex query is not always a simple representation of a single resource. It can represent a set of filters, conditions, and operations that produce a result. Expanding &lt;code&gt;GET&lt;/code&gt; to cover this use case would make its semantics much less clear.&lt;/p&gt;

&lt;p&gt;Second, the existing HTTP ecosystem has been built around the assumption that &lt;code&gt;GET&lt;/code&gt; bodies are not meaningful. Many intermediaries, caches, and CDNs were designed with this behavior in mind. Changing that assumption would require significant updates and could introduce unpredictable compatibility issues across the web.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Do Clients Know a Server Supports QUERY?
&lt;/h3&gt;

&lt;p&gt;You could simply send a &lt;code&gt;QUERY&lt;/code&gt; request and see what happens, but HTTP provides a cleaner discovery mechanism.&lt;/p&gt;

&lt;p&gt;A client can send an &lt;code&gt;OPTIONS&lt;/code&gt; request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="nf"&gt;OPTIONS&lt;/span&gt; &lt;span class="nn"&gt;/flights&lt;/span&gt; &lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt;
&lt;span class="na"&gt;Host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api.airport.example&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the server can respond with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Allow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;GET, HEAD, QUERY, OPTIONS&lt;/span&gt;
&lt;span class="na"&gt;Accept-Query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Allow&lt;/code&gt; tells the client that the resource supports the &lt;code&gt;QUERY&lt;/code&gt; method. The new &lt;code&gt;Accept-Query&lt;/code&gt; response header goes one step further and advertises the query formats accepted by that resource.&lt;/p&gt;

&lt;p&gt;For example, a different resource might support several formats:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;Accept-Query: application/jsonpath, application/sql
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So clients don't have to blindly guess whether a server expects JSON, SQL, or interpretive dance. The resource can tell them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Giving a Query a URI
&lt;/h3&gt;

&lt;p&gt;Putting the query in the request body solves the URI-length problem, but it creates another interesting question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"What if I want to refer to this query or its result later?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;RFC 10008 introduces the concept of an &lt;strong&gt;equivalent resource&lt;/strong&gt;: a resource that represents the combination of the &lt;code&gt;QUERY&lt;/code&gt; target, its content, and relevant metadata.&lt;/p&gt;

&lt;p&gt;After processing our flight query, the server could respond like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;Content-Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application/json&lt;/span&gt;
&lt;span class="na"&gt;Content-Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/flights/results/17&lt;/span&gt;
&lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/flights/queries/42&lt;/span&gt;
&lt;span class="na"&gt;ETag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"flights-42-1"&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"flightNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BA217"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"origin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"LHR"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"destination"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"IAD"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Delayed"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two location headers look similar, but they describe different things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Content-Location&lt;/code&gt; identifies a resource containing the result that was just returned.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Location&lt;/code&gt; identifies the equivalent query resource, allowing the client to repeat the same operation later with a normal &lt;code&gt;GET&lt;/code&gt; request instead of resending the query body.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The server is not required to create either resource, and any URI it provides may be temporary. But when it does, clients gain a GET-accessible link that can be cached, shared, or revisited.&lt;/p&gt;

&lt;p&gt;A server can also skip returning the result directly and send the client to that GET-accessible resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;303&lt;/span&gt; &lt;span class="ne"&gt;See Other&lt;/span&gt;
&lt;span class="na"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/flights/queries/42&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;303 See Other&lt;/code&gt; is important here because it explicitly tells the client to follow the redirect using &lt;code&gt;GET&lt;/code&gt;. Other standard redirects, including &lt;code&gt;301&lt;/code&gt;, &lt;code&gt;302&lt;/code&gt;, &lt;code&gt;307&lt;/code&gt;, and &lt;code&gt;308&lt;/code&gt;, preserve the &lt;code&gt;QUERY&lt;/code&gt; method for this operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Few Things to Watch Out For
&lt;/h3&gt;

&lt;p&gt;As we discussed earlier, using &lt;code&gt;POST&lt;/code&gt; for querying data has become such a common workaround that, at this point, it almost feels natural. Many systems have been built around this pattern for years, and switching from existing POST-based query endpoints to &lt;code&gt;QUERY&lt;/code&gt; across an entire ecosystem will require significant effort.&lt;/p&gt;

&lt;p&gt;Another thing to be careful about is caching.&lt;/p&gt;

&lt;p&gt;With &lt;code&gt;GET&lt;/code&gt; requests, caching is relatively straightforward because the request target (URI) already contains the information needed to identify the requested resource. With &lt;code&gt;QUERY&lt;/code&gt;, the request body becomes part of what defines the query itself.&lt;/p&gt;

&lt;p&gt;That means caching implementations must take the request content and relevant metadata, such as its media type, into account when generating cache keys. Otherwise, two completely different queries sent to the same endpoint could accidentally be treated as the same cached response, which is obviously not something anyone wants.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;QUERY&lt;/code&gt; also supports conditional requests. A client can send an &lt;code&gt;If-None-Match&lt;/code&gt; header with an ETag from an earlier response, and the server can return &lt;code&gt;304 Not Modified&lt;/code&gt; when the selected query result has not changed. So &lt;code&gt;QUERY&lt;/code&gt; doesn't merely claim to be cacheable, it can participate in the same validation model we already use with &lt;code&gt;GET&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, the fact that query content lives in the request body does &lt;strong&gt;not&lt;/strong&gt; make it magically private.&lt;/p&gt;

&lt;p&gt;Request URIs are more likely to appear in browser history, access logs, analytics systems, and intermediary logs, so moving complex query content out of the URI can reduce accidental exposure. But request bodies may still be logged, inspected, cached, or stored by your own infrastructure. If a query contains secrets, the correct solution is not to assume the body is invisible.&lt;/p&gt;

&lt;p&gt;And if the server generates a &lt;code&gt;Location&lt;/code&gt; or &lt;code&gt;Content-Location&lt;/code&gt; URI for a sensitive query, that URI should not contain sensitive pieces copied from the original request body. Otherwise, we would move the data out of the URL... only to put it right back there.&lt;/p&gt;

&lt;p&gt;There is one more browser-specific detail worth knowing: &lt;code&gt;QUERY&lt;/code&gt; is not a CORS-safelisted method. A cross-origin browser request therefore requires a preflight &lt;code&gt;OPTIONS&lt;/code&gt; request before the actual &lt;code&gt;QUERY&lt;/code&gt; request can be sent.&lt;/p&gt;

&lt;p&gt;And outside the browser, API gateways, firewalls, reverse proxies, and server configurations often use explicit method allowlists. Until they are updated, some of them may look at &lt;code&gt;QUERY&lt;/code&gt;, raise an eyebrow, and reject it before your application ever sees the request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Personal Take
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A Step in the Right Direction
&lt;/h3&gt;

&lt;p&gt;I really believe this is a step in the right direction.&lt;/p&gt;

&lt;p&gt;As someone who values logical design and following conventions, I think conventions exist for a reason: they make our lives easier by making systems more intuitive, predictable, and less confusing.&lt;/p&gt;

&lt;p&gt;For years, whenever I needed to implement a complex query endpoint, I usually reached for &lt;code&gt;POST&lt;/code&gt;. And while it worked, I always had that annoying voice in my head telling me something was off, because its semantics don't perfectly match the problem we are trying to solve.&lt;/p&gt;

&lt;p&gt;A query is a read operation. Ideally, it should be safe, idempotent, and compatible with HTTP's built-in capabilities. The semantics of &lt;code&gt;POST&lt;/code&gt; don't provide those guarantees, which is why it always felt like a workaround rather than a perfect fit.&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Rush
&lt;/h3&gt;

&lt;p&gt;That said, I wouldn't recommend rushing to replace every existing query endpoint with &lt;code&gt;HTTP QUERY&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Adoption takes time. CDNs, API gateways, proxies, frameworks, libraries, and tooling all need to understand and properly support the new method. Without that ecosystem support, you may simply introduce compatibility problems instead of solving existing ones.&lt;/p&gt;

&lt;p&gt;And even when &lt;code&gt;QUERY&lt;/code&gt; is fully supported, a normal &lt;code&gt;GET&lt;/code&gt; request remains the right choice for simple queries. &lt;code&gt;GET&lt;/code&gt; URLs are easy to bookmark, share, paste into a browser, and inspect. If a few query parameters express the request clearly and remain within practical URI limits, there is no problem that needs fixing.&lt;/p&gt;

&lt;p&gt;If you're maintaining legacy systems or working with older infrastructure, sticking with the traditional &lt;code&gt;GET&lt;/code&gt; and &lt;code&gt;POST&lt;/code&gt; approach is probably the practical choice for now. But if you're building something new and your entire stack supports &lt;code&gt;HTTP QUERY&lt;/code&gt;, it is absolutely worth considering.&lt;/p&gt;

&lt;p&gt;Just like with any new technology, the key is not blindly adopting it, it's understanding the problem it solves, knowing when it fits, and making sure the rest of your ecosystem is ready.&lt;/p&gt;

&lt;p&gt;Because, as we've learned throughout this article, these kinds of problems always show up eventually.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL
&lt;/h3&gt;

&lt;p&gt;One interesting area where &lt;code&gt;HTTP QUERY&lt;/code&gt; could potentially make a lot of sense is &lt;strong&gt;GraphQL&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I don't know, I'm just thinking out loud.&lt;/p&gt;

&lt;p&gt;Today, GraphQL APIs commonly send both query and mutation operations through &lt;code&gt;HTTP POST&lt;/code&gt;. And while this works perfectly fine from a practical perspective, using &lt;code&gt;POST&lt;/code&gt; for the read-only side has always felt a little strange from a pure HTTP semantics point of view.&lt;/p&gt;

&lt;p&gt;After all, a GraphQL &lt;strong&gt;query operation&lt;/strong&gt; is fundamentally a read operation. You are asking the server to retrieve and compose data, not modify anything. Yet we often represent that operation using a method that is not safe, not idempotent, and not naturally cache-friendly.&lt;/p&gt;

&lt;p&gt;The reason &lt;code&gt;POST&lt;/code&gt; became the standard approach is understandable. GraphQL queries can be large, highly structured documents with variables and nested selections, which makes a request body a natural fit.&lt;/p&gt;

&lt;p&gt;However, this is exactly the kind of problem &lt;code&gt;HTTP QUERY&lt;/code&gt; was designed to address: sending complex query instructions while preserving the semantics of a safe, idempotent read operation.&lt;/p&gt;

&lt;p&gt;To be clear, this would apply only to GraphQL query operations. GraphQL mutations intentionally change state, so representing them with a safe method like &lt;code&gt;QUERY&lt;/code&gt; would violate the method's semantics.&lt;/p&gt;

&lt;p&gt;Whether GraphQL ecosystems will eventually adopt &lt;code&gt;QUERY&lt;/code&gt; remains to be seen, but conceptually, the two technologies seem like a very natural match.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;After more than three decades, HTTP is still evolving.&lt;/p&gt;

&lt;p&gt;And that's one of the most fascinating things about it. It would be easy to assume that a protocol as fundamental as HTTP is already complete, but real-world usage always finds new challenges.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET&lt;/code&gt; was never designed for massive, complex queries. &lt;code&gt;POST&lt;/code&gt; became a common workaround, but it was never a perfect semantic fit either.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;HTTP QUERY&lt;/code&gt; doesn't replace the methods we already have. It simply fills a gap that has existed for years: a way to send complex queries with a request body while keeping the semantics of a safe and idempotent operation.&lt;/p&gt;

&lt;p&gt;It's not just another HTTP method. It's a reminder that even the foundations of the web can continue improving when we find a better way to build.&lt;/p&gt;

&lt;p&gt;What are your thoughts about all this?&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Enjoyed this deep dive? Let's stay connected!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I share more software engineering insights, projects, and experiments across these platforms:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💼 &lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;Connect with me on LinkedIn&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💻 &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Explore my projects on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;💬 &lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Follow me on X&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;🎥 &lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;Watch my videos on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>network</category>
      <category>api</category>
      <category>news</category>
    </item>
    <item>
      <title>A New Personal Best: What Six Months of Locking In Can Do</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sat, 04 Jul 2026 16:44:58 +0000</pubDate>
      <link>https://dev.to/georgekobaidze/a-new-personal-best-what-six-months-of-locking-in-can-do-p3k</link>
      <guid>https://dev.to/georgekobaidze/a-new-personal-best-what-six-months-of-locking-in-can-do-p3k</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Setting a New Benchmark for Myself&lt;/li&gt;
&lt;li&gt;My Most Productive Six Months Yet&lt;/li&gt;
&lt;li&gt;
2 Hackathon Wins

&lt;ul&gt;
&lt;li&gt;GitHub Copilot CLI Challenge Win: Metal Birds Watch&lt;/li&gt;
&lt;li&gt;Notion MCP Challenge Win: NoteRunway&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Raised Money for Charity&lt;/li&gt;
&lt;li&gt;Became an Engineering Manager&lt;/li&gt;
&lt;li&gt;Collected More Than 25 Stars on My GitHub Repositories&lt;/li&gt;
&lt;li&gt;Beat My Own Record in Terms of Likes per Article&lt;/li&gt;
&lt;li&gt;One Article Made It Into the Top 7 of the Week&lt;/li&gt;
&lt;li&gt;Got Accepted into the Virtual Coffee Community&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dev.to/georgekobaidze/a-new-personal-best-what-six-months-of-locking-in-can-do-p3k#joined-devengers"&gt;Joined Devengers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;To Sum It All Up&lt;/li&gt;
&lt;li&gt;Zero Luck, All Hard Work&lt;/li&gt;
&lt;li&gt;Share Your Wins and Achievements, and Set a New Benchmark Starting Now&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Setting a New Benchmark for Myself
&lt;/h2&gt;

&lt;p&gt;This short piece serves as a quick reminder of what my current benchmark looks like in terms of how much I should aim to do and achieve within a six-month period for it to feel successful.&lt;/p&gt;

&lt;p&gt;Six months is a solid amount of time, you can accomplish a lot in that window. I'm not someone who tends to look back too often, but every now and then, it's important to check in with yourself to make sure you're still moving forward and not slipping backward. And slipping backward is never a good sign.&lt;/p&gt;

&lt;p&gt;Some people might argue that just because you've been successful during a certain period, it doesn't necessarily mean you'll keep improving from there.&lt;/p&gt;

&lt;p&gt;And that is true, there's no doubt about that. Sometimes things just go south, and we fail to achieve even half of what we set out to accomplish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But that's the whole point!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Success doesn't teach us much, failure does. Failure is where the most important lessons come from. So set your standards high. If you fail, don't worry about it. Every failure is a lesson, and the more you fail, the more opportunities you have to learn and grow.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Most Productive Six Months Yet
&lt;/h2&gt;

&lt;p&gt;At the beginning of the year, I made a pact with myself that the first half of this year would be the most successful period of my life. Plans often don't work out, but this one worked like a charm.&lt;/p&gt;

&lt;p&gt;Don't get me wrong though, I'm still not fully happy with myself, I feel like I could've done even better but still, it's good enough for now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here are the most important things that happened during that time:&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  2 Hackathon Wins
&lt;/h2&gt;

&lt;p&gt;If I set out to do something, I want to succeed every way possible, whether it's industry work, writing code, writing articles, managing people, or presenting my work. I had already done all of that, but I had never participated in a hackathon.&lt;/p&gt;

&lt;p&gt;As a long-time member of the DEV Community, I was well aware of the dev challenges and hackathons that occasionally pop up, especially after the merge with MLH. That felt like the perfect opportunity to finally go after that goal.&lt;/p&gt;

&lt;p&gt;And boy did it turn out even better than I expected.&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Copilot CLI Challenge Win: Metal Birds Watch
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3s2wzbbh5sfkwi2gfv40.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3s2wzbbh5sfkwi2gfv40.webp" alt="GitHub Copilot CLI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This was my first-ever hackathon. Over 400 people took part, as it was a large event with great prizes for the winners, one of them being a ticket to the GitHub Universe conference, which is happening later this year in beautiful San Francisco.&lt;/p&gt;

&lt;p&gt;As an aviation enthusiast, I poured my heart into this project. I could barely work on it, as my neck, shoulder, and arm were in constant pain, I was in complete agony. A few days earlier, I had spent a long time clearing snow from my driveway, which took a serious toll on my body. I was in terrible pain.&lt;/p&gt;

&lt;p&gt;Here's me (the fool) trying to clear up the driveway:&lt;/p&gt;

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

&lt;p&gt;But I pushed through it and finished the project anyway.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0" class="crayons-story__hidden-navigation-link"&gt;Metal Birds Watch: Copilot CLI Helped Me Watch Planes Without Looking Up&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;GitHub Copilot CLI Challenge Submission&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/georgekobaidze" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" alt="georgekobaidze profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/georgekobaidze" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Giorgi Kobaidze
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Giorgi Kobaidze
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-3242019" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/georgekobaidze" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Giorgi Kobaidze&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Feb 13&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0" id="article-link-3242019"&gt;
          Metal Birds Watch: Copilot CLI Helped Me Watch Planes Without Looking Up
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cli"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cli&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/githubcopilot"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;githubcopilot&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;56&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              18&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/fe2eGNbItUk" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;When I saw that I had taken first place, I literally shouted out of excitement. That project will always be special to me.&lt;/p&gt;

&lt;p&gt;By the way, these are my initial sketches and outlines of the project. A lot of math was involved, and I'm glad I'm good at it. Sorry for my ugly handwriting, as I mentioned, my arm was killing me.&lt;/p&gt;

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




&lt;h3&gt;
  
  
  Notion MCP Challenge Win: NoteRunway
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvuvdtwox1xebpm55jz3.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvvuvdtwox1xebpm55jz3.webp" alt="Notion MCP"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This one was special too. I built a large, complex, AI-powered tool that helps manage your Notion workspace. I've been a Notion user for six years now, and I wanted to give something back to this incredible team. It turned out far better than I expected.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk" class="crayons-story__hidden-navigation-link"&gt;NoteRunway: Because Your Notion Workspace Deserves an Elite Crew&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Notion MCP Challenge Submission 🧠&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/georgekobaidze" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" alt="georgekobaidze profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/georgekobaidze" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Giorgi Kobaidze
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Giorgi Kobaidze
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-3425746" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/georgekobaidze" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Giorgi Kobaidze&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk" id="article-link-3425746"&gt;
          NoteRunway: Because Your Notion Workspace Deserves an Elite Crew
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/notionchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;notionchallenge&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/fire-f60e7a582391810302117f987b22a8ef04a2fe0df7e3258a5f49332df1cec71e.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;47&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              32&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/qtaKv66-8AY" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;And do you know the best part?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Because of that project, I got to meet &lt;strong&gt;Ivan Zhao&lt;/strong&gt; himself, the founder of Notion. We talked about my project and many other interesting topics. How awesome is that?! Life is full of surprises, let me tell you that!&lt;/p&gt;




&lt;h2&gt;
  
  
  Raised Money for Charity
&lt;/h2&gt;

&lt;p&gt;This was also a huge win. I regularly donate to charity, but this one was by far the largest contribution I've made. It came as a result of winning the GitHub Copilot CLI challenge (my first hackathon).&lt;/p&gt;

&lt;p&gt;The prize included a Copilot Pro Plus subscription, which I already had. GitHub gave me a few alternative options instead, and I chose to donate it to charity, an easy decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now the best part:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;GitHub matched my contribution, bringing the total donation to a significant amount.&lt;/p&gt;

&lt;p&gt;Once again, a huge thank you to &lt;strong&gt;GitHub&lt;/strong&gt; for making that possible, you're awesome!&lt;/p&gt;




&lt;h2&gt;
  
  
  Became an Engineering Manager
&lt;/h2&gt;

&lt;p&gt;As I mentioned above, if I set out to do something, I want to be the best at every part of it. I've been writing code for more than 10 years now, and I felt it was time to explore other dimensions of engineering. This role made the most sense to me, as I'm still closely involved in engineering, but now I also take on more responsibility and get to see things from a different perspective.&lt;/p&gt;

&lt;p&gt;So far, I'm absolutely loving it!&lt;/p&gt;




&lt;h2&gt;
  
  
  Collected More Than 25 Stars on My GitHub Repositories
&lt;/h2&gt;

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

&lt;p&gt;A number of people became interested in my work and started starring my repositories, which is always great to see.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beat My Own Record in Terms of Likes per Article
&lt;/h2&gt;

&lt;p&gt;One of my articles received significant engagement and became the most liked piece I've written so far. Many people also reached out to tell me they used it to train their LLMs or to build new skills around it.&lt;/p&gt;

&lt;p&gt;Check out the article below:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie" class="crayons-story__hidden-navigation-link"&gt;15 Essential Sections Every README Needs: Give Your Project What It Deserves&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;Ready-to-use markdown template&lt;/p&gt;

&lt;/a&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/georgekobaidze" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" alt="georgekobaidze profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/georgekobaidze" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Giorgi Kobaidze
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Giorgi Kobaidze
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-3553477" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/georgekobaidze" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Giorgi Kobaidze&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Apr 26&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie" id="article-link-3553477"&gt;
          15 Essential Sections Every README Needs: Give Your Project What It Deserves
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/documentation"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;documentation&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/tutorial"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;tutorial&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/development"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;development&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;171&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/15-essential-sections-every-readme-needs-give-your-project-what-it-deserves-fie#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              83&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  One Article Made It Into the Top 7 of the Week
&lt;/h2&gt;

&lt;p&gt;If you're not a technical writer on DEV.to, it's hard to appreciate how difficult it is to get an article into the weekly top 7, it really needs to stand out. This article made it there, which I was extremely happy about.&lt;/p&gt;

&lt;p&gt;Check it out below:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62" class="crayons-story__hidden-navigation-link"&gt;Can AI Generate Binary Directly? Is It Feasible? Does It Make Sense?&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/georgekobaidze" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" alt="georgekobaidze profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/georgekobaidze" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Giorgi Kobaidze
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Giorgi Kobaidze
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png"&gt;&lt;/a&gt;
                
              
              &lt;div id="story-author-preview-content-3327718" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/georgekobaidze" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F3ad144e9-ca91-4395-b73a-9a0a3d843af9.jpg" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Giorgi Kobaidze&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 8&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62" id="article-link-3327718"&gt;
          Can AI Generate Binary Directly? Is It Feasible? Does It Make Sense?
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/discuss"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;discuss&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/ai"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;ai&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/compilers"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;compilers&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/programming"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;programming&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/raised-hands-74b2099fd66a39f2d7eed9305ee0f4553df0eb7b4f11b01b6b1b499973048fe5.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;36&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              14&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            11 min read
          &lt;/small&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  Got Accepted into the Virtual Coffee Community and the Devengers Team
&lt;/h2&gt;

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

&lt;p&gt;I've always wanted to be part of this community. I knew the people there were great and supportive. I got accepted, and I'm incredibly happy about it. It's always important to have good people around you.&lt;/p&gt;

&lt;p&gt;You really are who you surround yourself with.&lt;/p&gt;




&lt;h2&gt;
  
  
  Joined Devengers
&lt;/h2&gt;

&lt;p&gt;Thanks to &lt;a class="mentioned-user" href="https://dev.to/francistrdev"&gt;@francistrdev&lt;/a&gt; I joined the Devengers team. It makes me think I've done something special on this platform, which feels awesome!&lt;/p&gt;




&lt;h2&gt;
  
  
  To Sum It All Up
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Won the GitHub Copilot CLI Challenge&lt;/li&gt;
&lt;li&gt;Won the Notion MCP Challenge&lt;/li&gt;
&lt;li&gt;Raised a significant amount of money for charity with GitHub&lt;/li&gt;
&lt;li&gt;Won a ticket to the GitHub Universe conference&lt;/li&gt;
&lt;li&gt;Met Ivan Zhao, the founder of Notion&lt;/li&gt;
&lt;li&gt;Became an Engineering Manager&lt;/li&gt;
&lt;li&gt;Built 4 new personal projects&lt;/li&gt;
&lt;li&gt;Collected 25+ GitHub stars&lt;/li&gt;
&lt;li&gt;Published 13 new articles&lt;/li&gt;
&lt;li&gt;Wrote my all-time most loved article&lt;/li&gt;
&lt;li&gt;Reached the Top 7 of the week with an article&lt;/li&gt;
&lt;li&gt;Joined 2 new communities: Virtual Coffee and the Devengers team here on DEV Community.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Zero Luck, All Hard Work
&lt;/h2&gt;

&lt;p&gt;I've seen a lot of people talk about the importance of luck, which I agree plays a role to some extent. But it often creates a mindset where people start relying on luck more than they should, and that's a big mistake, I hate that.&lt;/p&gt;

&lt;p&gt;These things I just mentioned didn't happen because of luck. They came from pushing myself to the limit, at times even through severe physical pain (no exaggeration), and sacrificing a lot of my personal life along the way. My evenings, nights, and weekends were dedicated to all of this.&lt;/p&gt;

&lt;p&gt;It's not a lot of time in the grand scheme of things, but I'd rather use that limited time than not do it at all.&lt;/p&gt;

&lt;p&gt;Of course, this isn't for everyone, or maybe even for most people. I've even been called a few "funny" names because of it: weird, psycho, freak, nerd. But who gives a "fork"? I certainly don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share Your Wins and Achievements, and Set a New Benchmark Starting Now
&lt;/h2&gt;

&lt;p&gt;Now I'd love to hear about your new baseline and your new standards, share them, and let's talk about them.&lt;/p&gt;

&lt;p&gt;Let's keep grinding!&lt;/p&gt;

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




&lt;p&gt;&lt;strong&gt;If you want to follow my work or connect, you can find me here:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/giorgikobaidze/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x.com/georgekobaidze" rel="noopener noreferrer"&gt;Twitter/X&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.youtube.com/@Pilotronica" rel="noopener noreferrer"&gt;YouTube&lt;/a&gt;&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>career</category>
      <category>showdev</category>
      <category>community</category>
    </item>
  </channel>
</rss>
