<?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>Forem: Giorgi Kobaidze</title>
    <description>The latest articles on Forem by Giorgi Kobaidze (@georgekobaidze).</description>
    <link>https://forem.com/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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg</url>
      <title>Forem: Giorgi Kobaidze</title>
      <link>https://forem.com/georgekobaidze</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/georgekobaidze"/>
    <language>en</language>
    <item>
      <title>The Final 1% of Every GitHub Project: Sealing It Properly</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sat, 11 Apr 2026 15:55:53 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/the-final-1-of-every-github-project-sealing-it-properly-2app</link>
      <guid>https://forem.com/georgekobaidze/the-final-1-of-every-github-project-sealing-it-properly-2app</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What Does It Mean to "Seal" a Project?&lt;/li&gt;
&lt;li&gt;
The Release Checklist

&lt;ul&gt;
&lt;li&gt;README&lt;/li&gt;
&lt;li&gt;The "About" Section&lt;/li&gt;
&lt;li&gt;Branch Hygiene&lt;/li&gt;
&lt;li&gt;Release Tags&lt;/li&gt;
&lt;li&gt;Branch and Tag Rulesets&lt;/li&gt;
&lt;li&gt;New Release and Release Notes&lt;/li&gt;
&lt;li&gt;Move All Tasks to Done&lt;/li&gt;
&lt;li&gt;Choose a License for Your Project&lt;/li&gt;
&lt;li&gt;CI/CD Status &amp;amp; Pipeline Health&lt;/li&gt;
&lt;li&gt;Versioned Builds &amp;amp; Artifacts&lt;/li&gt;
&lt;li&gt;Optional: Write an Article or Record a Demo Video&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Here's the Full Checklist to Copy and Use&lt;/li&gt;

&lt;li&gt;Finish as Strong as You Start&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;You're sitting at your desk excited, sleep-deprived, but still genuinely happy.&lt;/p&gt;

&lt;p&gt;After weeks, maybe even months of grinding, you're finally ready to show your project to the world, or your team.&lt;/p&gt;

&lt;p&gt;This is the moment you've been waiting for.&lt;br&gt;
Time to publish, share, and feel proud of what you've built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But hold on&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might not be done just yet.&lt;/p&gt;

&lt;p&gt;There's that final 1% you need to take care of before even thinking about wrapping things up - the part where you truly seal your project.&lt;/p&gt;

&lt;p&gt;Because "done" usually just means the code works.&lt;/p&gt;

&lt;p&gt;❓ But is it versioned?&lt;br&gt;
❓ Can someone else understand it?&lt;br&gt;
❓ Is it safe to deploy?&lt;br&gt;
❓ Can your future self come back to it without pain?&lt;/p&gt;

&lt;p&gt;That last 1% isn't about writing more code.&lt;br&gt;
It's about making your project ready for the real world.&lt;/p&gt;

&lt;p&gt;And that's exactly what most developers overlook.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Does It Mean to "Seal" a Project?
&lt;/h2&gt;

&lt;p&gt;Well, that's what I call it, but it's not really about the repository as a whole. &lt;strong&gt;It's about every single version of your product.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every time you release something, you're not just shipping code, you're shipping a complete unit. A version that should stand on its own: deployable, tested, and fully functional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But that's only the baseline.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A properly "sealed" version is also:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Well-documented&lt;/li&gt;
&lt;li&gt;Clearly versioned&lt;/li&gt;
&lt;li&gt;Properly packaged&lt;/li&gt;
&lt;li&gt;Easy to understand and use&lt;/li&gt;
&lt;li&gt;Presented in a way that others (or your future self) can trust&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You need a well-defined checklist to go through before you can call it done. Let's go through them one by one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Release Checklist
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;This isn't a definitive list&lt;/strong&gt;, it's my personal approach. You might find it helpful, but everyone has their own way of properly wrapping up a project or repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  README
&lt;/h3&gt;

&lt;p&gt;Duh, right?&lt;/p&gt;

&lt;p&gt;It might sound obvious, but you'd be surprised how many repositories either don't have a README at all, or have one that barely says anything useful.&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.amazonaws.com%2Fuploads%2Farticles%2F2ak4ljzlzgjtjq4z8stm.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.amazonaws.com%2Fuploads%2Farticles%2F2ak4ljzlzgjtjq4z8stm.png" alt="Metal Birds Watch Readme" width="800" height="394"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your README should be the main entry point to your project.&lt;br&gt;
&lt;strong&gt;If someone can't understand, set up, or use your project from it without any hassle, it's not good enough.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A solid README should answer the basic questions:&lt;/p&gt;

&lt;p&gt;❓ What is this project?&lt;br&gt;
❓ Why does it exist?&lt;br&gt;
❓ How do I run it?&lt;br&gt;
❓ How do I use it?&lt;/p&gt;

&lt;p&gt;And many more important questions.&lt;/p&gt;

&lt;p&gt;I'll write a separate article on how to craft an effective README that's actually useful, because it deserves that level of attention.&lt;/p&gt;

&lt;p&gt;But for now, just remember this:&lt;br&gt;
&lt;strong&gt;README is never optional, it's one of the most essential parts of your project.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The "About" Section
&lt;/h3&gt;

&lt;p&gt;The About section is one of the most important parts of a repository. It provides a quick, high-level overview of the project and makes it easier for others to immediately understand what it is about.&lt;/p&gt;

&lt;p&gt;It can include a short description of the repository, a demo or live link, and other quick-access resources like documentation or a website. It also surfaces key repository metadata such as stars, forks, and watchers, giving instant context about the project's popularity and activity.&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.amazonaws.com%2Fuploads%2Farticles%2F8kjzsje69mfctv8cf4k4.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.amazonaws.com%2Fuploads%2Farticles%2F8kjzsje69mfctv8cf4k4.png" alt="About" width="475" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In addition, the About section allows you to enable or disable different repository features and visibility components, helping you control what information is highlighted on the repo page.&lt;/p&gt;

&lt;p&gt;One of its most powerful features is tags (topics). Tags improve searchability and discovery by helping your repository appear in relevant searches and topic-based browsing. They also communicate the tech stack and domain of your project at a glance.&lt;/p&gt;

&lt;p&gt;Used properly, the About section becomes a compact "control panel" for your repository's identity, visibility, and discoverability.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branch Hygiene
&lt;/h3&gt;

&lt;p&gt;When writing code, you usually end up creating a number of temporary branches like &lt;code&gt;feature&lt;/code&gt;, &lt;code&gt;bugfix&lt;/code&gt;, &lt;code&gt;documentation&lt;/code&gt;, &lt;code&gt;refactor&lt;/code&gt;, and so on.&lt;/p&gt;

&lt;p&gt;Some developers stay disciplined and clean them up right after they're merged into permanent branches like &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;develop&lt;/code&gt;, or &lt;code&gt;release&lt;/code&gt;. Others, however, leave them behind, where they slowly accumulate in the repository without any real purpose.&lt;/p&gt;

&lt;p&gt;That doesn't leave a great impression for someone exploring your project or considering a contribution. It's a bit like walking into someone's house and seeing empty soda cans, pizza boxes, and empty, expired snack wrappers scattered all over the living room and kitchen, you immediately feel that things aren't being maintained properly.&lt;/p&gt;

&lt;p&gt;More importantly, it creates internal confusion over time. You'll eventually find yourself asking: "Do we still need this branch? Why is it still here?" In many cases, it's just forgotten, not intentionally kept.&lt;/p&gt;

&lt;p&gt;Keeping your branch list clean is a small habit, but it improves clarity, reduces cognitive load, and makes repository maintenance much easier in the long run.&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.amazonaws.com%2Fuploads%2Farticles%2Fvsqrele2y3l1oypov5rj.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.amazonaws.com%2Fuploads%2Farticles%2Fvsqrele2y3l1oypov5rj.png" alt="Branches" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So once development work is finished and merged, make it a habit to remove temporary branches and keep only the long-lived ones like main, develop, and release (not limited to these three, there can be more).&lt;/p&gt;

&lt;p&gt;A clean repository isn't just about code, it's about discipline and clarity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Release Tags
&lt;/h3&gt;

&lt;p&gt;Release tags are one of the most important but often overlooked parts of properly sealing a project.&lt;/p&gt;

&lt;p&gt;A tag marks a specific point in your repository's history as a meaningful version, such as &lt;code&gt;v1.0.1&lt;/code&gt;, &lt;code&gt;v1.2.3&lt;/code&gt;, or &lt;code&gt;v2.0.0&lt;/code&gt;. Unlike branches, tags are immutable - they permanently point to a specific commit. This makes them ideal for representing official releases.&lt;/p&gt;

&lt;p&gt;Without tags, it becomes harder to track what version was deployed, compare changes between releases, or reliably roll back if something breaks. With proper version tagging, every release becomes a clear and reproducible snapshot of your project.&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.amazonaws.com%2Fuploads%2Farticles%2Fwp5lkj83zbg0q7fu0iux.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.amazonaws.com%2Fuploads%2Farticles%2Fwp5lkj83zbg0q7fu0iux.png" alt="Tags" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most teams follow semantic versioning &lt;strong&gt;(MAJOR.MINOR.PATCH)&lt;/strong&gt;, which communicates the nature of changes:&lt;/p&gt;

&lt;p&gt;MAJOR: breaking changes&lt;br&gt;
MINOR: new features, backward compatible&lt;br&gt;
PATCH: bug fixes&lt;/p&gt;

&lt;p&gt;In my own workflow, I sometimes take this a step further. Alongside a release tag like &lt;code&gt;1.0.1&lt;/code&gt;, I also create a corresponding branch such as &lt;code&gt;release/1.0.1&lt;/code&gt;. I treat it as an immutable reference point that mirrors the tagged commit.&lt;/p&gt;

&lt;p&gt;This is my personal approach, and it's not the only way to handle releases. Many developers or teams rely solely on tags, while others use release branches for stabilization, CI/CD workflows, or long-term maintenance.&lt;/p&gt;

&lt;p&gt;Tags are often sufficient on their own, but in certain workflows, combining them with release branches can add flexibility and clarity.&lt;/p&gt;

&lt;p&gt;In short, a release tag gives you a stable reference. How you structure around it depends on your workflow and team preferences.&lt;/p&gt;

&lt;h3&gt;
  
  
  Branch and Tag Rulesets
&lt;/h3&gt;

&lt;p&gt;GitHub provides rulesets (under repository settings → rules) that let you define and enforce policies for both branches and tags. This is an important but often overlooked part of properly "sealing" a project.&lt;/p&gt;

&lt;p&gt;Rulesets allow you to control what is allowed and what is restricted in your repository. For branches, you can enforce things like requiring pull requests before merging, requiring status checks to pass, blocking force pushes, and restricting direct commits to important branches like &lt;code&gt;main&lt;/code&gt;, &lt;code&gt;develop&lt;/code&gt;, or &lt;code&gt;release/*&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For tags, rulesets are just as important. You can control who is allowed to create or modify tags, enforce naming patterns (such as semantic versioning like &lt;code&gt;v1.2.3&lt;/code&gt;), and prevent accidental or unauthorized releases from being created.&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.amazonaws.com%2Fuploads%2Farticles%2Frced4jmq9k63f6ts6rk3.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.amazonaws.com%2Fuploads%2Farticles%2Frced4jmq9k63f6ts6rk3.png" alt="Rulesets" width="376" height="490"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Together, branch and tag rulesets help ensure that your repository follows a predictable and safe workflow. They prevent accidental changes to critical branches and protect release integrity by making sure that versions are created in a controlled and consistent way.&lt;/p&gt;

&lt;p&gt;In practice, I use these rulesets to enforce discipline around my workflow. For example, I restrict direct pushes to main, require pull request reviews, and ensure that release tags follow a strict versioning format. This helps keep the repository clean, predictable, and production-ready.&lt;/p&gt;

&lt;p&gt;That said, rulesets are flexible and highly team-dependent. Different projects will have different levels of strictness depending on their size, deployment strategy, and collaboration model.&lt;/p&gt;

&lt;p&gt;At a high level, rulesets are what turn a repository from "just code" into a controlled system with enforced structure and reliability. I'll discuss more about the best practices of rulesets in a separate article.&lt;/p&gt;

&lt;h3&gt;
  
  
  New Release and Release Notes
&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.amazonaws.com%2Fuploads%2Farticles%2Fuvkbr7o0kwpiw2kv0qjv.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.amazonaws.com%2Fuploads%2Farticles%2Fuvkbr7o0kwpiw2kv0qjv.png" alt="New Release" width="403" height="141"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A project version is not truly complete until it has been published as an official release.&lt;/p&gt;

&lt;p&gt;In GitHub terms, this means creating a release tied to a specific tag, marking a stable and meaningful snapshot of your codebase. However, the release itself is only half of the story.&lt;/p&gt;

&lt;p&gt;A release is not complete until it is accompanied by proper release notes that describe what has changed since the previous version.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Release notes are not a "nice to have", they are critical.&lt;/strong&gt; They are the primary way for users, consumers, contributors, and dependent teams/developers to understand what has changed, why it changed, and how it might affect them.&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.amazonaws.com%2Fuploads%2Farticles%2F0n7iwhcket5ksvn9dbpt.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.amazonaws.com%2Fuploads%2Farticles%2F0n7iwhcket5ksvn9dbpt.png" alt="Release Note Template" width="800" height="590"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Good release notes typically include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New features added&lt;/li&gt;
&lt;li&gt;Bug fixes&lt;/li&gt;
&lt;li&gt;Breaking changes&lt;/li&gt;
&lt;li&gt;Internal improvements or refactors&lt;/li&gt;
&lt;li&gt;Migration notes or required actions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That said, not everything from this list might be applicable to every release.&lt;/p&gt;

&lt;p&gt;Without this context, even a well-versioned release becomes difficult to use safely. People are left guessing what changed, which increases the risk of integration issues and misunderstandings.&lt;/p&gt;

&lt;p&gt;A well-written release note also improves collaboration. It acts as a communication layer between development and usage, ensuring that changes are transparent and traceable.&lt;/p&gt;

&lt;p&gt;Here is a simple example of the &lt;code&gt;v1.0.0&lt;/code&gt; release notes for the Metal Birds Watch project:&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.amazonaws.com%2Fuploads%2Farticles%2Fzvx0bxr4vx9v6r4lxauo.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.amazonaws.com%2Fuploads%2Farticles%2Fzvx0bxr4vx9v6r4lxauo.png" alt="Metal Birds Watch v1.0.0" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Move All Tasks to Done
&lt;/h3&gt;

&lt;p&gt;One often overlooked part of properly finishing a project is cleaning up your task tracking system, especially in GitHub Projects.&lt;/p&gt;

&lt;p&gt;Before considering a version truly complete, all relevant tasks should be either completed, closed, or moved to a final "Done" state. This ensures that the project board accurately reflects the actual state of the work.&lt;/p&gt;

&lt;p&gt;Leaving tasks in "In Progress" or "To Do" after a release creates confusion. It becomes unclear whether something was forgotten, postponed, or simply not tracked properly. Over time, this reduces trust in the project's planning and documentation.&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.amazonaws.com%2Fuploads%2Farticles%2F9zvko0ztbjf3p7qhwehi.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.amazonaws.com%2Fuploads%2Farticles%2F9zvko0ztbjf3p7qhwehi.png" alt="Project" width="800" height="535"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A clean project board has a psychological impact as well. It gives a clear sense of closure and helps both contributors and maintainers understand that a release cycle has been fully completed.&lt;/p&gt;

&lt;p&gt;In addition, GitHub Projects can act as a historical record of work. Keeping it clean and properly closed makes it easier to review past development cycles and understand what was delivered in each release.&lt;/p&gt;

&lt;p&gt;So before you consider a version fully "sealed", make sure the work is not only merged, but also properly reflected in your project board. Everything should either be done, closed, or intentionally moved forward into the next iteration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose a License for Your Project
&lt;/h3&gt;

&lt;p&gt;One of the most commonly overlooked parts of finishing a project is adding a proper license.&lt;/p&gt;

&lt;p&gt;A license defines how others are allowed to use your code, whether they can modify it, distribute it, use it commercially, or build on top of it. Without a license, your project is technically "all rights reserved" by default, meaning others don't actually have legal permission to use it in most contexts.&lt;/p&gt;

&lt;p&gt;This is especially important if your repository is public. People may be interested in learning from your work, contributing to it, or using it as a dependency. Without a clear license, you're creating uncertainty around what is and isn't allowed.&lt;/p&gt;

&lt;p&gt;Choosing a license doesn't need to be complicated. Many projects use standard options like MIT, Apache 2.0, or GPL, depending on how permissive or restrictive they want to be. The key is not which license you choose, but that you choose one deliberately.&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.amazonaws.com%2Fuploads%2Farticles%2F0xnylzayxqukm5cv00bo.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.amazonaws.com%2Fuploads%2Farticles%2F0xnylzayxqukm5cv00bo.png" alt="License" width="800" height="659"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adding a license is a small step, but it completes an essential part of the project's "contract" with its users.&lt;/p&gt;

&lt;p&gt;A project without a license is unfinished in a different way, it may work technically, but it's not fully ready for real-world use.&lt;/p&gt;

&lt;h3&gt;
  
  
  CI/CD Status &amp;amp; Pipeline Health
&lt;/h3&gt;

&lt;p&gt;A project is not truly "done" if your CI/CD pipeline is broken or unreliable.&lt;/p&gt;

&lt;p&gt;Before considering a release complete, you should always ensure that your automation pipelines are in a healthy state. This includes making sure that builds run successfully, tests pass consistently, and deployment workflows behave as expected.&lt;/p&gt;

&lt;p&gt;CI/CD is often the first thing that silently breaks over time. A small change in dependencies, configuration, or environment setup can easily lead to failing pipelines, even if the application itself seems fine locally.&lt;/p&gt;

&lt;p&gt;That's why pipeline health is part of the final 1% of sealing a project. It ensures that your code is not only working on your machine, but is also reliably validated and deployable in an automated environment.&lt;/p&gt;

&lt;p&gt;A properly sealed project should have:&lt;/p&gt;

&lt;p&gt;✅ Green build status on all required branches&lt;br&gt;
✅ Passing unit and integration tests&lt;br&gt;
✅ Stable and repeatable workflows&lt;br&gt;
✅ No failing or outdated GitHub Actions (or equivalent pipelines)&lt;/p&gt;

&lt;p&gt;If your pipeline is broken, your release is not really safe, no matter how good the code looks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Versioned Builds &amp;amp; Artifacts
&lt;/h3&gt;

&lt;p&gt;Another critical part of properly finishing a project is ensuring that your builds and artifacts are versioned and reproducible.&lt;/p&gt;

&lt;p&gt;A release should not just exist in source code, it should exist as a concrete, identifiable output that can be built, stored, and retrieved at any time.&lt;/p&gt;

&lt;p&gt;Versioned builds ensure that every release corresponds exactly to a specific state of your codebase. Whether it's a compiled binary, a Docker image, a NuGet package, or any other artifact, it should always be traceable back to a specific tag or commit.&lt;/p&gt;

&lt;p&gt;Without this, deployments become unreliable. You may end up in situations where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You cannot reproduce an older version of the application&lt;/li&gt;
&lt;li&gt;Different environments produce different outputs&lt;/li&gt;
&lt;li&gt;Rolling back becomes difficult or impossible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A properly sealed project ensures that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Every release is tied to a versioned artifact&lt;/li&gt;
&lt;li&gt;Artifacts are stored in a consistent registry or repository&lt;/li&gt;
&lt;li&gt;Builds are reproducible from source at any time&lt;/li&gt;
&lt;li&gt;Tags, versions, and artifacts are aligned&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In mature systems, this is often automated through CI/CD pipelines, where every tag or release automatically produces a versioned build artifact.&lt;/p&gt;

&lt;p&gt;In short, if you cannot rebuild and retrieve a specific version of your project, then the release is not truly complete, it is only partially sealed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional: Write an Article or Record a Demo Video
&lt;/h3&gt;

&lt;p&gt;This step is optional and rightfully so. Not everyone needs to go this far, because a well-written README and proper release notes usually cover the essentials.&lt;/p&gt;

&lt;p&gt;However, if you want to truly showcase your work in a more complete and impactful way, consider going beyond the repository itself.&lt;/p&gt;

&lt;p&gt;Writing an article about your project allows you to explain the motivation, design decisions, challenges, and solutions in a structured and human-readable format. It gives context that code alone often cannot communicate.&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.amazonaws.com%2Fuploads%2Farticles%2Fxfeks10m55wuaio6x0ex.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.amazonaws.com%2Fuploads%2Farticles%2Fxfeks10m55wuaio6x0ex.png" alt="Article" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Taking it a step further, recording a short demo video can be even more powerful. It lets people see your project in action, understand its behavior instantly, and get a feel for the user experience without needing to set anything up. This is often the fastest way to communicate value.&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.amazonaws.com%2Fuploads%2Farticles%2F9qbpjb5uxifckxzyd6vd.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.amazonaws.com%2Fuploads%2Farticles%2F9qbpjb5uxifckxzyd6vd.png" alt="Video" width="800" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This combination, an article or a demo, also helps you improve your communication and presentation skills, which are just as important as technical ability.&lt;/p&gt;

&lt;p&gt;Because no matter how good your application is, if it's not presented properly, it might never get the attention it deserves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here's the Full Checklist to Copy and Use
&lt;/h2&gt;

&lt;p&gt;✅ README&lt;br&gt;
✅ The "About" Section&lt;br&gt;
✅ Branch Hygiene&lt;br&gt;
✅ Release Tags&lt;br&gt;
✅ Branch and Tag Rulesets&lt;br&gt;
✅ New Release and Release Notes&lt;br&gt;
✅ Move All Tasks to Done&lt;br&gt;
✅ Choose a License for Your Project&lt;br&gt;
✅ CI/CD Status &amp;amp; Pipeline Health&lt;br&gt;
✅ Versioned Builds &amp;amp; Artifacts&lt;br&gt;
✅ Optional: Write an Article or Record a Demo Video&lt;/p&gt;

&lt;h2&gt;
  
  
  Finish as Strong as You Start
&lt;/h2&gt;

&lt;p&gt;Sometimes we're so desperate to finish a project that we rush through the final steps and end up missing important details. When that happens, keep in mind to slow down, take a deep breath, and remind ourselves that &lt;strong&gt;finishing well is just as important as starting well.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of a brand-new car missing a taillight or a side mirror - it still works, but it's not complete, and it's not safe, and it looks ugly. Unfinished or rushed projects feel the same: something important is missing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you've already committed to doing something, take the extra time to do it properly. Be a strong finisher. Be someone who completes things with care and intention.&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>opensource</category>
      <category>development</category>
      <category>repository</category>
    </item>
    <item>
      <title>365 Days of Building in Public, Perfectly Reflected By My Badges</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Thu, 02 Apr 2026 21:24:26 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/365-days-of-building-in-public-perfectly-reflected-by-my-badges-2h5f</link>
      <guid>https://forem.com/georgekobaidze/365-days-of-building-in-public-perfectly-reflected-by-my-badges-2h5f</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/wecoded-2026"&gt;2026 WeCoded Challenge&lt;/a&gt;: Echoes of Experience&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;365&lt;/li&gt;
&lt;li&gt;Your DEV Badges Are Trying to Tell Your Story. Listen to Them&lt;/li&gt;
&lt;li&gt;
One Year Club

&lt;ul&gt;
&lt;li&gt;"Hey Mom, Your Son Is a Software Engineer"&lt;/li&gt;
&lt;li&gt;And That's When I Discovered DEV Community&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Two &amp;amp; Three Year Club

&lt;ul&gt;
&lt;li&gt;Fast forward to 2020&lt;/li&gt;
&lt;li&gt;Boom: The Pandemic Hits. And It Hits Real Bad&lt;/li&gt;
&lt;li&gt;I Had to Carve Time Out of Thin Air&lt;/li&gt;
&lt;li&gt;If You're Expecting a Happy Ending, You Won't Find It Here&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Four, Five, Six &amp;amp; Seven Year Club

&lt;ul&gt;
&lt;li&gt;I Refuse to Catch a Break, Ever&lt;/li&gt;
&lt;li&gt;Then I Finally Started to Feel Comfortable... I Absolutely Hated It&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Writing Debut&lt;/li&gt;

&lt;li&gt;Community Wellness Streak&lt;/li&gt;

&lt;li&gt;

Top 7

&lt;ul&gt;
&lt;li&gt;I'm All In on AI, But We Need to Talk About Vibe Coding&lt;/li&gt;
&lt;li&gt;20 Rules for Becoming THAT Manager (From a Principal Engineer's Perspective)&lt;/li&gt;
&lt;li&gt;Can AI Generate Binary Directly? Is It Feasible? Does It Make Sense?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;C#&lt;/li&gt;

&lt;li&gt;Eight Year Club&lt;/li&gt;

&lt;li&gt;GitHub Copilot CLI Challenge Winner&lt;/li&gt;

&lt;li&gt;DEV Weekend Challenge Completion&lt;/li&gt;

&lt;li&gt;Still Not Convinced?!&lt;/li&gt;

&lt;li&gt;Time to Play the Game&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;I keep all my articles tucked away in a private repository on GitHub. It's not just storage, it's more like an archive of how I think, how I grow, and sometimes, how I struggle.&lt;/p&gt;

&lt;p&gt;Over time, it naturally shaped itself into a few categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Analysis&lt;/li&gt;
&lt;li&gt;Career&lt;/li&gt;
&lt;li&gt;Technical&lt;/li&gt;
&lt;li&gt;Challenges&lt;/li&gt;
&lt;li&gt;Specials&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could argue this belongs in the "Challenges" category. And you wouldn't be wrong. But I chose "Specials" instead. Because this isn't just another challenge. It's something different... something that stays with you.&lt;/p&gt;

&lt;p&gt;The moment &lt;a class="mentioned-user" href="https://dev.to/jess"&gt;@jess&lt;/a&gt; announced this challenge and I read the description, it actually made me smile, because right away I knew exactly what I would write. I have zero ideas for the Frontend Art challenge, my creativity sometimes isn't performing at its best. &lt;/p&gt;

&lt;p&gt;Since that frontend challenge is out of the question, well, here I am, offering the textual representation of the intense signals firing in my brain. This article won't be technical at all (which is by design), more like an easy-going, reflective piece to read while you're chilling in your favorite chair, in your room, garden, or porch, sipping your coffee, tea, or whatever your favorite beverage is.&lt;/p&gt;

&lt;p&gt;Right now, I don't have an internet connection and for the first time, I'm actually grateful. No notifications, no tabs, no distractions. Just the quiet hum of my thoughts, letting me focus on writing this.&lt;/p&gt;

&lt;p&gt;Strap in. We're about to take a little journey through my brain, neuron by neuron. And make sure you read it all the way to the end, because I'm about to play a game with you that might just change your entire life.&lt;/p&gt;




&lt;h2&gt;
  
  
  365
&lt;/h2&gt;

&lt;p&gt;The timing of this challenge couldn't have been better.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because it's March 2026 (at the moment of writing this article), which means I published my first article a year ago. And this anniversary fits perfectly with the spirit of the challenge.&lt;/p&gt;

&lt;p&gt;This past year has been spectacularly amazing. There's so much to reflect on that I don't even know where to start, and I definitely can't recall everything in one go. Of course, I won't try to fit it all into this article, that would turn it into a small book.&lt;/p&gt;

&lt;p&gt;But being brief isn't easy either. Anyone familiar with my writing knows I'm really terrible at keeping things short. I like providing as many details as possible, whether technical or non-technical. Definitely something I need to work on.&lt;/p&gt;




&lt;h2&gt;
  
  
  Your DEV Badges Are Trying to Tell Your Story. Listen to Them
&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.amazonaws.com%2Fuploads%2Farticles%2Fpudv7nblq31plci53qdu.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.amazonaws.com%2Fuploads%2Farticles%2Fpudv7nblq31plci53qdu.png" alt="DEV Badges"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I don't want this to be a generic storytelling of my journey, I'll save that for when I write a proper, comprehensive lookback.&lt;/p&gt;

&lt;p&gt;Instead, I want to show how my badges on DEV Community can actually tell my story. And honestly, it's surprising how accurate they are, I can't believe I hadn't noticed it before.&lt;/p&gt;

&lt;p&gt;If you take a close look at them, they form a perfect timeline of what you've been doing on this amazing platform. They give you a ton of context about your values, your focus, and your performance.&lt;/p&gt;

&lt;p&gt;These aren't just random badges, icons hanging on your profile. They're trying to tell your story. They have purpose. They are your path. Your signature.&lt;/p&gt;

&lt;p&gt;Let me show you, using my example.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Year Club
&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.amazonaws.com%2Fuploads%2Farticles%2F8k0gka2it6zdk2etxknz.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F8k0gka2it6zdk2etxknz.webp" alt="One Year Club Badge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  "Hey Mom, Your Son Is a Software Engineer"
&lt;/h3&gt;

&lt;p&gt;I know I should reflect on the past year, but to see the full picture, I need to go much further back than that.&lt;/p&gt;

&lt;p&gt;I've known DEV since 2017, when I first started coding professionally as a junior developer. Good times... man, I was so happy. I even remember stepping out of my final interview and calling my mom right away. I was like, "Hey Mom, your son is officially a software engineer! How cool is that?!"&lt;/p&gt;

&lt;p&gt;That very moment didn't just define my career, it defined my life. I had never felt that proud of myself before.&lt;/p&gt;

&lt;p&gt;Back then, in my country, getting a job as a junior software engineer was almost impossible, everybody wanted seniors. And when you somehow did land a junior role, eager to learn as much as possible, they expected you to handle senior developer tasks as quickly as possible, with little to no guidance.&lt;/p&gt;

&lt;p&gt;Sure, reaching that level is the goal for every junior developer, but when it comes paired with immense pressure, things can get tricky, sometimes really tricky.&lt;/p&gt;

&lt;p&gt;I remember being trapped in a vicious cycle, wanting to excel at work while also trying to learn as many things as possible in every direction. I ended up stressing myself out even more than the work did, and there were times I even questioned if I was good enough. Impostor syndrome is one hell of a thing.&lt;/p&gt;

&lt;h3&gt;
  
  
  And That's When I Discovered DEV Community
&lt;/h3&gt;

&lt;p&gt;A few months after I started working, I came across a really interesting article on DEV Community. I was at home, writing code, when it just popped up and it completely blew my mind. I wish I had saved it.&lt;/p&gt;

&lt;p&gt;Back then, I wasn't trying to get involved in any kind of community. I'd just occasionally stumble upon articles on the platform, and whenever a title caught my eye, I'd read it.&lt;/p&gt;

&lt;p&gt;One day in 2018, I decided to join DEV Community. I was already reading most of the articles there and wanted to give something back, even if it was just my presence, or a few comments here and there.&lt;/p&gt;

&lt;p&gt;Back then, I didn't think I was worthy of writing articles. I believed it was only for the most experienced, veteran, superstar developers, how wrong I was. I wish I had started writing from the moment I registered.&lt;/p&gt;

&lt;p&gt;So you, yeah, you, reading this, if you're hesitating about whether to start writing, just start. Do it NOW! You'll thank me in a few months. Mark my words.&lt;/p&gt;




&lt;h2&gt;
  
  
  Two &amp;amp; Three Year Club
&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.amazonaws.com%2Fuploads%2Farticles%2Fzkwi8hrdpv7bt3maepm3.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.amazonaws.com%2Fuploads%2Farticles%2Fzkwi8hrdpv7bt3maepm3.png" alt="Two And Three Year Badges"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Fast forward to 2020
&lt;/h3&gt;

&lt;p&gt;Even though there are so many stories from that fast-forward period, I want to move quickly to the more recent years. I'll save the tales of all the things I faced back then for another time, there will be other opportunities to share them.&lt;/p&gt;

&lt;p&gt;I stayed pretty passive for a few years. Then, sometime in 2020, I started leaving comments on other people's articles, and that alone already made me feel like part of the community. It felt really good.&lt;/p&gt;

&lt;p&gt;I'm not trying to make excuses, but in my defense, that period was extremely tough. I had been selected to continue my PhD research at SDSU (San Diego State University). Everything was set — and then... &lt;/p&gt;

&lt;h3&gt;
  
  
  Boom: The Pandemic Hits. And It Hits Real Bad
&lt;/h3&gt;

&lt;p&gt;Everything shut down instantly. Flights were canceled, programs postponed, the whole world shifted to remote, including universities. So my plans of continuing my PhD just went out the window.&lt;/p&gt;

&lt;p&gt;That was something I had wanted since I was a teenager. And just like that, for reasons completely out of my control, that perfect opportunity was gone overnight.&lt;/p&gt;

&lt;p&gt;I'm not the type of person who gives up easily, so when they offered continuing it remotely from my country, I said, "hell yeah, I'm in! Count me in!"&lt;/p&gt;

&lt;p&gt;But there was a small catch: I was working full-time during the day, and then getting into my research in the evening, when it was still morning for my co-researchers in California.&lt;/p&gt;

&lt;p&gt;So my schedule basically looked like 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.amazonaws.com%2Fuploads%2Farticles%2Fvy0gf0um8c5gu9cis91o.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.amazonaws.com%2Fuploads%2Farticles%2Fvy0gf0um8c5gu9cis91o.png" alt="Schedule"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I basically only had a few hours to work on my research - late at night, when my brain was completely exhausted and there was barely any energy left for creativity. Sometimes I'd stay up until 3 AM or even later, barely getting any sleep.&lt;/p&gt;

&lt;p&gt;The next day, I'd be so drained that I'd fall asleep right after the meeting, I just couldn't keep my head up anymore. That kind of inconsistency destroys your productivity, and I was feeling miserable.&lt;/p&gt;

&lt;p&gt;But no matter how I felt, I just don't give up. I'm not trying to sound cool, it's just who I am. I don't trust my own brain or body when they tell me I'm tired or exhausted or I can't do it anymore. I convince myself they're just being lazy, that I can push even further.&lt;/p&gt;

&lt;p&gt;Even if I dropped unconscious in the street after a few sleepless nights, I'd still try to work on my PhD. That's just how I'm wired.&lt;/p&gt;

&lt;p&gt;Is it a good trait?&lt;br&gt;
That's debatable. Probably not.&lt;/p&gt;
&lt;h3&gt;
  
  
  I Had to Carve Time Out of Thin Air
&lt;/h3&gt;

&lt;p&gt;I was trying everything to find extra time. I didn't even have a car back then, and I was losing way too much time commuting. So I decided to spend most of my savings to get one (which I still have, by the way, I'm way too loyal).&lt;/p&gt;

&lt;p&gt;But that wasn't all. I also changed jobs and joined a company that would let me work from home. That alone saved me around 2–3 hours a day, and at that time, it felt like the best decision ever.&lt;/p&gt;

&lt;p&gt;I started there as a senior software engineer, which is even tougher than starting out as a junior, because the expectations are there from day one. Literally. You're expected to do senior-level work, and you're expected to do it well.&lt;/p&gt;
&lt;h3&gt;
  
  
  If You're Expecting a Happy Ending, You Won't Find It Here
&lt;/h3&gt;

&lt;p&gt;That stretch lasted for about two years. Eventually, I was finally able to move to the right time zone and continue working on my PhD properly.&lt;/p&gt;

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

&lt;p&gt;The timing, and the circumstances &lt;strong&gt;couldn't have been worse&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The university was still partially closed. COVID was still very much a thing. We didn't meet often as a research team.&lt;/p&gt;

&lt;p&gt;Because of my schedule over those two years, my co-researchers were already far ahead. Some of them were even thinking about moving on to other programs. The group was slowly coming to an end.&lt;/p&gt;

&lt;p&gt;And on top of everything, it was decided that I had only a few months to finish my research. Not more.&lt;/p&gt;

&lt;p&gt;If you've ever worked on a PhD, you know that finishing your first research in such a short time is nearly impossible. Yes, I had those two years before that...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But did I really?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This whole pandemic situation really messed up my PhD plans. I still managed to get some work done, but I wasn't happy with my progress.&lt;/p&gt;

&lt;p&gt;That entire experience completely broke me. I just can't handle losing or not succeeding, I have to win. Doesn't matter if it's my PhD or playing with my cat. Sorry, Ruby.&lt;/p&gt;

&lt;p&gt;I'm honestly jealous of people who can lose and just say, "yeah, whatever." I wish I could do that. And I do understand that failure is necessary for growth, sometimes even more than success.&lt;/p&gt;

&lt;p&gt;But still... it leaves scar tissues.&lt;/p&gt;


&lt;h2&gt;
  
  
  Four, Five, Six &amp;amp; Seven Year Club
&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.amazonaws.com%2Fuploads%2Farticles%2Ffdgzdxoirfc9wbpaba4w.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.amazonaws.com%2Fuploads%2Farticles%2Ffdgzdxoirfc9wbpaba4w.png" alt="4 Badges"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  I Refuse to Catch a Break, Ever
&lt;/h3&gt;

&lt;p&gt;So I became a principal engineer, which was multiple levels harder than what I'd been doing as a senior software engineer.&lt;/p&gt;

&lt;p&gt;Granted, I no longer had to work on my PhD, since the program had ended. But transition periods are never easy, they demand your full focus - I had to level up both my technical and management skills to become a solid principal engineer. Because even if you're a technical genius, if you can't manage people, your products, your services, and your communication properly, you simply can't be a strong principal engineer. You really need to be good at... pretty much everything. You're the bridge between multiple different teams and people: technical, product, leadership, and more.&lt;/p&gt;

&lt;p&gt;So it's not just about being good at each of those areas, but also figuring out how to manage communication between all those levels and roles.&lt;/p&gt;

&lt;p&gt;Yeah... it's a little tricky, to say the least.&lt;/p&gt;

&lt;p&gt;I once published an article: &lt;a href="https://dev.to/georgekobaidze/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3"&gt;20 Rules for Becoming THAT Manager (From a Principal Engineer’s Perspective)&lt;/a&gt;. A reader left a comment that really stuck with me: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"After more than 35 years of engineering management, the only comment I need to make is: You have arrived early my friend. You expressed most of what needs to be said, and extremely more eloquently than I could ever wish to do. Brilliant! I just wish everybody, regardless of the profession would read this slowly and thoughtfully. It would make the world a better place. Thanks for taking the time. I can't say that I enjoyed reading anything on the subject more - ever." &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That comment absolutely made my day, especially coming from such an experienced veteran. But the truth is, I had to be an early bird. My career accelerated incredibly fast, or rather, I forced it to, because I desperately needed to get my life on track and fast, because there's no time to waste. Out of curiosity, I asked ChatGPT about the average ages for different levels of software engineers, and here is what it told me:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Typical path:

Junior → Mid: early–mid 20s
Senior: late 20s–early 30s
Staff: early–mid 30s
Principal: late 30s → mid 40s (most common)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I had just turned 27 when I became a principal engineer. Now, at 30, I feel like it had to happen that quickly, because you are never truly ready for anything until you actually try it. My philosophy has always been this: don't worry if a challenge sounds hard. As long as it sounds even a tiny bit reasonable, jump in and figure things out as you go. Otherwise, you will spend your entire life just getting ready. That mindset has always worked for me. Almost every challenge I've tackled has turned out to be much easier than I expected. I'm sure it would have worked with my PhD, too, if it weren't for COVID and all the chaos it brought to the world.&lt;/p&gt;
&lt;h3&gt;
  
  
  Then I Finally Started to Feel Comfortable... I Absolutely Hated It
&lt;/h3&gt;

&lt;p&gt;This madness continued until about 2024. Once I noticed I was starting to feel comfortable in my new position, with more free time and mental capacity after work, the thought of writing articles snuck back into my mind. I had a few ideas, but I lacked the courage to start. That lingering trauma of not achieving my PhD was still echoing in my brain (and to be honest, it still does, but it's much more manageable now). &lt;/p&gt;

&lt;p&gt;For some reason, I need to be in constant motion to feel alive. I have to direct my thoughts toward something productive, it doesn't matter whether that means tackling a new project, drafting an article, washing my car, organizing my workspace, or getting a workout in.&lt;/p&gt;

&lt;p&gt;I spent a lot of time sketching out drafts only to abandon them, convinced they weren't good enough. I threw away five or six different articles. Even though I already had a huge experience, I still couldn't shake the feeling that public writing just wasn't for me...&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Until March 8th, 2025.&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Writing Debut
&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.amazonaws.com%2Fuploads%2Farticles%2Fv5yamchn8ezxjlckjkrn.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fv5yamchn8ezxjlckjkrn.webp" alt="Writing Debut Badge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It hit me while I was having my morning coffee, which is a brief period of the day when I can step back and reflect. I was overthinking the idea of blogging when I suddenly remembered my own "doer" mindset. A wave of frustration washed over me as I realized I was betraying my own rules. What kind of leader am I if I abandon my own principles?! I actually said out loud, &lt;strong&gt;"What the hell is wrong with you, man? Is that all you got?!"&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;That verbal reality check was all I needed. I gave myself a few days to commit to a topic and force it onto the page. That was how &lt;a href="https://dev.to/georgekobaidze/understanding-your-audience-as-a-software-engineer-4g3"&gt;Understanding Your Audience as a Software Engineer&lt;/a&gt; came to life. While the article itself isn't a masterpiece, it remains special to me. It marks the precise starting point of my writing addiction.&lt;/p&gt;

&lt;p&gt;I had no idea how the community would react to my first article, but I was genuinely surprised by how well it was received. And you know how it goes: when you realize you're actually decent at something and it's also a lot of fun, you can't stop. You just want to do it over and over again. That's exactly what happened to me. I just carried on.&lt;/p&gt;


&lt;h2&gt;
  
  
  Community Wellness Streak
&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.amazonaws.com%2Fuploads%2Farticles%2Fjbqzy89574ndfr6houm2.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.amazonaws.com%2Fuploads%2Farticles%2Fjbqzy89574ndfr6houm2.png" alt="Community Wellness Streak Badges"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Writing is great, but if you really want to contribute to your community at the highest level, you have to read other people's work and engage in the comments. Over time, I've developed a few rules I always follow whenever I leave a comment:&lt;/p&gt;
&lt;h4&gt;
  
  
  1. Always write a high-quality comment
&lt;/h4&gt;

&lt;p&gt;Be professional. This is your image as a community member and creator. Nobody likes to see an unprofessional or even slightly offensive comment on their posts. You won't make any friends by being arrogant.&lt;/p&gt;
&lt;h4&gt;
  
  
  2. Be a decent human being
&lt;/h4&gt;

&lt;p&gt;Express appreciation for other people's work. They took the time to deliver a product to you, whether it's an article, a project, or anything else. Show them that you appreciate that effort.&lt;/p&gt;
&lt;h4&gt;
  
  
  3. Include as many details as possible
&lt;/h4&gt;

&lt;p&gt;Be comprehensive about your ideas. A comment doesn't have to be just a few words. I've seen comments that are better than many articles. Write thought-provoking, interesting ideas and show your thinking process.&lt;/p&gt;
&lt;h4&gt;
  
  
  4. If you disagree, explain your point of view clearly
&lt;/h4&gt;

&lt;p&gt;Never offend or ridicule an author, even if you think a blog post is total nonsense. An offensive or mocking comment says a lot more about the commenter than it does about the author.&lt;/p&gt;
&lt;h4&gt;
  
  
  5. Don't be a hater. It will just eat you from the inside
&lt;/h4&gt;

&lt;p&gt;If someone else's post gathers way more engagement than yours, even if yours is 10 times longer and 20 times more complex, don't feel like you were treated unfairly. I usually write large, technical posts (some might even be a 20-minute read), and it's entirely natural that they won't get as many likes because not everyone is interested in that level of detail. I've seen two-paragraph posts reach incredible engagement because they are highly relatable and draw people in easily. Writing those kinds of articles is a real talent, and it's not easy at all. I myself am not great at it. Check out this very article, it's a monster, and it might not even get 10 likes. But that's okay with me because I write to share my knowledge and experience, not to chase and collect likes.&lt;/p&gt;
&lt;h4&gt;
  
  
  6. Never rush to press the "submit" button
&lt;/h4&gt;

&lt;p&gt;Read your comment again to make sure none of the previous five rules are broken.&lt;/p&gt;

&lt;p&gt;Sometimes, I get so absorbed in writing my own articles that I completely forget to check out what other people are publishing and leave comments. To fix this, I use any spare minutes I have to read at least one article a day. Whether you are writing or engaging with others, consistency is always the key. That's how I managed to reach the "8 Week Community Wellness Streak" badge, and I'm going for the "16 week" one next.&lt;/p&gt;


&lt;h2&gt;
  
  
  Top 7
&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.amazonaws.com%2Fuploads%2Farticles%2Fuanrm6tyny7nloj0t41e.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fuanrm6tyny7nloj0t41e.webp" alt="Top 7 Badge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's talk about the articles that were especially successful, the ones that made it onto the weekly top 7 list. I never imagined I would hit that milestone even once, let alone three times.&lt;/p&gt;
&lt;h3&gt;
  
  
  I'm All In on AI, But We Need to Talk About Vibe Coding
&lt;/h3&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__hidden-navigation-link"&gt;I'm All In on AI, But We Need to Talk About Vibe Coding&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2619292" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 24 '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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" id="article-link-2619292"&gt;
          I'm All In on AI, But We Need to Talk About Vibe Coding
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&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/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" 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;126&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              64&lt;span class="hidden s:inline"&gt; 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;
            16 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;This particular article took off faster than I could have imagined. It went so viral that I actually came across it in the Google feed on my phone.&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.amazonaws.com%2Fuploads%2Farticles%2F6wm0m6dujxe4rzour872.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.amazonaws.com%2Fuploads%2Farticles%2F6wm0m6dujxe4rzour872.jpg" alt="Google Feed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me tell you, sitting there looking at my own article on my homepage... that was a genuinely proud moment.&lt;/p&gt;

&lt;p&gt;I had been thinking about that idea for ages before I finally brought it to life and published it. I literally spent a solid &lt;strong&gt;three months&lt;/strong&gt; just thinking and planning. &lt;strong&gt;It even led to a podcast invitation&lt;/strong&gt;, after which I wrote a &lt;a href="https://dev.to/georgekobaidze/behind-the-mic-ai-and-the-vibe-coding-podcast-retrospective-3hfe"&gt;reflective article&lt;/a&gt; where I mentioned something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;...this was the result of nearly three months of thinking, writing, grinding, editing, and second-guessing. I kind of knew what Axl Rose must've felt like when releasing "November Rain" after working on it for nearly a decade. (Okay, I'm joking, I'm nowhere near Axl's level in any way. It's just a bad analogy. But as a rock fan, I had to make it.)...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That article definitely felt like I had created something special, and that was the moment I got totally addicted to writing, forever. As I mentioned, it even landed me a guest spot on a podcast, which was an incredibly cool experience.&lt;/p&gt;

&lt;h3&gt;
  
  
  20 Rules for Becoming THAT Manager (From a Principal Engineer's Perspective)
&lt;/h3&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3" class="crayons-story__hidden-navigation-link"&gt;20 Rules for Becoming THAT Manager (From a Principal Engineer’s Perspective)&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2705969" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 19 '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/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3" id="article-link-2705969"&gt;
          20 Rules for Becoming THAT Manager (From a Principal Engineer’s Perspective)
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/management"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;management&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/softskills"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softskills&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/leadership"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;leadership&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&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/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3" 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;19&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/20-rules-for-becoming-that-manager-from-a-principal-engineers-perspective-58n3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              15&lt;span class="hidden s:inline"&gt; 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;
            10 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;About a month later, I wrote "20 Rules for Becoming THAT Manager (From a Principal Engineer's Perspective)". &lt;/p&gt;

&lt;p&gt;It's funny because, unlike the vibe coding article, I wrote this one completely spontaneously. I was sitting in my car in a parking lot with time to kill, realized my laptop was in the backseat, and just started typing. That actually worked out perfectly because it allowed me to write purely from my raw experience as both an engineer and a development lead. &lt;/p&gt;

&lt;p&gt;That article was special. I wanted to create a set of notes for myself and for others on what it takes to be a good manager. I've seen all kinds of leaders in my career: the good, the great, the bad, and the absolute worst as well. Through it all, I gathered enough data to know exactly the kind of leader I want to be.&lt;/p&gt;

&lt;p&gt;Being a leader is vastly harder than most people think. Some take it for granted, while others overthink it entirely. The whole magic is in finding the fine balance between the two.&lt;/p&gt;

&lt;p&gt;By the way, I'm currently working on another article focused on leadership, and it's shaping up to be a good one. Stay tuned.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can AI Generate Binary Directly? Is It Feasible? Does It Make Sense?
&lt;/h3&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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;41&lt;span class="hidden s:inline"&gt; 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;
              Comments


              14&lt;span class="hidden s:inline"&gt; 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;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;A few weeks ago, I wrote about the concept of AI generating binary code directly, a topic that, for whatever reason, suddenly became the internet's favorite subject to debate. &lt;/p&gt;

&lt;p&gt;I noticed that most of the takes out there weren't very precise and were missing a few key points, so I decided to jump in and give my two cents. To my surprise, that piece also made it into the weekly top 7. Hitting that milestone three times in just under a year is a result I'm incredibly proud of.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;code&gt;C#&lt;/code&gt;
&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.amazonaws.com%2Fuploads%2Farticles%2Fawh1nz5ntnix4obst28m.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fawh1nz5ntnix4obst28m.webp" alt="C# Badge"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll admit, sometimes my articles can get intensely technical. Sometimes, they only resonate with specialists in that exact niche. But I love writing them. I'm a software engineer and I always have to scratch that itch to dive deep into the code, especially with .NET and C#.&lt;/p&gt;

&lt;p&gt;I've built things across a bunch of languages like JavaScript, Python, Java, TypeScript, even C and C++, but C# is still my baby.&lt;/p&gt;

&lt;p&gt;Getting that badge for the most popular C# article was an incredible feeling. Now? The goal is to collect a few more language badges to sit right next to it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Eight Year Club
&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.amazonaws.com%2Fuploads%2Farticles%2Fcv2elrkovp089ys07bhc.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fcv2elrkovp089ys07bhc.webp" alt="Eight Year Club"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And amidst all of this, I just completed my 8th year on dev.to.&lt;/p&gt;

&lt;p&gt;Sometimes a career in software can feel a bit dull and repetitive, but when you actually stop to reflect on the road so far, you realize how much you've been through. Honestly, you kind of question how on earth you remained sane.&lt;/p&gt;

&lt;p&gt;Especially for a guy like me who doesn't look back too often, it's almost shocking how much you can learn just by checking your rearview mirror. But one thing is for sure: I ain't going anywhere anytime soon. I'm going to be right here with this community until the day I retire, and I never plan on retiring.&lt;/p&gt;




&lt;h2&gt;
  
  
  GitHub Copilot CLI Challenge Winner
&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.amazonaws.com%2Fuploads%2Farticles%2F9xdal640sl89376lp6wu.webp" 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.amazonaws.com%2Fuploads%2Farticles%2F9xdal640sl89376lp6wu.webp" alt="GitHub Copilot CLI Challenge Winner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This right here is my biggest achievement on the platform, and easily one of the proudest moments of my entire career. &lt;/p&gt;

&lt;p&gt;I never actually thought I'd win my first real dev competition. Sure, I did some algorithmic challenges back in the day when I was still a junior developer, but those aren't real hackathons, they're mostly for the younger crowd, not a 30-year-old millennial.&lt;/p&gt;

&lt;p&gt;Taking first place in my debut, especially in a massive challenge with over 400 people, was surreal. But the absolute best part? I won it by building &lt;a href="https://github.com/georgekobaidze/metal-birds-watch" rel="noopener noreferrer"&gt;Metal Birds Watch&lt;/a&gt;. It was an idea I had been keeping in my head for years, and this hackathon gave me the perfect excuse to finally bring it to life. I still catch myself smiling whenever I think about seeing my name sitting there at number one.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The Making of Metal Birds Watch:&lt;/em&gt;&lt;br&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.amazonaws.com%2Fuploads%2Farticles%2F3mktmind6fii9l5q1jnr.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.amazonaws.com%2Fuploads%2Farticles%2F3mktmind6fii9l5q1jnr.png" alt="Metal Birds Watch Creation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you'd like to know the story behind this idea and project, check out the following article:&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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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;50&lt;span class="hidden s:inline"&gt; 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;
              Comments


              17&lt;span class="hidden s:inline"&gt; 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;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;





&lt;h2&gt;
  
  
  DEV Weekend Challenge Completion
&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.amazonaws.com%2Fuploads%2Farticles%2Fwnah9uy4rhmikzjg6293.webp" 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.amazonaws.com%2Fuploads%2Farticles%2Fwnah9uy4rhmikzjg6293.webp" alt="DEV Weekend Challenge Completion"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I took on this challenge because I love spontaneous, short-term challenges. They allow me to test my speed and give me the intense drive to build something from start to finish in record time. &lt;/p&gt;

&lt;p&gt;I wanted to create a project that would make people smile and feel a deep sense of pride in what they've created. The goal was to take their articles and turn them into something interactive, motivate the self-doubters to finally hit 'publish,' and even draw new people into the community. I was aiming for something totally unique... something actually fun.&lt;/p&gt;

&lt;p&gt;That's how &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive" rel="noopener noreferrer"&gt;Sunday DEV Drive&lt;/a&gt; was born - a browser game.&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.amazonaws.com%2Fuploads%2Farticles%2Fdofv79dm8xodd4xfaboe.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.amazonaws.com%2Fuploads%2Farticles%2Fdofv79dm8xodd4xfaboe.jpg" alt="Game Creation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might be thinking: a browser game built by a backend engineer? But it turned out much better than I ever 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.amazonaws.com%2Fuploads%2Farticles%2Fj13p4ucjf3puy4ods5wa.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.amazonaws.com%2Fuploads%2Farticles%2Fj13p4ucjf3puy4ods5wa.jpg" alt="Game Poster"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032" class="crayons-story__hidden-navigation-link"&gt;Sunday DEV Drive: A Synthwave Driving Experience Through Your DEV Community Articles&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
      &lt;a href="https://dev.to/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032" class="crayons-article__context-note crayons-article__context-note__feed"&gt;&lt;p&gt;DEV Weekend Challenge: Community&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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-3299096" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 1&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/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032" id="article-link-3299096"&gt;
          Sunday DEV Drive: A Synthwave Driving Experience Through Your DEV Community Articles
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag crayons-tag--filled  " href="/t/showdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;showdev&lt;/a&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/weekendchallenge"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;weekendchallenge&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/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032" 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;65&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              23&lt;span class="hidden s:inline"&gt; 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;
            10 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Well, I didn't win this challenge because you can't win every competition, however you can learn from each one. That said, the feedback I received was so incredibly amazing that it felt like winning a championship all on its own. Plus, the badge is absolutely gorgeous.&lt;/p&gt;




&lt;h2&gt;
  
  
  Still Not Convinced?!
&lt;/h2&gt;

&lt;p&gt;All of the things starting from writing my first article, happened within the span of a single year. If I can do all of this, so can you and you can achieve much more if you push harder than I did. &lt;/p&gt;

&lt;p&gt;It's not about becoming famous, earning more money, or chasing status. It's about proving to yourself that you are capable of doing it all, and actually having fun in the process. &lt;/p&gt;

&lt;p&gt;Whenever people doubt their skills or career choices, I always tell them the same thing: &lt;strong&gt;"If you lack confidence, build evidence."&lt;/strong&gt; Once you start taking action: coding, writing, recording, that output becomes all the evidence you need. Just try it and see yourself how your life changes.&lt;/p&gt;

&lt;p&gt;But I have a feeling you might still need a little more convincing. So, let's play a little game.&lt;/p&gt;




&lt;h2&gt;
  
  
  Time to Play the Game
&lt;/h2&gt;

&lt;p&gt;Don't worry, I'm not Triple H, so I'm not going to jump out and hit you with a sledgehammer. But depending on how you play, the result of this game might feel like it.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Game
&lt;/h4&gt;

&lt;p&gt;Imagine it is the year [current year + 10]. &lt;br&gt;
Take a moment to really immerse yourself in that future. &lt;br&gt;
You still haven't started building your personal projects or writing technical articles. You realize how much time you've lost and how much you could have accomplished in that decade. &lt;/p&gt;

&lt;p&gt;You are frustrated and annoyed at yourself for never taking that first step. You feel like you failed... you spent your prime years idle, and now nobody will ever know what could have been if you had just tried. You would give ANYTHING to start over, knowing exactly how much better you would do. But you can't go back in time. Sad, isn't it?&lt;/p&gt;

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

&lt;p&gt;Now, end your immersion. You are back in the present. You have just been gifted those 10 years back. Congratulations! You are the first person in the universe to be handed a decade of extra time to start over. &lt;/p&gt;

&lt;p&gt;So... are you really going to waste that chance again? &lt;/p&gt;

&lt;p&gt;Start NOW! Your journey begins right NOW!&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>wecoded</category>
      <category>dei</category>
      <category>career</category>
    </item>
    <item>
      <title>NoteRunway: Because Your Notion Workspace Deserves an Elite Crew</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 29 Mar 2026 20:54:06 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk</link>
      <guid>https://forem.com/georgekobaidze/noterunway-because-your-notion-workspace-deserves-an-elite-crew-53bk</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/notion-2026-03-04"&gt;Notion MCP Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;
What I Built

&lt;ul&gt;
&lt;li&gt;Explanatory Video&lt;/li&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;The Backstory&lt;/li&gt;
&lt;li&gt;The 7 Tools&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Show us the code&lt;/li&gt;

&lt;li&gt;

How I Used Notion MCP

&lt;ul&gt;
&lt;li&gt;The Architecture&lt;/li&gt;
&lt;li&gt;Why MCP and Not Just the API?&lt;/li&gt;
&lt;li&gt;Destructive Tool Safety&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

The Tech Behind It

&lt;ul&gt;
&lt;li&gt;Multi-Provider AI (BYOK)&lt;/li&gt;
&lt;li&gt;The Archive System&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Wrapping Up&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Explanatory Video
&lt;/h3&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/qtaKv66-8AY"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;NoteRunway&lt;/strong&gt;: an AI-powered workspace management tool that helps Notion power users clean up, audit, and command their workspace through a single interface.&lt;/p&gt;

&lt;p&gt;Think of it as a flight control tower for your Notion workspace. It scans for problems you didn't know you had, visualizes connections you couldn't see, and lets you talk to your workspace in plain English.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://noterunway.pilotronica.com/" rel="noopener noreferrer"&gt;Live Demo → noterunway.pilotronica.com&lt;/a&gt;&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2Fjhvpyj75zoebrfzinfya.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.amazonaws.com%2Fuploads%2Farticles%2Fjhvpyj75zoebrfzinfya.png" alt="Main Page" width="800" height="532"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Backstory
&lt;/h3&gt;

&lt;p&gt;I'm a Notion addict. Not the &lt;em&gt;"I use it for grocery lists"&lt;/em&gt; kind, rather the &lt;em&gt;"I have 400+ pages, nested databases inside databases, and a set of half-written ideas from 2 AM"&lt;/em&gt; kind.&lt;/p&gt;

&lt;p&gt;It all started in 2020, when I decided it was time to bring more order into my life. My notes were scattered everywhere, there was some structure, but not nearly enough. I needed something more powerful... something more organized.&lt;/p&gt;

&lt;p&gt;Then I discovered Notion and instantly knew it was exactly what I'd been looking for all along and didn't know existed.&lt;/p&gt;

&lt;p&gt;You know how it goes, at first, you're fully motivated. Everything's clean, structured, flawless. You're convinced this time you'll manage your notes perfectly.&lt;/p&gt;

&lt;p&gt;But sooner or later, every power user ends up in the same place: orphaned pages from long-forgotten projects, duplicate notes written three times because the first two vanished into the void, and dead links leading to pages you archived months ago.&lt;/p&gt;

&lt;p&gt;And somewhere in that chaos, there's probably a note with an API key you definitely didn't mean to paste and leave it forever. Have you ever pasted an API key or secret thinking "I'm gonna move it somewhere more secure later"? And that "later" doesn't really come, does it?&lt;/p&gt;

&lt;p&gt;I needed a tool that could see the bigger picture, something that could scan everything, something that'd surface what's broken, and help me fix it without blindly deleting content or forcing me to manually comb through bajillion pages.&lt;/p&gt;

&lt;p&gt;When the Notion MCP Challenge dropped, it clicked right away. I could build that tool, and give something back to the Notion community while I'm at it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 7 Tools
&lt;/h3&gt;

&lt;p&gt;NoteRunway packs 7 workspace management tools, split between pure scanners and AI-powered analyzers.&lt;/p&gt;

&lt;p&gt;Think of it as a crew of seven tools at your disposal, everything you need to keep your Notion workspace in top shape. Each one has a specific role: some scan your workspace to surface hidden issues, others go deeper to analyze patterns and give you smarter insights.&lt;/p&gt;

&lt;p&gt;Together, they cut through the clutter, highlight what actually needs attention, and help you clean things up without the risk of losing something important. No guesswork, no endless manual checks, just a clear view of your workspace and the tools to keep it running smoothly.&lt;/p&gt;

&lt;h4&gt;
  
  
  📊 Workspace Health Dashboard
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2F3we2wpydgjqhpob5slo1.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.amazonaws.com%2Fuploads%2Farticles%2F3we2wpydgjqhpob5slo1.png" alt="Dashboard" width="800" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your workspace at a glance. Total pages, top-level pages, recently edited, empty pages, and link density (how well-connected your workspace actually is).&lt;/p&gt;

&lt;p&gt;It's the "oh wow, I have &lt;em&gt;how many&lt;/em&gt; empty pages?" moment.&lt;/p&gt;

&lt;h4&gt;
  
  
  🔍 Duplicate Detection
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Ft5krg2jx52ji0y6tda54.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.amazonaws.com%2Fuploads%2Farticles%2Ft5krg2jx52ji0y6tda54.png" alt="Duplicate Detection" width="800" height="909"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where the AI earns its keep. NoteRunway fetches up to 100 pages with their content snippets, sends them to the LLM with a specialized system prompt, and gets back &lt;strong&gt;semantic duplicate groups&lt;/strong&gt; with similarity scores.&lt;/p&gt;

&lt;p&gt;Not just "same title" duplicates, it catches pages with different names but overlapping content. The AI picks a recommended "keep" version (⭐), and you choose which ones to archive.&lt;/p&gt;

&lt;h4&gt;
  
  
  🗑️ Garbage Collector
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fmx1ugdhm2iwc64kpxxgv.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.amazonaws.com%2Fuploads%2Farticles%2Fmx1ugdhm2iwc64kpxxgv.png" alt="Garbage Collector" width="800" height="655"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Rule-based detection across three categories:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Orphaned&lt;/strong&gt; — parent page was deleted, child is floating in limbo&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Empty&lt;/strong&gt; — zero content blocks (you created it and... forgot)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stale&lt;/strong&gt; — untouched for 90+ days (configurable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dry-run mode is on by default. You review everything before anything moves.&lt;/p&gt;

&lt;h4&gt;
  
  
  🔗 Dead Link Detector
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fk5hcxen8i5p6ea63hrtp.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.amazonaws.com%2Fuploads%2Farticles%2Fk5hcxen8i5p6ea63hrtp.png" alt="Dead Link Detector" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finds @mentions pointing to pages that no longer exist. Every broken mention is tracked back to its source page, so you know exactly where to fix it.&lt;/p&gt;

&lt;h4&gt;
  
  
  🔐 Sensitive Data Finder
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fqaq4phbecizlf0q05w50.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.amazonaws.com%2Fuploads%2Farticles%2Fqaq4phbecizlf0q05w50.png" alt="Sensitive Data Finder" width="800" height="867"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two-phase security scanner:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 1 (Regex):&lt;/strong&gt; Scans all pages against 13 patterns: API keys (OpenAI, Anthropic, Stripe, AWS, GitHub), PEM keys, JWTs, database URLs, passwords, credit cards. Findings are always &lt;strong&gt;partially redacted&lt;/strong&gt;, never exposing full values.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Phase 2 (AI Deep Scan):&lt;/strong&gt; Optionally sends page text to the LLM to catch natural-language secrets that regex misses. Things like &lt;em&gt;"the password is hunter2"&lt;/em&gt; or &lt;em&gt;"login: admin/secret123"&lt;/em&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  🕸️ Dependency Graph
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Fytw78didci1k27nudswl.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.amazonaws.com%2Fuploads%2Farticles%2Fytw78didci1k27nudswl.png" alt="Dependency Graph" width="800" height="653"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An interactive force-directed graph of your entire workspace. Pages are nodes (colored by depth), connections are edges (solid for parent-child, dashed for @mentions). Orphaned pages glow red.&lt;/p&gt;

&lt;p&gt;You can hover, click, collapse branches, and zoom around. It's surprisingly therapeutic to see your workspace as a living network.&lt;/p&gt;

&lt;h4&gt;
  
  
  💬 Semantic Ask (Agentic Chat)
&lt;/h4&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.amazonaws.com%2Fuploads%2Farticles%2Flygi7dt2on8c65a7zf71.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.amazonaws.com%2Fuploads%2Farticles%2Flygi7dt2on8c65a7zf71.png" alt="Semantic Ask" width="800" height="854"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A natural language interface to your workspace, powered by an agentic AI loop.&lt;/p&gt;

&lt;p&gt;Type something like &lt;em&gt;"Find all pages about authentication and summarize them"&lt;/em&gt; or &lt;em&gt;"Archive everything in the old-project folder."&lt;/em&gt; The AI breaks it into tool calls (search, read, analyze), feeds results back into its context, and proposes structured actions for your approval.&lt;/p&gt;

&lt;p&gt;It supports 5 action types: &lt;strong&gt;archive&lt;/strong&gt;, &lt;strong&gt;create&lt;/strong&gt;, &lt;strong&gt;rename&lt;/strong&gt;, &lt;strong&gt;append&lt;/strong&gt;, and &lt;strong&gt;update&lt;/strong&gt;, all with a human-in-the-loop confirmation step. No action executes without your explicit "yes."&lt;/p&gt;

&lt;p&gt;Just a heads-up: be cautious with destructive actions. Avoid updating or archiving critical data.&lt;/p&gt;

&lt;p&gt;This project is still in beta, and I don't want you to risk losing important information. As you know, AI isn't deterministic, and unexpected outcomes can happen.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show us the code
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Here's the repository:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;
        georgekobaidze
      &lt;/a&gt; / &lt;a href="https://github.com/georgekobaidze/noterunway" rel="noopener noreferrer"&gt;
        noterunway
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;NoteRunway&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;AI-Powered Notion Workspace Management&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Clean, organize, and command your Notion workspace with AI. Powered by the Notion MCP.&lt;/p&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/georgekobaidze/noterunway/./public/images/poster.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgeorgekobaidze%2Fnoterunway%2F.%2Fpublic%2Fimages%2Fposter.png" alt="NoteRunway"&gt;&lt;/a&gt;
&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://noterunway.pilotronica.com/" rel="nofollow noopener noreferrer"&gt;Live Demo → noterunway.pilotronica.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://nextjs.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/b283804a59db8759c5fd73dbdbfc9d4727842d46c29cf3870913538f602939d3/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6578742e6a732d31362d626c61636b3f6c6f676f3d6e6578742e6a73" alt="Next.js"&gt;&lt;/a&gt;
&lt;a href="https://typescriptlang.org/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/97fc638db3dd58f0590d3cc254cd7a8a65369aad17049aba215575dd3ec55dcb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f547970655363726970742d352d626c75653f6c6f676f3d74797065736372697074" alt="TypeScript"&gt;&lt;/a&gt;
&lt;a href="https://tailwindcss.com/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/94f426fcc79b2189030a2654451467767035d98e0a49f86a97d85899cde1c37f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5461696c77696e642d342d3338626466383f6c6f676f3d7461696c77696e64637373" alt="Tailwind CSS"&gt;&lt;/a&gt;
&lt;a href="https://github.com/notionhq/notion-mcp-server" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/48474cb9502d49ea599f8c751dcf6b374947a5037896e7f878fc55594430a649/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f74696f6e5f4d43502d322e322d3030303f6c6f676f3d6e6f74696f6e" alt="Notion MCP"&gt;&lt;/a&gt;
&lt;a href="https://sdk.vercel.ai/" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/dd83920e87915f248793d3164ca02e44d36683834ae469eadbc36a0382a7e3ca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f56657263656c5f41495f53444b2d362d3030303f6c6f676f3d76657263656c" alt="Vercel AI SDK"&gt;&lt;/a&gt;
&lt;a href="https://github.com/georgekobaidze/noterunway#license" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Table of Contents&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-overview" rel="noopener noreferrer"&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-features" rel="noopener noreferrer"&gt;Features&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-tech-stack" rel="noopener noreferrer"&gt;Tech Stack&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-architecture" rel="noopener noreferrer"&gt;Architecture&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-project-structure" rel="noopener noreferrer"&gt;Project Structure&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-ai-provider-support" rel="noopener noreferrer"&gt;AI Provider Support&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-mcp-integration" rel="noopener noreferrer"&gt;MCP Integration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-archive-system" rel="noopener noreferrer"&gt;Archive System&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-security" rel="noopener noreferrer"&gt;Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-scripts" rel="noopener noreferrer"&gt;Scripts&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-author" rel="noopener noreferrer"&gt;Author&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-acknowledgements" rel="noopener noreferrer"&gt;Acknowledgements&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/georgekobaidze/noterunway#-license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;NoteRunway&lt;/strong&gt; is a browser-based tool that helps Notion power users clean up, audit, and manage their workspace using a combination of deterministic scans and AI-powered intelligence via the &lt;a href="https://github.com/notionhq/notion-mcp-server" rel="noopener noreferrer"&gt;Notion MCP&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It connects to your Notion workspace through OAuth, runs server-side analysis via Next.js API routes, and provides a cyberpunk-themed UI for reviewing findings and approving actions.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Core Principles&lt;/h3&gt;

&lt;/div&gt;
&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Principle&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Zero Lock-in&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Your data stays in Notion. NoteRunway never stores workspace content.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Human-in-the-Loop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No destructive action runs without explicit user approval.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privacy First&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;AI keys stored only in your browser (BYOK). Sent per-request to NoteRunway APIs and never persisted server-side.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/georgekobaidze/noterunway" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  How I Used Notion MCP
&lt;/h2&gt;

&lt;p&gt;This is the core of the whole project. NoteRunway uses the &lt;a href="https://github.com/notionhq/notion-mcp-server" rel="noopener noreferrer"&gt;Notion MCP Server&lt;/a&gt; as the execution layer for all workspace interactions in the Semantic Ask feature.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser → Next.js API (SSE) → Vercel AI SDK → MCP Client → notion-mcp-server (stdio) → Notion API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's the flow:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;User sends a message&lt;/strong&gt; in the Ask interface&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vercel AI SDK&lt;/strong&gt; processes it with &lt;code&gt;streamText()&lt;/code&gt; and the selected LLM&lt;/li&gt;
&lt;li&gt;When the AI decides it needs workspace data, it &lt;strong&gt;calls tools&lt;/strong&gt;: &lt;code&gt;search_pages&lt;/code&gt;, &lt;code&gt;get_page&lt;/code&gt;, &lt;code&gt;get_page_content&lt;/code&gt;, &lt;code&gt;run_analysis&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;These tools route through &lt;strong&gt;MCPClient&lt;/strong&gt;, which communicates with the Notion MCP server over &lt;strong&gt;stdio&lt;/strong&gt; (JSON-RPC 2.0)&lt;/li&gt;
&lt;li&gt;The MCP server translates tool calls into &lt;strong&gt;Notion API requests&lt;/strong&gt; and returns structured results&lt;/li&gt;
&lt;li&gt;Results feed back into the AI's context for the next reasoning step (up to 10 steps)&lt;/li&gt;
&lt;li&gt;When the AI wants to make changes, it calls &lt;code&gt;propose_actions&lt;/code&gt;, which streams proposed actions to the UI for &lt;strong&gt;human approval&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Only after the user confirms does the action execute via MCP&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Why MCP and Not Just the API?
&lt;/h3&gt;

&lt;p&gt;I use &lt;strong&gt;both&lt;/strong&gt;. Here's the split:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NotionClient (direct SDK)&lt;/strong&gt; for bulk reads, workspace scans, pagination-heavy operations. It's faster for fetching 400 pages than routing through MCP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;MCPClient (MCP server)&lt;/strong&gt; for all writes like creating, archiving, renaming, updating pages. MCP provides a sandboxed execution layer with tool-level safety.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This hybrid approach gives me the &lt;strong&gt;speed&lt;/strong&gt; of direct API access with the &lt;strong&gt;safety&lt;/strong&gt; of MCP's tool calling protocol.&lt;/p&gt;

&lt;h3&gt;
  
  
  Destructive Tool Safety
&lt;/h3&gt;

&lt;p&gt;Any tool that modifies workspace data (patch, post-page, delete, move) requires an &lt;code&gt;approved: true&lt;/code&gt; flag. The AI can propose actions, but &lt;strong&gt;nothing destructive runs without the user clicking "Execute."&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Tech Behind It
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Technology&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Framework&lt;/td&gt;
&lt;td&gt;Next.js 16 (App Router)&lt;/td&gt;
&lt;td&gt;Full-stack React with API routes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI SDK&lt;/td&gt;
&lt;td&gt;Vercel AI SDK 6&lt;/td&gt;
&lt;td&gt;Unified streaming + tool calling across 4 providers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;MCP&lt;/td&gt;
&lt;td&gt;@notionhq/notion-mcp-server&lt;/td&gt;
&lt;td&gt;Notion workspace access via Model Context Protocol&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Visualization&lt;/td&gt;
&lt;td&gt;React Flow 11&lt;/td&gt;
&lt;td&gt;Force-directed graph for the dependency viewer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validation&lt;/td&gt;
&lt;td&gt;Zod 4&lt;/td&gt;
&lt;td&gt;Runtime schema validation for all API inputs/outputs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Styling&lt;/td&gt;
&lt;td&gt;Tailwind CSS 4 + shadcn/ui&lt;/td&gt;
&lt;td&gt;Cyberpunk aesthetic with accessible components&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Multi-Provider AI (BYOK)
&lt;/h3&gt;

&lt;p&gt;NoteRunway supports &lt;strong&gt;4 AI providers&lt;/strong&gt; with &lt;strong&gt;13 models&lt;/strong&gt;: OpenAI (GPT-5.4, GPT-5 Mini), Anthropic (Claude Opus 4.6, Haiku 4.5), xAI (Grok 4, Grok 3), and Google (Gemini 2.5 Pro/Flash).&lt;/p&gt;

&lt;p&gt;Your API key stays in your &lt;strong&gt;browser's localStorage&lt;/strong&gt;. It's sent per-request in an HTTP header, used once to create a provider instance, and discarded. NoteRunway's server never stores, logs, or persists your key.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Archive System
&lt;/h3&gt;

&lt;p&gt;Every destructive action creates an audit trail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NoteRunway Archive/
├── Duplicates/
│   └── [Audit Stub] Original Title
├── Garbage Collection/
│   └── [Audit Stub] Stale Page Name
└── Semantic Ask/
    └── [Audit Stub] Archived via Chat
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each audit stub contains a callout with the archive date, reason, and a faithful copy of the original content. The original page is soft-archived to Notion's trash (recoverable for 30 days).&lt;/p&gt;

&lt;p&gt;Nothing is ever truly deleted without a paper trail.&lt;/p&gt;




&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;NoteRunway started as a personal itch, a messy workspace and a dev challenge deadline. It turned into something I'm going to use every week.&lt;/p&gt;

&lt;p&gt;Building with the Notion MCP was a revelation. The ability to give an AI structured access to a workspace, with tool-level control over what it can read and write, opens up workflows that feel like magic. Ask a question, get an answer sourced from your actual pages. Propose a cleanup, review it, execute it. All in one flow.&lt;/p&gt;

&lt;p&gt;If you're a Notion power user drowning in pages, give it a spin: &lt;strong&gt;&lt;a href="https://noterunway.pilotronica.com/" rel="noopener noreferrer"&gt;noterunway.pilotronica.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And if you find an API key you forgot about in a meeting note... you're welcome. 😄&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Built with ☕ and too many late nights by &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;Giorgi Kobaidze&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>notionchallenge</category>
      <category>mcp</category>
      <category>ai</category>
    </item>
    <item>
      <title>Can AI Generate Binary Directly? Is It Feasible? Does It Make Sense?</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 08 Mar 2026 20:33:41 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62</link>
      <guid>https://forem.com/georgekobaidze/can-ai-generate-binary-directly-is-it-feasible-does-it-make-sense-b62</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
From Prompt to Binary Code

&lt;ul&gt;
&lt;li&gt;Is It Even Feasible?&lt;/li&gt;
&lt;li&gt;Is It Worth It?&lt;/li&gt;
&lt;li&gt;Things That Almost Everyone Gets Wrong&lt;/li&gt;
&lt;li&gt;So What Are the Actual Problems with This Approach?&lt;/li&gt;
&lt;li&gt;Generalized Prompt Repetition Formula&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;How Can AI Be Helpful for Modern Compilers?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Summary&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;Exciting, futuristic ideas tend to gain traction quickly. Whether they are realistic or not often matters less at first. After all, no one can truly prove an idea will work until someone actually attempts it. The concept alone can still be exciting enough to capture everyone's attention.&lt;/p&gt;

&lt;p&gt;However, that initial excitement often fades once people begin to analyze the complexities, trade-offs, and potential downsides. In many cases the idea ultimately proves to be feasible, but the path toward making it practical and usable can lead in directions no one initially anticipated.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Prompt to Binary Code
&lt;/h2&gt;

&lt;p&gt;In this article, I want to explore the idea of generating binary directly from a prompt, without first producing human-readable source code.&lt;/p&gt;

&lt;p&gt;In other words, the goal would be to bypass the traditional steps in the compilation pipeline that normally transform human-written code into a final executable binary.&lt;/p&gt;

&lt;p&gt;The process can be visualized like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Prompt → AI → Binary&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This approach eliminates many of the intermediate components typically involved in producing an executable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No source code required&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No compilation or interpretation needed&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No intermediate representation, such as IL in C#&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;On paper, this sounds appealing: so many steps are skipped, product creation could be faster and more streamlined, and AI could generate binary directly without worrying about programming languages or their specifications.&lt;/p&gt;

&lt;p&gt;It sounds like a logical next step, right?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Well... not quite.&lt;/strong&gt; This is far from the most practical approach, at least for the near, or even distant future.&lt;/p&gt;

&lt;p&gt;Let's break down why this idea is problematic, but before we do, let's quickly address one of the more controversial questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is It Even Feasible?
&lt;/h3&gt;

&lt;p&gt;Many people quickly dismiss this idea because they assume AI simply cannot generate binary directly. That's understandable, AI can only learn from the data that exists, and there's very little information about writing software directly in binary. After all, humans don't and can't do it (well unless your idea of fun is debugging a bajillion bits at 2 AM).&lt;/p&gt;

&lt;p&gt;However, that doesn't mean it's impossible (I mean training AI models, not debugging binary). Technically, it is feasible. You could take existing source code, there's no shortage of it, compile it to produce binary, and then create a &lt;code&gt;source code &amp;lt;-&amp;gt; binary code&lt;/code&gt; dataset to train AI models.&lt;/p&gt;

&lt;p&gt;As you might imagine, though, this would require astronomical amounts of data and computational resources, making it extremely expensive. Which brings us to the next question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is It Worth It?
&lt;/h3&gt;

&lt;p&gt;This question requires a deeper analysis on multiple levels. Let's examine each point one by one.&lt;/p&gt;

&lt;h4&gt;
  
  
  What's the Point of Source Code, Anyway?
&lt;/h4&gt;

&lt;p&gt;To explore this question, I'll refer back to &lt;strong&gt;my very first article on this platform&lt;/strong&gt; and link an important section for this context.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/understanding-your-audience-as-a-software-engineer-4g3" class="crayons-story__hidden-navigation-link"&gt;Understanding Your Audience as a Software Engineer&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2356479" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/understanding-your-audience-as-a-software-engineer-4g3" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 25 '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/understanding-your-audience-as-a-software-engineer-4g3" id="article-link-2356479"&gt;
          Understanding Your Audience as a Software Engineer
        &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/softwareengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwareengineering&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;a class="crayons-tag  crayons-tag--monochrome " href="/t/productivity"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;productivity&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/understanding-your-audience-as-a-software-engineer-4g3" 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/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;4&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/understanding-your-audience-as-a-software-engineer-4g3#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&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;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




&lt;p&gt;If you don't feel like reading another article, here's a brief summary of the key points from that section:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Software code isn't primarily for computers, it's for humans. Computers don't "understand" programming languages directly, they require translation into machine code via compilers, interpreters, or virtual machines. Programming languages are designed to be human-readable so developers can write, read, and maintain code effectively. Clear, structured, and well-documented code prevents confusion, reduces bugs, and avoids long-term technical debt. Writing with future maintainers (including yourself) in mind ensures smoother collaboration and easier maintenance as projects grow.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The main point is this: you don't write source code primarily for computers, otherwise, you'd be writing it in binary yourself. Source code exists for a very good reason: to be understandable by humans. It acts as an interface for developers to communicate with machines, giving them instructions and rules in a readable form. That's why we have coding best practices, naming conventions, design patterns, and so on. Compilers or CPUs don't care about any of that, it's all for us.&lt;/p&gt;

&lt;h4&gt;
  
  
  When You Take Away the Interface, the System Becomes Unusable
&lt;/h4&gt;

&lt;p&gt;As I mentioned, source code is the only ergonomic and sensible interface that developers currently understand and can use reliably. Nobody can read or write raw binary code directly. Think of source code like the steering wheel, gear selector, and pedals of a car, the binary code under the hood is the engine's "magic". Technically, you might try to operate the car without a steering wheel, but is it ergonomic or even feasible? Absolutely not!&lt;/p&gt;

&lt;p&gt;If we remove source code from the equation, the entire deterministic process goes out the window. From that point onward, there's no way to generate code while ensuring the resulting binary is exactly correct. We'll explore this in more detail later in the article.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This brings us to a common issue I've seen in many articles on this topic. They're not exactly wrong, but they often argue against the idea using points that are irrelevant in the context of what we've just discussed. Let's take a closer look at those arguments.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Things That Almost Everyone Gets Wrong
&lt;/h3&gt;

&lt;p&gt;In almost every article on this topic, authors point out a few issues with the idea of generating binary directly. Technically, their points are correct, but they often miss the core problem. Some of the common criticisms include:&lt;/p&gt;

&lt;h4&gt;
  
  
  Source Control Will Become Pointless
&lt;/h4&gt;

&lt;p&gt;Let's start with this one, as it's a somewhat controversial claim. The statement is partially correct, but not entirely.&lt;/p&gt;

&lt;p&gt;Technically, you can still store binaries in source control, manage releases, tags, versions, and all the other standard repository references. You can even switch between different versions, so many core features of source control would remain usable.&lt;/p&gt;

&lt;p&gt;However, one thing that would no longer be possible is code review - the very feature that makes source code so valuable in the first place. That said, using this as an argument against the entire idea feels a bit off, and here's why:&lt;/p&gt;

&lt;h4&gt;
  
  
  Code Review Will Become Impossible
&lt;/h4&gt;

&lt;p&gt;Absolutely, there's no doubt about it. Pull requests would just be an opaque sequence of binary data, providing no context at all. Sure, you might still see a bunch of "LGTM" comments, but on a serious note, without a tangible interface to review, what would there even be to review? This makes the argument largely irrelevant in the context of evaluating direct binary generation.&lt;/p&gt;

&lt;h4&gt;
  
  
  Security Auditing Will Become Impossible
&lt;/h4&gt;

&lt;p&gt;Of course, without human-readable source code, there would be no way to audit it for vulnerabilities, let alone fix any issues. This limitation is another obvious downside.&lt;/p&gt;

&lt;h4&gt;
  
  
  Libraries and Shared Source Code Will Become Pointless
&lt;/h4&gt;

&lt;p&gt;Yeah, again, just like everything else that relies on proper source code. Without source code, there are no best practices, naming conventions, project structure, modularity, or shared packages... basically none of the tools and patterns developers rely on. While this argument is technically correct, it's not really relevant in the context of evaluating direct binary generation.&lt;/p&gt;

&lt;p&gt;In this scenario, the only interface would be the prompt. &lt;strong&gt;Could natural English become a new unified programming language?&lt;/strong&gt; That's a fascinating question, but it's a topic for another article. For now, let's stay focused.&lt;/p&gt;

&lt;h3&gt;
  
  
  So What Are the Actual Problems with This Approach?
&lt;/h3&gt;

&lt;p&gt;There are quite a few challenges with this approach, and I hope I don't turn this into another 20-minute read (which, annoyingly, almost always happens to me).&lt;/p&gt;

&lt;h4&gt;
  
  
  Determinism Goes Out the Window
&lt;/h4&gt;

&lt;p&gt;When you write code in C#, it goes through several steps before becoming actual machine code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Compilation with Roslyn: the compiler parses your source code, performing lexical, syntax, and semantic analysis, along with some basic optimizations. It doesn't produce native code directly, instead, it emits CIL (Common Intermediate Language) instructions and metadata tables describing types, attributes, generics, and other information. All of this is packaged into a .NET assembly (a &lt;code&gt;.dll&lt;/code&gt; or &lt;code&gt;.exe&lt;/code&gt;) using the Portable Executable (PE) format.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Execution under the CLR: when the program runs in the Common Language Runtime (CLR), methods are compiled by the JIT compiler (Just-In-Time compiler):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A method is called for the first time&lt;/li&gt;
&lt;li&gt;JIT reads the IL instructions and metadata&lt;/li&gt;
&lt;li&gt;Performs runtime-aware optimizations such as inlining, escape analysis, and CPU-specific vectorizations&lt;/li&gt;
&lt;li&gt;Finally generates native machine code (x64, ARM, etc.) and caches it for future calls&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;In short, the pipeline looks like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;C# -&amp;gt; Roslyn -&amp;gt; IL + metadata (assembly) -&amp;gt; CLR JIT/AOT -&amp;gt; Native machine code&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This process is complex, but its key advantage is determinism: given the same input, the compiler will produce the exact same IL every time, and the JIT will produce logically equivalent native code. While runtime factors like tiered compilation (Tier 0 vs Tier 1) might produce different native code across runs, the logical behavior remains consistent.&lt;/p&gt;

&lt;p&gt;When you delegate this task to AI, however, determinism disappears. Not only can unpredictable issues arise, but the entire process becomes abstracted and uncertain, introducing significant risk.&lt;/p&gt;

&lt;h4&gt;
  
  
  No More Partial Changes
&lt;/h4&gt;

&lt;p&gt;Every time you want to make a change, like adding a small feature, the machine code would likely have to be regenerated from scratch. This is because machine code is a low-level representation with no modular structure, comments, or abstractions, so an AI can't easily patch just one part of it.&lt;/p&gt;

&lt;p&gt;Each new "build" could differ slightly from the last, increasing the risk that a previously working program might break completely with just a minor change. While in theory, binary patching is possible, it's extremely complex and error-prone.&lt;/p&gt;

&lt;p&gt;Without source code as an interface, you'd be forced to rely entirely on the AI model to fix issues, since the prompt would be your only way to interact with the system. You might end up imploring your AI model to fix a bug that needs to go to production today, but instead it just adds more and more bugs. A minor update could turn into a chaotic conversation with your AI: "No, not that part... the other part... wait, why is it doing this again?" - a scenario that's both unpredictable and, frankly, a little scary.&lt;/p&gt;

&lt;h4&gt;
  
  
  Waste of Precious Tokens
&lt;/h4&gt;

&lt;p&gt;Even today, when AI-assisted coding has become more common and models are well-trained, generating code is still expensive and consumes a lot of tokens. Now imagine AI generating binary code from scratch every time you need even the smallest feature. The whole project would have to be regenerated, wasting a huge number of tokens and it's unlikely to get it right on the first, second, or even fiftieth attempt. &lt;br&gt;
&lt;strong&gt;That's a multiplied token disaster.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Generalized Prompt Repetition Formula
&lt;/h3&gt;

&lt;p&gt;When each change might have a different number of failed attempts, the total number of prompts needed can be expressed as:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repetitions&lt;/strong&gt; = Σᵢ₌₁ⁿ (Failed_Attemptsᵢ + 1)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Where:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;n = total number of changes required
&lt;/li&gt;
&lt;li&gt;Failed_Attemptsᵢ = number of failed attempts for the i-th change
&lt;/li&gt;
&lt;li&gt;+1 accounts for the successful attempt of each change
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Suppose you need 3 changes, and the failed attempts per change are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change 1 → 2 failed attempts
&lt;/li&gt;
&lt;li&gt;Change 2 → 0 failed attempts
&lt;/li&gt;
&lt;li&gt;Change 3 → 5 failed attempts
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repetitions&lt;/strong&gt; = (2 + 1) + (0 + 1) + (5 + 1) = 3 + 1 + 6 = 10&lt;/p&gt;

&lt;p&gt;You would need &lt;strong&gt;10 total prompts&lt;/strong&gt; to get all changes successfully applied.&lt;/p&gt;

&lt;p&gt;And that's a very optimistic example, by the way. The &lt;code&gt;n&lt;/code&gt; variable can even be infinite, meaning, you'll never get your project to the desired state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Possible solution?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One approach could be to divide your product into small, deployable components (yes, we're talking microservices). Instead of regenerating the entire project from scratch, you'd regenerate only the specific part of the system that needs updating. For example, updating a notification service is far easier than rebuilding an entire banking system.&lt;/p&gt;

&lt;p&gt;However, this solution undermines the original idea. You'd end up managing a huge number of microservices, which, if you've ever worked on large systems, you know can be far more painful to maintain than a single monolith. In other words, this "fix" may solve one problem but introduces many others.&lt;/p&gt;

&lt;h4&gt;
  
  
  Performance Issues
&lt;/h4&gt;

&lt;p&gt;As I mentioned earlier, modern compilers are extremely sophisticated. Entire teams focus solely on making compilers as accurate, optimized, and fast as possible. Today's compilers can generate machine code in milliseconds, and they do so deterministically.&lt;/p&gt;

&lt;p&gt;For example, the Roslyn compiler (which I mentioned earlier) supports incremental analysis, meaning it can run continuously as you type. Instead of recompiling everything, it only updates the syntax tree and dependent symbols. While this feature is mostly used in IDEs, it's a major performance booster.&lt;/p&gt;

&lt;p&gt;Roslyn also leverages heavy caching and immutable data structures, so previously computed semantic information can be reused. On top of that, it supports parallel compilation, allowing multiple files to be processed simultaneously across CPU cores.&lt;/p&gt;

&lt;p&gt;We could talk about Roslyn all day, but that's a completely different topic. The main point here is: when you bypass these sophisticated compilers, all these performance advantages disappear. You're left with just the AI, which works non-deterministically and can waste massive amounts of time, resources, and performance.&lt;/p&gt;

&lt;h4&gt;
  
  
  There Are Many Different Platforms (Architectures)
&lt;/h4&gt;

&lt;p&gt;Every platform requires its own specific binaries. For example, a binary built for x86 won't run on ARM. Compilers handle this automatically, they know exactly what to generate.&lt;/p&gt;

&lt;p&gt;With AI generating binaries directly, you'd need to produce separate versions for each architecture. Remember our earlier formula for prompt repetitions, which accounted for failed attempts per change? Now we have another variable: the number of architectures.&lt;/p&gt;

&lt;p&gt;If you previously calculated:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Repetitions = Σᵢ₌₁ⁿ (Failed_Attemptsᵢ + 1)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;We now need to multiply by the number of architectures (let's call it A):&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Repetitions = Σᵢ₌₁ⁿ ((Failed_Attemptsᵢ + 1) * A)&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;n = total number of changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Failed_Attemptsᵢ = failed attempts for the i-th change&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A = number of target architectures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;+1 accounts for the successful attempt of each change&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For complex projects, this can quickly explode. Multiply by 3–5 or more architectures, and remember that each attempt might fail multiple times. Suddenly, a small change could require hundreds or even thousands of AI prompts, burning through tokens and time at an alarming rate.&lt;/p&gt;

&lt;p&gt;Are you still excited about this idea?&lt;/p&gt;

&lt;h3&gt;
  
  
  How Can AI Be Helpful for Modern Compilers?
&lt;/h3&gt;

&lt;p&gt;AI should never be the main driver of compilation, because developers rely on compilers to be reliable, predictable, deterministic, and fast. AI simply can't guarantee any of that as the primary engine.&lt;/p&gt;

&lt;p&gt;However, AI shines as an assistant. It can provide refactoring suggestions, performance improvements, or code optimizations, effectively taking some of the load off the compiler and helping developers write better code.&lt;/p&gt;

&lt;p&gt;A realistic workflow could look like this:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Source code -&amp;gt; Roslyn -&amp;gt; AI assistant -&amp;gt; Suggestions&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Here, the AI doesn't replace the compiler, it analyzes the intermediate structures that Roslyn generates (syntax trees, semantic models, metadata) and provides actionable insights back to the developer. Think of it as a co-pilot rather than the engine: it makes your work smoother without risking determinism or performance. But even this is just an abstract concept.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This whole "AI generates binaries directly" idea sounds sci-fi and Cyberpunky, which is undeniably fun. But reality doesn't care about coolness, it cares about whether the idea actually solves a problem. In this case, it clearly doesn't. In fact, it introduces a mountain of new problems: non-determinism, wasted tokens, impossible debugging, and insane complexity across multiple architectures.&lt;/p&gt;

&lt;p&gt;Maybe one day in the far future, people will rely on prompts instead of source code, and developers won't even touch the code anymore. But even then, the core problem remains: without understandable source code and deterministic compilation, maintaining, debugging, and collaborating on software becomes almost impossible. The interface is gone, and with it, control is gone.&lt;/p&gt;

&lt;p&gt;At the end of the day, AI can be amazing for coding, but let's leave the heavy lifting of compilation to our compilers. The AI's real value is as a smart assistant, not the engine that drives everything.&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>ai</category>
      <category>compilers</category>
      <category>programming</category>
    </item>
    <item>
      <title>Sunday DEV Drive: A Synthwave Driving Experience Through Your DEV Community Articles</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 01 Mar 2026 20:32:00 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032</link>
      <guid>https://forem.com/georgekobaidze/sunday-dev-drive-a-synthwave-driving-experience-through-your-dev-community-articles-5032</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28"&gt;DEV Weekend Challenge: Community&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Community
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Let's Start from the Very Beginning
&lt;/h3&gt;

&lt;p&gt;I love weekends. Not because I want to escape coding, quite the opposite. As a full-time principal engineer, my weekdays belong to meetings, architecture decisions, reviews, and production responsibilities. Evenings are short. Energy is limited. But weekends? Weekends are different. Weekends are pure.&lt;/p&gt;

&lt;p&gt;They're the only time I can dedicate an entire day to building something just for the joy of it. Writing. Experimenting. Creating.&lt;/p&gt;

&lt;p&gt;Recently, I started participating in DEV challenges and it's been one of the best decisions I've made in a long time. There's something powerful about building in public. Shipping something playful and sharing it with your community.&lt;/p&gt;

&lt;p&gt;This challenge, in particular, just felt right - &lt;strong&gt;the weekend challenge&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  To the Community I Call Home
&lt;/h3&gt;

&lt;p&gt;The DEV community has been my home since 2017, since the very beginning of my &lt;strong&gt;professional&lt;/strong&gt; software engineering journey.&lt;/p&gt;

&lt;p&gt;More often than not, I found comfort here when things weren't going well. Especially in those early years. When imposter syndrome was loud. When mistakes felt heavier. When growth felt slow.&lt;/p&gt;

&lt;p&gt;Reading other developers' stories helped. Seeing their struggles. Their wins. Their lessons. It all reminded me that we're all just figuring it out.&lt;/p&gt;

&lt;p&gt;Now, years later, I wanted to give something back.&lt;/p&gt;

&lt;p&gt;I wanted to build something that would:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make fellow members smile.&lt;/li&gt;
&lt;li&gt;Help them feel proud of their work.&lt;/li&gt;
&lt;li&gt;Turn their articles into something interactive.&lt;/li&gt;
&lt;li&gt;Encourage passive members to write.&lt;/li&gt;
&lt;li&gt;Maybe even inspire non-members to join.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Something actually different... something actually fun...&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  So I Built Sunday DEV Drive
&lt;/h3&gt;

&lt;p&gt;Sunday DEV Drive is a game, but not in the traditional sense.&lt;/p&gt;

&lt;p&gt;There are no bosses to defeat, no side quests, no objectives, no timers.&lt;/p&gt;

&lt;p&gt;It's intentionally different.&lt;/p&gt;

&lt;p&gt;It's a browser-based synthwave driving game where your DEV Community articles become neon billboards along an endless procedural road. You type in a username, and within seconds you're cruising through a retro-futuristic cityscape with your article titles, cover images, and actual quotes from your writing towering above the highway.&lt;/p&gt;

&lt;p&gt;And as you drive, billboards around the city display articles - yours or someone else's, pulled dynamically using the &lt;a href="https://developers.forem.com/api/v1" rel="noopener noreferrer"&gt;DEV API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Imagine cruising through a digital city and suddenly seeing your own words glowing above you.&lt;/p&gt;

&lt;p&gt;Or discovering another developer's article while driving past a virtual skyline.&lt;/p&gt;

&lt;p&gt;It's not about winning, it's about reflecting, it's all about feeling proud and transforming written content into a spatial experience.&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.amazonaws.com%2Fuploads%2Farticles%2F3tu657tczdsqraa820nt.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.amazonaws.com%2Fuploads%2Farticles%2F3tu657tczdsqraa820nt.png" alt="Overhead billboard"&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fso02kijcvqpwryxbd80o.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.amazonaws.com%2Fuploads%2Farticles%2Fso02kijcvqpwryxbd80o.png" alt="Roadside billboard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  It Works in Three Modes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Your articles&lt;/strong&gt;: Enter any DEV username. The game fetches their posts via the DEV API, extracts real quotes from article bodies, and renders them onto billboard textures in real-time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Motivational mode&lt;/strong&gt;: If a user has an account but no articles yet, every billboard becomes an encouraging message with "Click here to start writing!" - each one linking directly to &lt;code&gt;dev.to/new&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test drive&lt;/strong&gt;: No DEV account? No problem. Take a demo spin and let the game convince you to join the community, every billboard becomes an invitation.&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.amazonaws.com%2Fuploads%2Farticles%2Fl8hn2dttfak4o9zy29n6.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.amazonaws.com%2Fuploads%2Farticles%2Fl8hn2dttfak4o9zy29n6.png" alt="Invitation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every billboard is clickable. See a post you want to read? Click it, and it opens in a new tab.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Beyond billboards, green road signs display your profile stats as you drive: total articles, lifetime reactions, reading time, your top post, favorite tags, and the date you joined DEV.&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.amazonaws.com%2Fuploads%2Farticles%2Fjqidtgqn3647xpy69e3b.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.amazonaws.com%2Fuploads%2Farticles%2Fjqidtgqn3647xpy69e3b.png" alt="Road sign"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But wait, there's more.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can even switch to first-person mode and drive straight from the cabin for full immersion.&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.amazonaws.com%2Fuploads%2Farticles%2Frofo6uyk7gkaphfd0048.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.amazonaws.com%2Fuploads%2Farticles%2Frofo6uyk7gkaphfd0048.png" alt="Interior mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Idea Behind It
&lt;/h3&gt;

&lt;p&gt;We usually consume articles passively, scrolling on a feed. But what if your writing became part of a world? What if your thoughts lived on digital billboards? What if discovering developers felt like exploring a city instead of browsing a list?&lt;/p&gt;

&lt;p&gt;Sunday DEV Drive turns articles into scenery. It makes community content feel tangible.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Than Just a Game
&lt;/h3&gt;

&lt;p&gt;At its core, this project is a thank-you letter.&lt;/p&gt;

&lt;p&gt;To the platform.&lt;br&gt;
To the writers.&lt;br&gt;
To the readers.&lt;br&gt;
To the beginners who are still doubting themselves.&lt;/p&gt;

&lt;p&gt;If you've ever published even one article, you deserve to see it shining in neon.&lt;/p&gt;

&lt;p&gt;If you've been thinking about writing, maybe this is your sign. WHAT ARE YOU WAITING FOR? START NOW. A year from now, you'll wish you'd started today. Regret is avoidable by taking action.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Welcome to Sunday DEV Drive!&lt;/strong&gt; 🚗✨&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Try it yourself: 🔗 &lt;strong&gt;&lt;a href="https://sundaydevdrive.pilotronica.com" rel="noopener noreferrer"&gt;sundaydevdrive.pilotronica.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Try it with your own DEV username, or just hit "Take a test drive" to jump right in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GAME CONTROLLER SUPPORT INCLUDED&lt;/strong&gt; &lt;br&gt;
Plug in a controller and enjoy the experience.&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.amazonaws.com%2Fuploads%2Farticles%2Fb8ynmhavpn6z33b2nz14.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.amazonaws.com%2Fuploads%2Farticles%2Fb8ynmhavpn6z33b2nz14.png" alt="Controls"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;The entire codebase is public, dive into the repository and take a look:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;
        georgekobaidze
      &lt;/a&gt; / &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive" rel="noopener noreferrer"&gt;
        sunday-dev-drive
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A synthwave driving experience through your DEV Community articles
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Sunday DEV Drive&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/georgekobaidze/sunday-dev-drive/assets/poster.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgeorgekobaidze%2Fsunday-dev-drive%2Fassets%2Fposter.jpg" alt="Sunday DEV Drive"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;
  &lt;strong&gt;A synthwave driving experience through your DEV Community articles&lt;/strong&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive/stargazers" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/dc40801d3314769e357648417281c3b429caffb0d7fbe6c5aa5b045788a46f38/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f67656f7267656b6f626169647a652f73756e6461792d6465762d6472697665" alt="Stars"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive/issues" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/bfdb646fc6496695a1c0db21486b9223c70422e7914aa9205cb9c99aa078d140/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f67656f7267656b6f626169647a652f73756e6461792d6465762d6472697665" alt="Issues"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive/actions" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/c9c6e62ffd538f0c8140df50d8d95cbd561421ef7aa4d183e670aca96817b364/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f67656f7267656b6f626169647a652f73756e6461792d6465762d64726976652f6465706c6f792d70616765732e796d6c3f6272616e63683d6d61696e" alt="Build Status"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive#live-demo" rel="noopener noreferrer"&gt;Live Demo&lt;/a&gt; •
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive#features" rel="noopener noreferrer"&gt;Features&lt;/a&gt; •
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive#controls" rel="noopener noreferrer"&gt;Controls&lt;/a&gt; •
  &lt;a href="https://github.com/georgekobaidze/sunday-dev-drive#how-it-works" rel="noopener noreferrer"&gt;How It Works&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Live Demo&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;🔗 &lt;strong&gt;&lt;a href="https://sundaydevdrive.pilotronica.com" rel="nofollow noopener noreferrer"&gt;sundaydevdrive.pilotronica.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Enter your &lt;a href="https://dev.to" rel="nofollow"&gt;DEV Community&lt;/a&gt; username, hit &lt;strong&gt;Start Driving&lt;/strong&gt;, and cruise through a neon-lit synthwave world where your articles appear as roadside billboards. Each billboard shows a title, cover image, and a snippet from the article body. Click any to open the full post.&lt;/p&gt;

&lt;p&gt;Built for the &lt;a href="https://dev.to/challenges/weekend-2026-02-28" rel="nofollow"&gt;DEV Weekend Challenge: Build for Your Community&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Your Articles as Billboards&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Roadside and overhead signs generated from your real DEV posts, complete with cover images, snippets, and reaction counts.&lt;/p&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/georgekobaidze/sunday-dev-drive/assets/screenshots/overhead_billboards.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgeorgekobaidze%2Fsunday-dev-drive%2Fassets%2Fscreenshots%2Foverhead_billboards.jpg" alt="Overhead"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/georgekobaidze/sunday-dev-drive/assets/screenshots/roadside_banner.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgeorgekobaidze%2Fsunday-dev-drive%2Fassets%2Fscreenshots%2Froadside_banner.jpg" alt="Roadside"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Stat Signs Along the Road&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Green road signs display your profile stats: total articles, reactions, reading time, top post, favorite tags, and join date.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/georgekobaidze/sunday-dev-drive/assets/screenshots/road_signs.jpg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fgeorgekobaidze%2Fsunday-dev-drive%2Fassets%2Fscreenshots%2Froad_signs.jpg" alt="Roadside"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Keyboard &amp;amp; gamepad support&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Drive with arrow keys or plug in a controller. Full analog steering, throttle, and a right-stick orbit…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/georgekobaidze/sunday-dev-drive" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;Don't judge the JavaScript too harshly, I come from the land of APIs and databases - I'm a back-end developer through and through.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Stack
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Three.js&lt;/strong&gt; (r170) - 3D rendering, loaded via ES module import maps from CDN&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Vanilla JavaScript&lt;/strong&gt; - 12 ES modules, zero build step, zero bundler, zero npm dependencies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Canvas API&lt;/strong&gt; - Every billboard and road sign texture is drawn programmatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DEV API&lt;/strong&gt; - Public endpoints, no API key, no backend&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No React. No Vite. No webpack. Open &lt;code&gt;index.html&lt;/code&gt; with any static file server and drive.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Architecture
&lt;/h3&gt;

&lt;p&gt;The entire project is 12 ES modules with a clean dependency graph and zero circular imports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scene.js ← road.js ← buildings.js
                    ← car.js ← camera.js
                              ← input.js
         ← billboards.js ← stats.js ← api.js
main.js imports everything
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each module owns its domain: &lt;code&gt;road.js&lt;/code&gt; generates the path, &lt;code&gt;car.js&lt;/code&gt; builds the car, &lt;code&gt;billboards.js&lt;/code&gt; handles the article-to-texture pipeline. The &lt;code&gt;main.js&lt;/code&gt; entry point wires them together and runs the animation loop.&lt;/p&gt;

&lt;h3&gt;
  
  
  Procedural Road Generation: Stochastic Steering
&lt;/h3&gt;

&lt;p&gt;The road is infinitely generated as you drive. There's no predefined track, it grows segment by segment using a stochastic steering algorithm:&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;growPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&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;pathTurnCountdown&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;pathTurnRate&lt;/span&gt;      &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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;random&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.5&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.042&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;pathTurnCountdown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&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;floor&lt;/span&gt;&lt;span class="p"&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;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;pathHead&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;pathTurnRate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;pathData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pathHead&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clone&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;angle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;pathHead&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="nx"&gt;pathHead&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&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;Vector3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;pathHead&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&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;pathHead&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;SEGMENT_LEN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;pathHead&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&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;pathHead&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;SEGMENT_LEN&lt;/span&gt;
    &lt;span class="p"&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;p&gt;Every few segments, a new random turn rate and duration are chosen. Because the turn rate &lt;em&gt;accumulates&lt;/em&gt; over multiple segments rather than being applied instantly, the road produces smooth, organic curves, gentle sweeps, not jarring zigzags. Randomizing both the magnitude (&lt;code&gt;0.042&lt;/code&gt; range) and the duration (&lt;code&gt;4–10 segments&lt;/code&gt;) creates surprising variation from very simple math.&lt;/p&gt;

&lt;p&gt;The road surface itself is a ribbon mesh: a sliding window of 200 segments rebuilt from raw &lt;code&gt;BufferGeometry&lt;/code&gt;. For each segment, perpendicular edge points are computed using the path angle:&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;rx&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;pd&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rz&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;pd&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&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="nx"&gt;rx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ROAD_WIDTH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Left edge&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;hx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pos&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="nx"&gt;rx&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;ROAD_WIDTH&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Right edge&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ribbon follows the car. When you've driven far enough, the mesh is rebuilt centered around your position. The road is always beneath you, and always extends into the horizon.&lt;/p&gt;

&lt;h3&gt;
  
  
  Canvas-Rendered Billboard Textures
&lt;/h3&gt;

&lt;p&gt;This is where the DEV API meets the Canvas API. Every billboard texture is a &lt;code&gt;512×768&lt;/code&gt; canvas (roadside) or &lt;code&gt;1024×512&lt;/code&gt; canvas (overhead), painted section by section:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Header bar&lt;/strong&gt; - neon-bordered strip with author and reaction count&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cover image&lt;/strong&gt; - letterboxed from the article's &lt;code&gt;cover_image&lt;/code&gt; URL, loaded asynchronously&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Snippet&lt;/strong&gt; - an actual quote extracted from the article body&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Footer&lt;/strong&gt; - reading time and tag display&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The tricky part: cover images load &lt;em&gt;after&lt;/em&gt; the texture is already applied to the 3D mesh. Three.js handles this beautifully with &lt;code&gt;tex.needsUpdate = true&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cover_image&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;img&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Image&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;crossOrigin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anonymous&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onload&lt;/span&gt; &lt;span class="o"&gt;=&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="nf"&gt;drawImageLetterbox&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ch&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;tex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;needsUpdate&lt;/span&gt; &lt;span class="o"&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;// GPU re-uploads on next frame&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nx"&gt;img&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;article&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cover_image&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;For articles without cover images, the cover area becomes a playful "404 / cover_image: null / (the author was too busy)" message, complete with a retro grid background. In motivational mode, it reads "Click here to start writing!" instead.&lt;/p&gt;

&lt;h3&gt;
  
  
  Snippet Extraction: Turning Markdown Into Billboard Quotes
&lt;/h3&gt;

&lt;p&gt;Simply showing article titles on billboards wouldn't be enough. I wanted actual &lt;em&gt;quotes&lt;/em&gt; from people's writing. But the DEV API returns raw Markdown, not clean prose. The extraction pipeline strips away code blocks, images, links, and headers, then picks paragraphs in a sweet spot - long enough to be meaningful, short enough to fit a billboard.&lt;/p&gt;

&lt;p&gt;The 60-400 character filter is crucial. Too short and you get orphaned sentences. Too long and the text overflows the billboard canvas. The result: clean, readable quotes that actually represent what someone wrote.&lt;/p&gt;

&lt;h3&gt;
  
  
  Car Physics: The Struggle Effect When Both Pedals Are Pressed
&lt;/h3&gt;

&lt;p&gt;The driving model is simple but has one detail I'm proud of. When a player presses both throttle and brake simultaneously (a common thing with gamepads), instead of canceling out, the car settles into a "struggle" state, which is basically low speed, high engine strain:&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;throttle&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;brake&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;struggle&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;maxSpeed&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.08&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;struggle&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="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.04&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;The speed converges to 8% of max through lerp smoothing. It simulates the feeling of fighting the brakes, the car doesn't stop, doesn't accelerate, just vibrates with restrained energy. It's a small detail but it makes the physics feel &lt;em&gt;alive&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Acceleration also uses diminishing returns, the faster you're going, the harder it is to go faster:&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;speedRatio&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;maxSpeed&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;effectiveAccel&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="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="nx"&gt;speedRatio&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.85&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single line replaces what would otherwise be a complex drag model. At zero speed, you get 100% acceleration. At top speed, you get 15%. The curve in between is completely smooth.&lt;/p&gt;

&lt;h3&gt;
  
  
  The 25-Article Shuffle
&lt;/h3&gt;

&lt;p&gt;The DEV API has a quirk: the list endpoint returns titles and metadata, but not the full article body. To get actual text for snippet extraction, you need a separate request per article. For a user with hundreds of posts, that's hundreds of requests - too slow and too aggressive.&lt;/p&gt;

&lt;p&gt;And I'm not planning to brutally overload our favorite creators' platform. I'll be easy on it. So Jess, Ben, Peter, if you're reading this, don't worry, I got you.😄&lt;/p&gt;

&lt;p&gt;The solution: shuffle the full article list and deep-fetch only 25 random articles. The rest get their &lt;code&gt;description&lt;/code&gt; field as a fallback snippet:&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;shuffled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;random&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.5&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;toFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;shuffled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for &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;art&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;toFetch&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;r&lt;/span&gt; &lt;span class="o"&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="s2"&gt;`https://dev.to/api/articles/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;art&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;art&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_snippets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;art&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&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;continue&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;full&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;art&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_snippets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractSnippets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;full&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body_markdown&lt;/span&gt; &lt;span class="o"&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;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;350&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;Each request has a 350ms delay to respect rate limits. If the API returns 429 (Too Many Requests), it gracefully falls back to the description instead of failing. The player never notices, they just see billboards with quotes. Whether those quotes came from a full article parse or a description fallback is invisible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Billboard Click Detection via Raycasting
&lt;/h3&gt;

&lt;p&gt;Clicking a 3D billboard to open an article isn't trivial in a 3D scene. The solution is Three.js raycasting, converting a 2D mouse position into a 3D ray, then testing intersection against billboard geometry.&lt;/p&gt;

&lt;p&gt;Each billboard stores its article URL in &lt;code&gt;userData&lt;/code&gt;. The raycast checks both front and back panels, so billboards work no matter which direction you're looking at them from. The &lt;code&gt;orbit.active&lt;/code&gt; guard prevents accidental clicks during camera rotation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a Car from 46 Boxes
&lt;/h3&gt;

&lt;p&gt;When I was a kid, I'd grab random little wooden scraps nobody seemed to need (or at least I thought nobody needed), hammer them together into a rough car shape, and nail four bottle caps on as wheels. Perfect toy car. Good times.&lt;/p&gt;

&lt;p&gt;Who would've thought that, more than 20 years later, the same "stack-and-nail" approach would actually come in handy... in code.&lt;/p&gt;

&lt;p&gt;There are no 3D models in this project. Every part of the car like body, cabin, hood, trunk, wheels, rims, windows, dashboard, headlights, tail/brake/reverse lights, steering wheel, interior screens, is built entirely from BoxGeometry and CylinderGeometry primitives, carefully stacked and positioned by hand.&lt;/p&gt;

&lt;p&gt;And boy did I spend a lot of time on that! Totally worth it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Lower body → Mid body → Hood → Trunk → Cabin
→ 4× Wheels (cylinder + torus rim)
→ 4× Windows (transparent glass material)
→ Dashboard with neon trim + dual screens
→ Steering wheel (torus + cylinder spokes)
→ Headlights (emissive mesh + PointLight)
→ Tail/brake/reverse lights
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The steering wheel actually rotates when you turn:&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;sw&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;userData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;steeringWheel&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="nx"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;sw&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rotation&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="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="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visible only in interior camera mode, but it's there. These kinds of details don't matter until they do.&lt;/p&gt;

&lt;h3&gt;
  
  
  So Much More to Talk About
&lt;/h3&gt;

&lt;p&gt;This project was a blast to build. Every component of the game required a ton of thought, and I learned so much along the way. What I've shared here are just the most exciting parts, there are plenty of other fascinating details. If I included everything, I'd probably end up writing a book. Maybe that's a story for another day.&lt;/p&gt;

&lt;h3&gt;
  
  
  What I Learned This Weekend
&lt;/h3&gt;

&lt;p&gt;Building a 3D game with zero dependencies and zero build tools in a weekend taught me a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Canvas API is absurdly powerful for textures.&lt;/strong&gt; Every billboard, every road sign, the sun, the skyline, all drawn with &lt;code&gt;fillRect&lt;/code&gt;, &lt;code&gt;fillText&lt;/code&gt;, and &lt;code&gt;drawImage&lt;/code&gt;. No texture files needed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ES modules are production-ready.&lt;/strong&gt; Import maps + CDN + &lt;code&gt;type="module"&lt;/code&gt; gives you a complete module system with zero tooling. Twelve modules, clean dependency graph, no bundler.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple physics beat complex physics.&lt;/strong&gt; A one-line diminishing-returns formula (&lt;code&gt;1 - speedRatio * 0.85&lt;/code&gt;) gives more "feel" than a proper friction simulation would. Games aren't simulations, they're about how things feel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The DEV API is a goldmine.&lt;/strong&gt; Public, no auth, generous rate limits, full Markdown body access. Building &lt;em&gt;for&lt;/em&gt; the community with the community's own API felt right.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This project was built in a weekend with coffee, a gamepad, and a deep appreciation for the DEV Community. Every article you've written deserves to be a neon billboard on an endless synthwave highway.&lt;/p&gt;

&lt;p&gt;Now it's your turn. Take your car for a spin, share your journey in the comments, grab screenshots and show it off to your friends, colleagues... anyone! I'd love to hear everyone's reaction. Let's show everyone that we're by far the best community.&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
      <category>showdev</category>
    </item>
    <item>
      <title>Could Vibe Coding Be the Missing Communication Link Between PMs and Developers?</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Tue, 17 Feb 2026 17:08:33 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/could-vibe-coding-be-the-missing-communication-link-between-pms-and-developers-3bch</link>
      <guid>https://forem.com/georgekobaidze/could-vibe-coding-be-the-missing-communication-link-between-pms-and-developers-3bch</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;
Building a Product Is a Team Sport

&lt;ul&gt;
&lt;li&gt;No Developer Is Perfect And That's Okay&lt;/li&gt;
&lt;li&gt;No Project Manager Is Perfect And That's Okay Too&lt;/li&gt;
&lt;li&gt;Even PMs and Clients Can Misalign&lt;/li&gt;
&lt;li&gt;Common Language&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Mental Models &amp;amp; Misalignment

&lt;ul&gt;
&lt;li&gt;Cognitive Science Tells Us Something Important&lt;/li&gt;
&lt;li&gt;Visualization Changes the Equation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Can Vibe Coding Be the Answer?

&lt;ul&gt;
&lt;li&gt;Yes, Absolutely&lt;/li&gt;
&lt;li&gt;Potential Issues&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Things To Keep In Mind

&lt;ul&gt;
&lt;li&gt;Make Sure Your Company Allows It&lt;/li&gt;
&lt;li&gt;Do the Research Yourself or Consult Your Technical Team&lt;/li&gt;
&lt;li&gt;AI Models Do Exactly What You Tell Them, So Be Specific&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;It's been a long time since I wrote about vibe coding, and for good reason - it's not a topic I like to talk about. As a seasoned software engineer, I'm all for &lt;strong&gt;AI-assisted&lt;/strong&gt; coding, but vibe coding? That's still a hard no from me.&lt;/p&gt;

&lt;p&gt;If you want to understand why I feel this way, check out 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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__hidden-navigation-link"&gt;I'm All In on AI, But We Need to Talk About Vibe Coding&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2619292" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 24 '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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" id="article-link-2619292"&gt;
          I'm All In on AI, But We Need to Talk About Vibe Coding
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&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/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" 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;126&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              64&lt;span class="hidden s:inline"&gt; 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;
            16 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;And here's where the good old 'however' comes in.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;However, today we're going to play a little "😈's 🥑".&lt;br&gt;
After crunching and grinding through the data, my brain finally figured out exactly where vibe coding can actually be useful. Yes, you heard me right, I just mentioned "vibe coding" and "useful" in the same sentence. Who'd have thought?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler alert:&lt;/strong&gt; it's not what you think. It's not the traditional, hype-driven version of vibe coding. If you're a software engineer hoping for an excuse to drop everything and dive headfirst into the vibe coding world, sorry, this isn't that place.&lt;/p&gt;

&lt;p&gt;In my world, there's no such thing as a developer without coding skills, no matter how hard the influencers who've never written a single line of production code try to sound cool by telling everyone that "Software engineers won't be needed in a month."&lt;br&gt;
They've been saying that for at least three years.&lt;/p&gt;

&lt;p&gt;Instead, we're going to explore vibe coding from a different angle, with an open mind. I'm not the type of person who's hostile toward an idea just because it's unfamiliar. That's why I've been thinking about this topic for a long time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Product Is a Team Sport
&lt;/h2&gt;

&lt;h3&gt;
  
  
  No Developer Is Perfect And That's Okay
&lt;/h3&gt;

&lt;p&gt;If you're a software engineer, chances are you've worked in a team with people in very different roles. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The single most important factor in successful teamwork is Communication.&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;You could assemble the world's best developers in one team, but if they can't communicate effectively, they won't achieve much. Just like in sports, talent alone isn't enough, teamwork and clear communication are what make the real difference.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But there's a problem that often gets overlooked.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A developer might be brilliant at designing systems, writing maintainable, optimized code, and thinking through architecture,  basically, everything you'd want technically. Sounds perfect, right? But that doesn't automatically make them a strong communicator when explaining what they're doing.&lt;/p&gt;

&lt;p&gt;Even more challenging is understanding exactly what's needed from the business side. For many developers, translating business requirements into technical implementation, or the other way around, can be far harder than just writing code. And there are multiple reasons for this, which we'll explore soon.&lt;/p&gt;

&lt;p&gt;Yes, we all know developers should be good communicators, but that's just "shoulda, coulda, woulda". It doesn't always happen. Sometimes a developer is so good at solving problems that you overlook the fact they're not the most talkative or expressive. Sure, they'll ask questions, understand the context, and gather the requirements. But once they feel they understand, they often assume everything's fine and dive into designing the solution, and sometimes, they get something wrong because of those assumptions.&lt;/p&gt;

&lt;p&gt;Then there's another category of developers, usually beginners, who worry that asking "too many" questions will make them look unqualified for the job (been there myself and it's miserable until you realize that's not how it works.)&lt;/p&gt;

&lt;p&gt;Either way, the result is the same: they end up doing things the wrong way, which is far from ideal.&lt;/p&gt;

&lt;h3&gt;
  
  
  No Project Manager Is Perfect And That's Okay Too
&lt;/h3&gt;

&lt;p&gt;Project managers usually aren't deeply familiar with the technical side of the product. Sure, there are PMs who understand what's going on at a high level, but they're typically either former software engineers who, for some reason, have had enough of writing code and moved toward the client-facing side, or people who are genuinely curious about how everything works under the hood.&lt;/p&gt;

&lt;p&gt;However, those cases aren't that common. Let look at the Venn diagram:&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.amazonaws.com%2Fuploads%2Farticles%2Fpvovvo23pis8jfjl7a5d.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.amazonaws.com%2Fuploads%2Farticles%2Fpvovvo23pis8jfjl7a5d.png" alt="Venn Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And this diagram isn't just about PMs and developers. The same idea applies to almost any job, technical or non-technical. There are hundreds of roles where the overlap of "excellent at communication" and "excellent at the core skill" creates the mythical, superhuman type.&lt;/p&gt;

&lt;p&gt;As a project manager, communication is your superpower. Your primary job is to understand exactly what your client wants and gather the right information from them. Then comes the next step: translating that information clearly to your developers.&lt;/p&gt;

&lt;p&gt;And that's when things can get really tricky.&lt;/p&gt;

&lt;p&gt;As mentioned, you won't always have developers who understand the product language the same way you do. You might use different terms or conceptualize things differently, and for developers, your terms could have completely different meanings.&lt;/p&gt;

&lt;p&gt;Let's look at an example. A simple term - "Real-Time".&lt;/p&gt;

&lt;p&gt;PM says: "We need real-time updates."&lt;/p&gt;

&lt;p&gt;What the PM might mean is when users refresh, they see fresh data. The numbers feel current. No obvious delay.&lt;/p&gt;

&lt;p&gt;What the developer hears? WebSockets, persistent connections, complex state management, scaling challenges.&lt;/p&gt;

&lt;p&gt;Now engineering effort multiplies... exponentially.&lt;br&gt;
All because "real-time" meant different things.&lt;/p&gt;

&lt;p&gt;This might sound like a funny or even nonsensical example, because surely you'd think it would get clarified, right? But to be honest, I've heard much worse horror stories than this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Even PMs and Clients Can Misalign
&lt;/h3&gt;

&lt;p&gt;Especially when PMs are working on highly technical products and their clients are also technical. I can only imagine how challenging it must be to listen, gather information you don't fully understand and then translate it clearly to your developers. You're the only bridge between these two overly complex technical worlds, and doing it flawlessly is no small task. That must be a lonely place to be.&lt;/p&gt;

&lt;h3&gt;
  
  
  Common Language
&lt;/h3&gt;

&lt;p&gt;Developers usually think system-first, while product people think product-first. There's nothing outrageous about this, that's exactly why different roles exist in a company. &lt;/p&gt;

&lt;p&gt;But these different mindsets can create gaps in language, perception, and understanding, which sometimes lead to problems. Think of it like Lego pieces: they can be used to build many different things. One person might build a horse🐴, while another builds a bear🐻. Neither is wrong, but the client only wants one of them.&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.amazonaws.com%2Fuploads%2Farticles%2F51z7tmzor5r8i2c67qna.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.amazonaws.com%2Fuploads%2Farticles%2F51z7tmzor5r8i2c67qna.jpg" alt="Lego Bear and Horse"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Mental Models &amp;amp; Misalignment
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Cognitive Science Tells Us Something Important
&lt;/h3&gt;

&lt;p&gt;It tells us that words don't carry meaning, they trigger mental models.&lt;/p&gt;

&lt;p&gt;When you say "dashboard", you're not transmitting an image. You're just activating one. That image is built from your own experiences, your past projects, your preferences, your assumptions. I do the same. And even if we both nod in agreement, we might be visualizing completely different products. That's why teams who've worked together for a long time make hard things look easy.&lt;/p&gt;

&lt;p&gt;Their words trigger similar mental models.&lt;br&gt;
The interpretation gap is tiny.&lt;br&gt;
And when you remove that gap, you've already solved half the problem.&lt;/p&gt;

&lt;p&gt;That's the hidden danger of language in product development.&lt;br&gt;
It feels precise. It feels shared. But it's interpretive.&lt;/p&gt;

&lt;p&gt;Our brains have to decode words, attach context, fill in gaps, and construct internal pictures. That process is fast but it's also personal. Which means two intelligent, competent professionals can agree on the same sentence and still walk away with different realities in mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visualization Changes the Equation
&lt;/h3&gt;

&lt;p&gt;The human brain processes visuals dramatically faster than text. Images don't need to be translated. They don't require semantic negotiation. They're concrete. Immediate. Shared.&lt;/p&gt;

&lt;p&gt;When we're both looking at the same interface, the same layout, the same interaction flow, the interpretation layer completely goes out of the window. The mental models collapse into a single reference point. We're no longer debating what something means. We're directly looking at that thing.&lt;/p&gt;

&lt;p&gt;So why do we keep trying to align through paragraphs?&lt;/p&gt;

&lt;p&gt;If visualization is the fastest path to alignment... then what happens when creating that visualization becomes effortless?&lt;/p&gt;

&lt;h2&gt;
  
  
  Can Vibe Coding Be the Answer?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Yes, Absolutely
&lt;/h3&gt;

&lt;p&gt;However, not to create the product itself, but to create a visual representation of the product, or a major new feature that's difficult to model clearly in your head.&lt;/p&gt;

&lt;p&gt;What I'm trying to say is this: vibe coding can give project managers something close to a superpower, the ability to communicate with near-perfect clarity. Instead of relying solely on words, they can create a working prototype. A tangible blueprint. Something engineers can look at, explore, question and then use as a foundation to build the real system.&lt;/p&gt;

&lt;p&gt;As mentioned earlier, misalignments sometimes even happen because clients and product teams visualize ideas differently. This approach can solve that problem as well, and arguably, that's even more important.&lt;/p&gt;

&lt;p&gt;Project managers can use this "blueprint" to validate requirements with precision, walking clients through quick demos and confirming alignment before a single line of production code is written.&lt;/p&gt;

&lt;h3&gt;
  
  
  Potential Issues
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;But let's address the potential issues with this approach:&lt;/strong&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Not Everyone Builds Visually Tangible Products
&lt;/h4&gt;

&lt;p&gt;What about teams that aren’t building something visually tangible? Teams developing internal libraries or purely technical tools, for example.&lt;/p&gt;

&lt;p&gt;In those cases, this approach might not even be necessary. The conversations are already deeply technical and everyone involved likely shares a similar mental model. The language gap is smaller and alignment happens through architecture diagrams, interfaces, and code, not UI prototypes. In cases like that, often the developers from different teams have direct communication with each other for steamlining the whole process.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. What About Mockup Tools?
&lt;/h4&gt;

&lt;p&gt;Conceptually, this isn't a particulary new idea, tools for creating mockups have existed for a long time.&lt;/p&gt;

&lt;p&gt;Absolutely. But those tools are quite limited: they can only do so much, and often your requirements are far more complex than what they support. That's why many companies and project managers skip this practice, it doesn't always deliver enough value to justify the time, and if used incorrectly, it can create more problems than it solves.&lt;/p&gt;

&lt;p&gt;With vibe coding, however, you can generate much more advanced, customized visuals that tell the full story. You don't need to learn complex software, it's much faster, and the result communicates your idea clearly to both clients and developers.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. Speaking of Speed, It Still Takes More Time Than Just Talking Verbally
&lt;/h4&gt;

&lt;p&gt;Even though vibe coding is faster and more precise than traditional mockup tools, It still takes more time than just explaining the concept verbally to developers. Sure.&lt;/p&gt;

&lt;p&gt;But... does it?👀&lt;/p&gt;

&lt;p&gt;I've seen developers and product people go back and forth tweaking a simple feature for months, only to get it wrong repeatedly. &lt;/p&gt;

&lt;p&gt;Think of it like racing: inexperienced drivers think that going "all in", way too hot into a corner will make them faster, but fast in doesn't always mean fast out. Sometimes the opposite is true. Experienced drivers know that to maximize speed on the next straight, you often need to slow down on entry: &lt;strong&gt;slow in, fast out.&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2Fw6v6ce595wpgfbxrvwdj.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.amazonaws.com%2Fuploads%2Farticles%2Fw6v6ce595wpgfbxrvwdj.png" alt="F1 car taking corner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The same principle applies here: it's better to invest a little extra time upfront, creating clear visuals and alignment, than to deal with endless issues down the line.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things To Keep In Mind
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Make Sure Your Company Allows It
&lt;/h3&gt;

&lt;p&gt;Every company has policies around sharing confidential information. Sometimes, a project, or even a single feature, can be sensitive enough that you're not allowed to mock it up using an external AI model. Typically, this isn't an issue if the company provides its own internal AI model, which keeps all data in-house.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do the Research Yourself or Consult Your Technical Team
&lt;/h3&gt;

&lt;p&gt;Yes, vibe coding is essentially telling an AI agent what to create, in plain English. But you still need a proper setup, which usually involves a small amount of configuration to get everything running. Consulting with your developers can make this even easier, they can have you up and running in just a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Models Do Exactly What You Tell Them, So Be Specific
&lt;/h3&gt;

&lt;p&gt;Make sure your instructions are precise. AI models often assume you want a fully functional system, complete with databases, caching, external requests, scaling, security - everything that comes with real software, because most people use vibe coding to actually build software (this is not recommended by me).&lt;/p&gt;

&lt;p&gt;If all you need is a dummy or mockup to use as a demo, &lt;strong&gt;you have to tell the AI that explicitly&lt;/strong&gt;. Doing so makes the model's job exponentially easier, produces more flexible results, &lt;strong&gt;and uses far fewer tokens&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Examples:
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Simple Visual Mockup&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt:&lt;br&gt;
"Create a simple mockup of a project management dashboard for a web app. Include task lists, progress bars, and a calendar view. This is just a visual demo, do not include actual databases, APIs, or backend logic."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Feature Prototype&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt:&lt;br&gt;
"Generate a prototype for a feature where users can create, edit, and delete items. The prototype should show screens and buttons, but it does not need to connect to a database or have real functionality."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Internal Tool Demo&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt:&lt;br&gt;
"Produce a mockup for an internal reporting tool. Include charts, filters, and tables. Only visual elements are required, do not add real data fetching, authentication, or backend services."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Mobile App Example&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt:&lt;br&gt;
"Create a visual prototype of a mobile to-do app with three screens: task list, task details, and task creation. This is just a demo, no actual storage, API calls, or notifications are required."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Interactive Demo with Dummy Data&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Prompt:&lt;br&gt;
"Build a mockup for a CRM dashboard with dummy data. Include client cards, search filters and activity logs. This is only a prototype for demonstration purposes, skip real functionality like databases, caching, or external requests."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;As a developer, I'm not a fan of vibe coding, it's definitely not coding (nor "vibe"), and the name is kind of silly if you ask me. But that doesn't mean it's useless. &lt;strong&gt;In software development, everything is a tool. There are no inherently good or bad tools, only good and bad ways to use them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Vibe coding can be a superpower for project managers, product managers, product owners, and others with limited technical knowledge. It's right there for you to use, with almost no learning curve. That's where I see the real value.&lt;/p&gt;

&lt;p&gt;If you're a product person, try suggesting this to your team: practice it, create a demo, and show the value in a tangible way. &lt;/p&gt;

&lt;p&gt;If you're a technical person struggling to understand requirements, invite your product people to try this approach. Make it a fun, knowledge-sharing session where you vibe code a dummy or mock application that looks like the real deal. The opportunities here are endless.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>vibecoding</category>
      <category>productivity</category>
      <category>softwaredevelopment</category>
    </item>
    <item>
      <title>Metal Birds Watch: Copilot CLI Helped Me Watch Planes Without Looking Up</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Fri, 13 Feb 2026 20:01:12 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0</link>
      <guid>https://forem.com/georgekobaidze/metal-birds-watch-copilot-cli-helped-me-watch-planes-without-looking-up-4ha0</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-01-21"&gt;GitHub Copilot CLI Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Demo&lt;/li&gt;
&lt;li&gt;
What I Built

&lt;ul&gt;
&lt;li&gt;The Idea&lt;/li&gt;
&lt;li&gt;So, What Does It Do?&lt;/li&gt;
&lt;li&gt;Turns Out, It Wasn't That Simple&lt;/li&gt;
&lt;li&gt;The Solution&lt;/li&gt;
&lt;li&gt;A Few Words About the Tech Stack&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

My Experience with GitHub Copilot CLI

&lt;ul&gt;
&lt;li&gt;So Here's the Conclusion:&lt;/li&gt;
&lt;li&gt;And One Last Thing&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Credits&lt;/li&gt;

&lt;li&gt;Useful Links&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;In this video, I not only present the demo, but also walk through the core purpose and motivation behind the project. I dive into the architecture and design decisions in detail, explaining how everything fits together and why certain approaches were chosen.&lt;/p&gt;

&lt;p&gt;You can check out the video chapters if you'd like to jump to a specific part, but I highly recommend watching the full video to get the complete picture and fully understand how everything connects.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/fe2eGNbItUk"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Idea
&lt;/h3&gt;

&lt;p&gt;I love airplanes, traveling, airports, the sound of engines, everything related to aviation. For a long time, I've wanted to build something connected to that world. I just needed the right excuse.&lt;/p&gt;

&lt;p&gt;Then this challenge appeared. This was my though process:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Okay, this challenge looks fun. I need to use Copilot CLI.&lt;br&gt;
Alright, but what do I build? It has to be authentic. Cool. Creative and actually useful...&lt;/p&gt;

&lt;p&gt;Copilot CLI...&lt;br&gt;
Copilot...&lt;br&gt;
Pilot...&lt;br&gt;
Airplanes...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And suddenly it clicked.&lt;/p&gt;

&lt;p&gt;That was the moment &lt;strong&gt;Metal Birds Watch&lt;/strong&gt; was born.&lt;/p&gt;

&lt;p&gt;What started as a word association turned into a real-time aircraft tracking app that notifies you when planes fly over you. Sometimes ideas don't come from complex brainstorming sessions, sometimes they come from connecting a few dots and letting your curiosity do the rest.&lt;/p&gt;

&lt;p&gt;This challenge didn't just give me a prompt, it gave me the push I needed to finally build something I'd been thinking about for years. And I'm insanely proud of how it turned out.&lt;/p&gt;

&lt;h3&gt;
  
  
  So, What Does It Do?
&lt;/h3&gt;

&lt;p&gt;As a regular aircraft nerd, I instinctively look up at the sky every time I hear an engine overhead. I try to guess the make and model, the airline, maybe even where it took off from or where it's heading. It's like a little game (I'm not the best at it though, my brother and mom absolutely destroy me at this game, they make me look like I've never seen a plane in my life).&lt;/p&gt;

&lt;p&gt;But there's one problem.&lt;/p&gt;

&lt;p&gt;I can't just stand outside all day watching planes. Most of the time I'm working - coding, building things, solving problems. I'm a busy guy, too busy.&lt;/p&gt;

&lt;p&gt;Sure, there are plenty of websites where you can track airplanes from all around the world in real time. But that still requires actively watching a screen. And again... I'm way too busy for that.&lt;/p&gt;

&lt;p&gt;So I decided to build something that would "watch the sky" for me.&lt;/p&gt;

&lt;p&gt;I use quotation marks because it doesn't literally watch the sky, it taps into real-time public flight data and detects when aircraft enter my area. When that happens, it sends me a notification. And if I miss it, the plane is still logged in my browser so I can check later and see what flew over my head.&lt;/p&gt;

&lt;p&gt;Instead of me watching planes, the app watches them for me. Hence the name &lt;strong&gt;Metal Birds Watch.&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2F7tmojjx9odbuxpabs16h.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.amazonaws.com%2Fuploads%2Farticles%2F7tmojjx9odbuxpabs16h.png" alt="Metal Birds Watch"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try it out yourself using the following link: &lt;a href="https://metalbirdswatch.pilotronica.com/" rel="noopener noreferrer"&gt;https://metalbirdswatch.pilotronica.com/&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Turns Out, It Wasn't That Simple
&lt;/h3&gt;

&lt;p&gt;The whole concept sounds pretty straightforward right?&lt;/p&gt;

&lt;p&gt;Fetch plane data periodically → filter by your area → trigger a notification. Easy!&lt;/p&gt;

&lt;p&gt;Well, nuh-uh! The architecture and implementation turned out to be way more complex than the idea itself.&lt;/p&gt;

&lt;p&gt;When you rely on a third-party public service, there are always limitations and rightfully so. Free APIs need rate limits. Without them, they'd be abused and become unusable for everyone.&lt;/p&gt;

&lt;p&gt;The API I used for this challenge is no exception. It has strict request limits, and I have to respect the limits. If I exceed them, my app runs out of credits and simply stops working.&lt;/p&gt;

&lt;p&gt;Usually when you're constrained by request limits or data quotas, the obvious solution is caching. Smart caching reduces the number of calls you make to the API provider. Great!&lt;/p&gt;

&lt;p&gt;But then comes the real question:&lt;/p&gt;

&lt;p&gt;How do you cache this kind of data?&lt;/p&gt;

&lt;p&gt;There are tens of thousands of aircraft in the sky at any given moment, scattered across the globe. I needed to keep a fine balance between caching too aggressively (which could overload my storage and keep irrelevant data) and not caching enough (which would burn through API credits in minutes).&lt;/p&gt;

&lt;p&gt;And that's where things started to get interesting.&lt;/p&gt;

&lt;p&gt;On top of that, I made a deliberate decision to keep the system simple.&lt;/p&gt;

&lt;p&gt;No persistent storage.&lt;/p&gt;

&lt;p&gt;And more importantly, no sensitive data stored anywhere.&lt;/p&gt;

&lt;p&gt;This is a privacy-first application. That means I don't store the user's location, IP address, or any personally identifiable information, not in a database, not in logs, not even in cache and any readable storage. Nor should it be retrievable via any endpoint.&lt;/p&gt;

&lt;p&gt;By now, you can probably tell there are already quite a few moving parts in this system.&lt;/p&gt;

&lt;p&gt;And we haven't even started talking about the actual solution yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Solution
&lt;/h3&gt;

&lt;h4&gt;
  
  
  A Note Before You Dive In
&lt;/h4&gt;

&lt;p&gt;Disclaimer: This is one way to solve this problem, not the only way. There are many strategies and approaches you could take, and I'd love to hear your ideas or suggestions. Here's how I tackled it:&lt;/p&gt;

&lt;h4&gt;
  
  
  Caching by "Grid Cells"
&lt;/h4&gt;

&lt;p&gt;I decided to cache plane data based on what I call grid cells - basically, areas where multiple airplanes might be present. Instead of tracking every user individually, I group users by coordinates, rounding them to the nearest grid cell.&lt;/p&gt;

&lt;p&gt;Each grid cell is roughly &lt;code&gt;0.2° latitude × 0.2° longitude&lt;/code&gt;, about &lt;code&gt;22 km × 22 km&lt;/code&gt;. That's &lt;code&gt;484 km²&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For reference, San Francisco is &lt;code&gt;121 km²&lt;/code&gt;, so each grid cell is about four times larger.&lt;/p&gt;

&lt;p&gt;Users are grouped by rounding their coordinates to nearest &lt;code&gt;0.2°&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User A&lt;/code&gt; at &lt;code&gt;(48.856, 2.352)&lt;/code&gt; → grid cell &lt;code&gt;48.8_2.4&lt;/code&gt; (cache key)&lt;/p&gt;

&lt;p&gt;&lt;code&gt;User B&lt;/code&gt; at &lt;code&gt;(48.772, 2.421)&lt;/code&gt; → same grid cell &lt;code&gt;48.8_2.4&lt;/code&gt; (same cache key)&lt;/p&gt;

&lt;p&gt;Both users can get plane data for the area without storing their exact locations anywhere.&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.amazonaws.com%2Fuploads%2Farticles%2Fdniwxyjoyw0mrxarqyfi.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.amazonaws.com%2Fuploads%2Farticles%2Fdniwxyjoyw0mrxarqyfi.jpg" alt="Grid Cell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, User B falls within the same grid cell initialized by User A, so both users share the same cache entry &lt;code&gt;48.8_2.4&lt;/code&gt;. Any user in this area will use the same entry.&lt;/p&gt;

&lt;h4&gt;
  
  
  Detection Radius
&lt;/h4&gt;

&lt;p&gt;After the plane data is retrieved, each user only sees aircraft within a 12 km detection radius centered on their location. This filtering happens on the client side to minimize backend resource usage and keep the system flexible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But there's an important edge case&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a user is near the edge of a grid cell, they might miss planes flying just outside the grid. Corner users could see only a quarter of the surrounding sky. See the diagram below for a better visualization:&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.amazonaws.com%2Fuploads%2Farticles%2Fqwrwpeedxjml9vokuvq1.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.amazonaws.com%2Fuploads%2Farticles%2Fqwrwpeedxjml9vokuvq1.jpg" alt="Edge Case"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The green planes (Plane A and Plane C) are cached and fall within the detection radii of their respective users so notifications will be triggered. ✅&lt;/p&gt;

&lt;p&gt;The yellow plane (Plane B) is inside the grid cell, so it's cached as well. Users will see it on the page, but no notification will be sent until it enters one of the detection circles. ❌&lt;/p&gt;

&lt;p&gt;The white planes (Plane E, Plane D, and Plane F), however, are outside the grid cell and therefore won't be cached, nor will they be shown on the map, even though Plane D is technically within the detection radius of User C. ❌&lt;/p&gt;

&lt;p&gt;Now, this is a significant drawback, because it means some users might not receive fully accurate information about nearby planes.&lt;/p&gt;

&lt;p&gt;And this is exactly where the &lt;strong&gt;Bounding Box&lt;/strong&gt; strategy saves the day.&lt;/p&gt;

&lt;h4&gt;
  
  
  Bounding Box
&lt;/h4&gt;

&lt;p&gt;Fetching a slightly larger rectangle ensures everyone gets the full "all-around" view.&lt;/p&gt;

&lt;p&gt;The backend actually fetches a 50 km × 50 km rectangle around the grid cell center, slightly larger than the grid itself, to ensure full coverage of the area.&lt;/p&gt;

&lt;p&gt;See the diagram below for a clearer view:&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.amazonaws.com%2Fuploads%2Farticles%2F6h7ksn87z8s2sxyicods.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.amazonaws.com%2Fuploads%2Farticles%2F6h7ksn87z8s2sxyicods.jpg" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, Plane D has just turned green, which means User C will now receive a notification about it.&lt;/p&gt;

&lt;p&gt;Keep in mind: the bounding box serves a completely different purpose than the grid cell. If a new user appears within the bounding box but outside the existing grid cell, a new grid cell and consequently a new bounding box will be created for them. The bounding box's only job is to ensure that no planes are missed near the edges.&lt;/p&gt;

&lt;p&gt;Looking at the diagram, you can see that the bounding box doesn't need to be this large, which is fine for now. In future versions of the app, users will be able to adjust their detection radius and making it bigger (or smaller).&lt;/p&gt;

&lt;h4&gt;
  
  
  Smart Polling
&lt;/h4&gt;

&lt;p&gt;Clients don't poll the server at fixed intervals. Instead, the server tells each client when to request new data, based on cache freshness. This approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reduces unnecessary polling&lt;/li&gt;
&lt;li&gt;Saves bandwidth&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Haversine Distance for Accuracy
&lt;/h4&gt;

&lt;p&gt;To calculate the exact distance between a plane and a user, I use the Haversine formula, which measures distance on a sphere. This ensures accurate notifications, even for users near the edge of a grid cell.&lt;/p&gt;

&lt;p&gt;This setup allows my app to provide real-time, privacy-first plane tracking, efficiently handling thousands of planes and users simultaneously.&lt;/p&gt;

&lt;h4&gt;
  
  
  Math Reference
&lt;/h4&gt;

&lt;h3&gt;
  
  
  Constants
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;KM_PER_DEGREE_LAT = 111 km (constant everywhere)
KM_PER_DEGREE_LON = 111 × cos(latitude) km (varies by latitude)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why Longitude Varies
&lt;/h3&gt;

&lt;p&gt;Earth is a sphere. Longitude lines converge at poles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;At equator (0°):    1° longitude = 111 km
At Paris (48.8°):   1° longitude = 111 × cos(48.8°) = 73 km
At Oslo (60°):      1° longitude = 111 × cos(60°) = 55.5 km
At poles (90°):     1° longitude = 0 km
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Converting km to Degrees
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Δlat = distance_km / 111
Δlon = distance_km / (111 × cos(latitude))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Bounding Box Calculation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Given center (φ, λ) and radius r km:

lat_min = φ - (r / 111)
lat_max = φ + (r / 111)
lon_min = λ - (r / (111 × cos(φ)))
lon_max = λ + (r / (111 × cos(φ)))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example: 25km around Paris (48.8°, 2.4°)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Δlat = 25 / 111 = 0.225°
Δlon = 25 / (111 × cos(48.8°)) = 25 / 73 = 0.342°

lat_min = 48.8 - 0.225 = 48.575
lat_max = 48.8 + 0.225 = 49.025
lon_min = 2.4 - 0.342 = 2.058
lon_max = 2.4 + 0.342 = 2.742
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Grid Rounding
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;grid_lat = round(lat / 0.2) × 0.2
grid_lon = round(lon / 0.2) × 0.2
cache_key = "{grid_lat}_{grid_lon}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User location: (48.8712, 2.3891)

grid_lat = round(48.8712 / 0.2) × 0.2 = round(244.356) × 0.2 = 244 × 0.2 = 48.8
grid_lon = round(2.3891 / 0.2) × 0.2 = round(11.9455) × 0.2 = 12 × 0.2 = 2.4

cache_key = "48.8_2.4"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A Few Words About the Tech Stack
&lt;/h3&gt;

&lt;p&gt;Even though I'm most proficient in .NET, I wanted to make this challenge more interesting by building it on something different, for a few reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;I wanted to learn a technology I had less experience with.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I'd get to interact more with Copilot CLI and explore its capabilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I needed a stack that's popular and widely used, making it easier for others to contribute in the future.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's how I landed on Node.js. It's completely different from .NET, but that's exactly the point! I wanted to step outside my comfort zone, explore a relatively unexplored area, and see how it felt. Spoiler: it felt just right!&lt;/p&gt;

&lt;p&gt;For the front-end, I kept things simple with plain HTML, CSS, and JavaScript. In the future, I plan to upgrade it with something more advanced, but for this challenge, simplicity was key.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Experience with GitHub Copilot CLI
&lt;/h2&gt;

&lt;p&gt;I'm a huge fan of the CLI tools in general. To me, it's the single most efficient and authentic tool a software engineer can use. After all, every GUI tool is built on top of it. I often find myself struggling to understand GUI tools, which might make me look a bit weird to developers who can't live without their shiny interfaces, but I guess I'll never be able to understand that point of view.&lt;/p&gt;

&lt;p&gt;As amazing as Copilot is, it always lacked one feature I had been waiting for - the CLI tool. Now that it's finally here, there's no way I'm not going to use it.&lt;/p&gt;

&lt;p&gt;This was actually my first time using Copilot in CLI mode, and I was instantly amazed at how good of a communicator it is. The variety of model options is fantastic too, and I really appreciate the token system, each model consumes a specific number of tokens, allowing you to choose based on the complexity of your task.&lt;/p&gt;

&lt;p&gt;Copilot CLI didn't just help me create beautiful visuals and make the front-end fully responsive, it also helped me refine all the ideas I had sketched out before even starting to code. It improved my calculations to handle edge cases I hadn't considered, like normalizing longitude values.&lt;/p&gt;

&lt;p&gt;Here's how the conversation went like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Me: Can you explain the purpose of this normalization function?&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Copilot CLI:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;This function ensures longitude values stay within the valid range of &lt;code&gt;-180° to +180°&lt;/code&gt;.&lt;/em&gt;&lt;br&gt;
&lt;em&gt;Why it's needed:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;- Longitude wraps around the Earth (&lt;code&gt;180° and -180°&lt;/code&gt; are the same line - the International Date Line)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;- If a user pans the map far right, Leaflet might report longitude as &lt;code&gt;370°&lt;/code&gt; instead of &lt;code&gt;10°&lt;/code&gt;&lt;/em&gt;&lt;br&gt;
&lt;em&gt;- API calls and distance calculations need standard &lt;code&gt;-180 to 180&lt;/code&gt; range&lt;br&gt;
How it works:&lt;/em&gt;&lt;br&gt;
&lt;em&gt;1. &lt;code&gt;lon % 360&lt;/code&gt; - Wraps values into &lt;code&gt;-360 to 360&lt;/code&gt; range&lt;/em&gt;&lt;br&gt;
&lt;em&gt;2. &lt;code&gt;If &amp;gt; 180&lt;/code&gt; → subtract 360 (e.g., &lt;code&gt;270° → -90°&lt;/code&gt;)&lt;/em&gt;&lt;br&gt;
&lt;em&gt;3. &lt;code&gt;If &amp;lt; -180&lt;/code&gt; → add 360 (e.g., &lt;code&gt;-270° → 90°&lt;/code&gt;)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Example: User pans to longitude &lt;code&gt;540° → 540 % 360 = 180&lt;/code&gt; → returns &lt;code&gt;180°&lt;/code&gt; ✓&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is one of the highlights and a perfect example of how Copilot CLI can save you from overlooking subtle details. It really feels like having a fellow engineer by your side, pointing out mistakes, suggesting better alternatives, and even helping you implement them.&lt;/p&gt;

&lt;p&gt;Additionally, it was incredibly easy and convenient to create issues on my GitHub project board directly from the CLI. Based on the strategy and implementation details I provided, Copilot generated a neatly organized list of tasks for me. I didn't have to create them manually, which is a process that can be repetitive and time-consuming.&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.amazonaws.com%2Fuploads%2Farticles%2F7obikrmo7qd9jrid0prg.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.amazonaws.com%2Fuploads%2Farticles%2F7obikrmo7qd9jrid0prg.png" alt="Copilot Issues"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  So, Here's the Conclusion
&lt;/h3&gt;

&lt;p&gt;Would I be able to create this project only by myself? - Yes, absolutely.&lt;br&gt;
Would I be able to create the same exact project only by myself &lt;strong&gt;in less than 2 weeks&lt;/strong&gt;? - Probably not - the Copilot CLI really boosted my performance.&lt;/p&gt;

&lt;p&gt;I didn't encounter any issues or bugs while using Copilot CLI, which is impressive for a brand-new tool, especially since you'd normally expect at least some minor hiccups.&lt;/p&gt;

&lt;p&gt;Overall, I'm absolutely satisfied with Copilot CLI and I think it'll always have room in my toolbox from now on.&lt;/p&gt;

&lt;h3&gt;
  
  
  And One Last Thing
&lt;/h3&gt;

&lt;p&gt;This app has great potential. I've already planned many features that will be added in the future, and I'd love to see contributions from other software engineers as well.&lt;/p&gt;

&lt;p&gt;Check out the high-level roadmap in the screenshot on the website:&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.amazonaws.com%2Fuploads%2Farticles%2Fvfd39fim024txbxd8tkz.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.amazonaws.com%2Fuploads%2Farticles%2Fvfd39fim024txbxd8tkz.png" alt="Future Roadmap"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Building this app wasn't just a coding challenge, it was a way to bring a piece of my passion for aviation into reality. Every line of code, every architecture decision, and every optimization I made was about connecting people to the thrill of watching planes even if they're stuck at a desk or on the go.&lt;/p&gt;

&lt;p&gt;It's amazing how technology can bridge the gap between curiosity and reality. With just a few carefully crafted algorithms, users can feel the sky above them, catch glimpses of planes flying overhead, and experience the small joys I've loved for years.&lt;/p&gt;

&lt;p&gt;This project reminded me that the best ideas aren't just about what you create, they're about the feeling they leave behind. For me, it's that little spark of excitement when a plane passes by, and now, thanks to this app, I can share that spark with anyone, anywhere. Working on this app reminded me that nothing makes me feel more alive than building and creating things that I'm passionate about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;p&gt;Special thanks to the following projects and services that made this application possible:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://opensky-network.org/data/api" rel="noopener noreferrer"&gt;OpenSky Network API&lt;/a&gt; - An incredible public service providing real-time aviation data that powers this application ✈️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://leafletjs.com/" rel="noopener noreferrer"&gt;Leaflet&lt;/a&gt; - For delivering lightweight and powerful interactive maps&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.openstreetmap.org/" rel="noopener noreferrer"&gt;OpenStreetMap&lt;/a&gt; - For providing the open-source map data and tiles&lt;/p&gt;

&lt;h2&gt;
  
  
  Useful Links
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/georgekobaidze/metal-birds-watch" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://metalbirdswatch.pilotronica.com/" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://youtu.be/fe2eGNbItUk" rel="noopener noreferrer"&gt;Video Explanation&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>cli</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>The Real Cost of Loving What You Do: The Uncomfortable Truth About Developer Burnout</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 18 Jan 2026 15:48:39 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/the-real-cost-of-loving-what-you-do-the-uncomfortable-truth-about-developer-burnout-43n6</link>
      <guid>https://forem.com/georgekobaidze/the-real-cost-of-loving-what-you-do-the-uncomfortable-truth-about-developer-burnout-43n6</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 Complexity We Underestimate About Burnout

&lt;ul&gt;
&lt;li&gt;It Takes Experience and Time to Handle It&lt;/li&gt;
&lt;li&gt;Why Most Burnout Advice Misses the Point&lt;/li&gt;
&lt;li&gt;No One's Coming to Fix You&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Why I Can't Stop Reading About Navy SEALs&lt;/li&gt;

&lt;li&gt;

The Darkest Days of My Burnout

&lt;ul&gt;
&lt;li&gt;Bit Off More Than I Could Chew&lt;/li&gt;
&lt;li&gt;Multitasking, A.K.A: Screwing Up Multiple Things at Once&lt;/li&gt;
&lt;li&gt;Trapped in a Vicious Cycle&lt;/li&gt;
&lt;li&gt;Escaping the Cycle&lt;/li&gt;
&lt;li&gt;Checking Your Rearview Mirror is Important&lt;/li&gt;
&lt;li&gt;The Main Reasons in My Personal Case&lt;/li&gt;
&lt;li&gt;Wait, What About Working too Hard or Too Much?&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Then What's The Main Cause of Burnout?

&lt;ul&gt;
&lt;li&gt;Reflect Honestly on These Factors&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

And This Is Where the Navy SEALs Reference Comes Into Play

&lt;ul&gt;
&lt;li&gt;How Does This Relate to Our Field?&lt;/li&gt;
&lt;li&gt;Discipline, Discipline, Discipline!&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Why Burnout Hits Software Engineers Differently&lt;/li&gt;

&lt;li&gt;The Method That Keeps Me Running and Avoids Burnout&lt;/li&gt;

&lt;li&gt;

Summary and Exercise for You

&lt;ul&gt;
&lt;li&gt;The Summary&lt;/li&gt;
&lt;li&gt;The Excercise&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

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

&lt;p&gt;I usually write code-heavy articles filled with snippets and concepts meant for a very specific crowd, the "chosen ones". &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;This one is different.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's still about software engineering, but instead of code, it's a "let's talk about it" kind of article. Even if you're not a software engineer, this will likely feel familiar. Burnout exists in every career. No matter what you do at a professional level, the work is demanding and harsh. &lt;/p&gt;

&lt;p&gt;You're constantly operating near your limits, juggling multiple responsibilities, trying to do everything as well as you can, because performance is expected, on top of that, you have high standards for yourself. And sometimes, even that isn't enough, leaving you feeling like you need to push even harder, you don't trust your perception of your limits, you think that there's much more to give.&lt;/p&gt;

&lt;p&gt;If this sounds familiar, keep reading. You may find perspectives you haven't considered before, ones that could help break the friction loop that causes your burnout.&lt;/p&gt;

&lt;p&gt;I'll share the time when my burnout reached its absolute peak, and at the end of the article, I'll give you a small exercise you can try, one that might just help you break free from burnout.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Complexity We Underestimate About Burnout
&lt;/h2&gt;

&lt;h3&gt;
  
  
  It Takes Experience and Time to Handle It
&lt;/h3&gt;

&lt;p&gt;I'm no different, I've struggled with the same condition for a while in the past and sometimes it still stops by to say hello. But now, with experience, I can handle it more calmly and easily. It's never actually easy, and it can still jab me in the face, but understanding what causes it and why it hits so hard makes it more manageable. It might still hurt, but at least it won't knock me down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Most Burnout Advice Misses the Point
&lt;/h3&gt;

&lt;p&gt;I've read plenty of articles regarding this topic, but very few really delivered a message I could relate to. Most felt like they were written to make me feel better about myself, a temporary shelter where I could justify not working on my skills or personal projects because I was burned out. Sure, sometimes we need a little comfort and a reminder that we're still awesome, but in the long run, that doesn't actually help, does it?&lt;/p&gt;

&lt;h3&gt;
  
  
  No One's Coming to Fix You
&lt;/h3&gt;

&lt;p&gt;When I spend my own time reading about mindset, discipline, or work ethic, I'm looking for long-term benefit. The best way to get that is by being honest with yourself, figuring out what's really holding you back from becoming a better software engineer, leader, or professional in your career. I'm not interested in fake "you're awesome!", "you're a winner!" "you can do anything!" type of nonsense. I'm looking for something, that'll point out where I'm an absolute loser at. So I can address it.&lt;/p&gt;

&lt;p&gt;In today's world, very few people will be that brutally honest with you. The ones who do, are the people who truly care. But nobody can study you full-time, so it's up to you to do the work: reflect on your career, run experiments, and debug your own system. Identify your flaws, confront them, and use that insight to grow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Can't Stop Reading About Navy SEALs
&lt;/h2&gt;

&lt;p&gt;Before we dive into burnout itself, let's set the stage. This topic is complex and touches on many different areas, so establishing a clear reference point will help explain the core concept more effectively.&lt;/p&gt;

&lt;p&gt;If I were to recommend a book to someone trying to improve their life or start a new career with the right mindset, I'd advise staying away from the commonly hyped titles that everyone talks about but rarely deliver real value. The reason is simple: they teach the techniques, but they don't tell the story, and without the story, it just doesn't stick.&lt;/p&gt;

&lt;p&gt;Instead, look for books written about real stories. Storytelling is one of the most underrated tools in almost everything. A good story captures attention, draws you in, and makes you want to learn more. That's why I recommend reading books that share real experiences, you'll gain lessons you can actually apply.&lt;/p&gt;

&lt;p&gt;As a software engineer, you wouldn't expect me to relate to Navy SEALs in any way. Does it sound strange? Absolutely. But reading their stories has been incredibly valuable, it actually helped me uncover why I was constantly feeling burned out.&lt;/p&gt;

&lt;p&gt;Navy SEALs are an elite special operations force. The name "SEAL" comes from Sea, Air, and Land, meaning they are trained to be excellent in any environment imaginable. They are basically the toughest humans on the planet, which is why their selection and training process is brutally demanding, almost impossible to pass.&lt;/p&gt;

&lt;p&gt;What's most fascinating is that the training isn't designed to lead to comfort or ease afterward. In fact, the challenges they face in real-life missions are far tougher and exponentially more dangerous than anything in training.&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.amazonaws.com%2Fuploads%2Farticles%2F9ni66pgsmypw4rh6deqh.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.amazonaws.com%2Fuploads%2Farticles%2F9ni66pgsmypw4rh6deqh.jpg" alt="Navy SEALs" width="800" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's hard for the regular, common people to understand this, because the common mindset always seeks comfort and convenience. SEALs think differently, they embrace the struggle completely. I remember one of them saying something like: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Those moments when everything feels heavy, quiet, and painful, that's where self-respect is built."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And the more I think about it, the more I'm convinced how true it is.&lt;/p&gt;

&lt;p&gt;You're probably wondering what all of this has to do with burnout, especially in software engineering. Stick with me, we'll uncover it all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Darkest Days of My Burnout
&lt;/h2&gt;

&lt;p&gt;As I mentioned in the previous section, sharing knowledge or giving advice without proper storytelling is pretty dull. It's like eating a burger without sauce, sure, it fills you up, but the experience is nothing alike. The richer the experience, the more unforgettable it becomes and the more it can positively affect you. With that in mind, I'll share as much as I can about what the best (or worst) version of burnout has meant personally for me.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bit Off More Than I Could Chew
&lt;/h3&gt;

&lt;p&gt;This was a long time ago, when I was still a beginner software engineer. I decided to learn multiple completely different things at once while staying extremely productive at work, because I wanted to reach the senior level as fast as possible and keep up with seasoned developers, some of them with five times more experience than me.&lt;/p&gt;

&lt;p&gt;Not only that, I wanted to be self-sufficient right away, meaning I decided to learn every part of the software engineering &lt;strong&gt;at the same time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Back then, I didn't have much experience and didn't really know the most effective ways to work or learn. I bought a bunch of video courses and tried to go through them all in parallel to "save time" - &lt;strong&gt;BIG MISTAKE&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Multitasking, A.K.A: Screwing Up Multiple Things at Once
&lt;/h3&gt;

&lt;p&gt;Let's be honest here, who ever learned anything in tech just by watching someone else do it? &lt;strong&gt;Nobody&lt;/strong&gt;. I'm no exception.&lt;/p&gt;

&lt;p&gt;Back then, I hadn't realized that a 30-hour video course doesn't mean you'll master the topic in 30 hours. You need to multiply that time by at least 15 just to grasp the basics, the foundation on which you can build real knowledge and experience. Unless you write code yourself, you don't really know anything, all you're doing is memorizing, and memorization alone never works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Trapped in a Vicious Cycle
&lt;/h3&gt;

&lt;p&gt;I was miserable. My plan was failing and I felt completely unlike the person I was when I started. I watched the tutorials and did exactly the same as they did, sometimes not even that. I made no progress, life felt boring, and I definitely couldn't keep up with the seniors around me.&lt;/p&gt;

&lt;p&gt;I forced myself to work overtime, going home at 10 PM or later, and then spent almost the entire night/morning watching tutorials or building meaningless, goalless apps. I had no discipline, I was doing everything without a plan or real commitment.&lt;/p&gt;

&lt;p&gt;Sometimes, out of boredom, I'd stop a tutorial halfway through and play video games late into the night to "unwind". But it didn't even feel fun, I was just pretending to have fun. Then I'd wake up after three hours of sleep and drag myself to work, clueless about how I was supposed to function. Somehow, I still did, probably coffee? I don't really know.&lt;/p&gt;

&lt;p&gt;I was completely stuck in a vicious circle that looked something like 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.amazonaws.com%2Fuploads%2Farticles%2Ff9ynctf62jip2wzhx65i.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.amazonaws.com%2Fuploads%2Farticles%2Ff9ynctf62jip2wzhx65i.png" alt="Cycle of Doom" width="663" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That almost broke me. &lt;/p&gt;

&lt;p&gt;I was visibly overwhelmed, not enjoying life, and making no real progress. The worst part was that I wasn't even trying to change anything, I was too stubbornly persistent to step back and rethink what I was doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Escaping the Cycle
&lt;/h3&gt;

&lt;p&gt;This peak period of burnout and stress lasted about 3 to 4 months. Luckily, at some point, I decided to reflect on the road I had traveled so far and realized that all the struggle, sleepless nights, and mental and physical strain hadn't brought any real progress whatsoever. Quite the opposite, in fact.&lt;/p&gt;

&lt;p&gt;It was alarming. I knew I had to change my approach because continuing like that wasn't doing me any favors. Burnout can easily turn into depression, and we all know that's a place you don't want to be at. Looking back, admittedly, I was there without even realizing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Checking Your Rearview Mirror is Important
&lt;/h3&gt;

&lt;p&gt;I'm a true believer of always moving and looking forward, but occasionally you need to check your rearview mirror to make sure there's no danger behind you. I know people who say, &lt;em&gt;"Never look back, doesn't matter if it's bad or good"&lt;/em&gt; - &lt;strong&gt;WRONG!&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;Ignoring the past means missing out on valuable lessons, especially when you view them with a fresh, current perspective.&lt;/p&gt;

&lt;p&gt;I don't play chess, but I've watched professional players, both the winner and the loser review their moves immediately after the game. It doesn't matter where past actions got you, reflecting on them is still incredibly valuable. It teaches you what to do better in the future.&lt;/p&gt;

&lt;p&gt;If I hadn't taken the time to evaluate my progress and the road I'd traveled so far, I'd have stayed stuck in that burnout loop much longer, causing even more damage to myself and my career.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Main Reasons in My Personal Case
&lt;/h3&gt;

&lt;p&gt;In hindsight, the main reasons I burned out were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Lack of specific goals: I was doing everything just for the sake of doing it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack of commitment: I wasn't motivated or excited to tackle tasks consistently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Nonexistent discipline: I worked based on how I felt each day, with zero consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Chasing quick dopamine hits: when coding or learning got boring, I'd switch to social media or video games. Even then, I wasn't truly enjoying myself, I was just pretending.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Making excuses for slow progress: I never questioned my approach and always found lame reasons for lack of results.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fear of leaving my comfort zone: this actually translates to "fear of achieving a much better life and career".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;False expectations: before I started working as a software engineer, I imagined it would be a nonstop process of exciting problems and constant feature development. The reality is different: at some point, you get stuck in a routine, and it can feel dull.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Wait, What About Working too Hard or Too Much?
&lt;/h3&gt;

&lt;p&gt;Some of you might be wondering why "working too hard" or "working too much" isn't on my burnout list. Let's dive into that.&lt;/p&gt;

&lt;p&gt;To be honest, what I was doing back then was far from true "hard work." As I mentioned earlier, I had no real discipline, and my bursts of intense work weren't consistent. Working hard for two or three hours a day while coasting the rest of the time doesn't make you a hardworking person. In my case, burnout had nothing to do with overworking.&lt;/p&gt;

&lt;p&gt;As for working too much, it would be a lie to say I wasn't putting in long hours, sometimes I'd go to bed at 3 or 4 AM, or even later. &lt;strong&gt;But what's the point of working that much if it doesn't actually lead to anything? It's just convincing yourself that you're being productive.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Those long sessions contributed to my burnout, but not in the way you might think. It wasn't that I was putting in massive effort every minute and wearing myself down over time, it was that I was spending hours boring myself by accomplishing almost nothing. &lt;strong&gt;I was like a car idling with the engine on: burning fuel, going nowhere, and slowly getting rusty in the process.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When I said I didn't relate to most articles on this topic, this is what I meant. Most of them suggest things like "take it easy," "limit your coding time," or "do something else instead." For me, that NEVER, EVER worked.&lt;/p&gt;

&lt;p&gt;Burnout isn't about how hard or how much you work, or about what other activities you do besides coding or learning. I've tried plenty of things like walking, running, working out, even meditating, but none of that gets rid of burnout on its own. Sure, they can help a little, but unless you identify the main, core reason behind it, burnout will always find a way back, no matter how many distractions or hobbies you add.&lt;/p&gt;

&lt;h2&gt;
  
  
  Then What's The Main Cause of Burnout?
&lt;/h2&gt;

&lt;p&gt;There's no single cause, or set of causes for burnout. It can depend on many different factors, including your personality. But the bottom line is this: &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you genuinely enjoy what you do, burnout is unlikely to happen, no matter how much or how hard you work in a day. There's a huge difference between feeling tired and being burned out, and it's critical to recognize that distinction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Have you ever felt tired but still completely happy? I have, and it's absolutely amazing. I remember working on projects so exciting that I'd skip sleep, sometimes going almost three nights without rest, let alone sleep, just because I just didn't want to stop coding. I was so exhausted that my eyes would close on their own, and I was barely holding on with a huge coffee mug by my side.&lt;/p&gt;

&lt;p&gt;But I didn't care for a second. I coded not because of deadlines, and not because I couldn't do it later, I coded because I was in my flow state, which was way too precious to break. &lt;/p&gt;

&lt;p&gt;Was I tired? Absolutely!&lt;br&gt;
Was I Burned out or stressed? &lt;strong&gt;Not at all!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In fact, I felt incredible, because I was doing something meaningful and absorbing an enormous amount of knowledge that I knew would pay off massively in the future.&lt;/p&gt;

&lt;p&gt;That's one of the many reasons why I keep coding and writing articles even when I don't have to - I'm addicted to that rewarding feeling of creating something new, whether it's a software or an article.&lt;/p&gt;

&lt;p&gt;So before you label yourself as a burned-out developer, ask yourself: are you just tired, the kind of tired that goes away after a good night's sleep? To find out, try getting a solid 8 hours of sleep for 2-3 days and observe your mood and motivation. If you feel significantly better afterward, congratulations! You're not burned out, you're just tired. You just need a proper system and a good sleep schedule, and you'll be back on track.&lt;/p&gt;

&lt;p&gt;⚠️ However, if you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Feel stressed out all the time&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Struggle to even tackle the simplest tasks at work, like adding a button, implementing a basic CRUD operation, or reviewing a simple code change properly&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feel sleepy during the day but can't fall asleep at night&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Don't know what to chase or focus on when you wake up&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Experience severe anxiety even during a short, easy 15-minute call&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No longer feel excited about new features or enhancements&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Lack discipline and just do things arbitrarily&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only do activities because they're labeled as "fun", without actually enjoying them&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Feel like you're just coasting, working only for your paycheck (and even that doesn't make you properly happy)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Struggle with peak-level impostor syndrome&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then it's likely that you're dealing with real burnout, not just tiredness. And you need to start addressing it as soon as you can.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reflect Honestly on These Factors
&lt;/h3&gt;

&lt;p&gt;When it comes to developer burnout, it's important to reflect on your own habits, mindset, and approach to work and learning. Consider the following factors:&lt;/p&gt;

&lt;h4&gt;
  
  
  Impostor Syndrome
&lt;/h4&gt;

&lt;p&gt;Feeling like you need to be as skilled as developers with years of experience immediately is a common trap. Comparing yourself to others can create unnecessary pressure and stress.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lack of Experience
&lt;/h4&gt;

&lt;p&gt;Mastery takes time. No matter how hard you try, it's unrealistic to expect instant expertise. Understanding this helps set more reasonable expectations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Wrong Direction
&lt;/h4&gt;

&lt;p&gt;Not developing the right skills or learning in an inefficient way can lead to frustration and slow progress. Focus on learning methods that actually help you grow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Overly Self-Critical
&lt;/h4&gt;

&lt;p&gt;Perfectionism is a silent burnout driver. Everyone needs to accept that mistakes and failures are part of learning. It's okay to fail, you can't be perfect all the time.&lt;/p&gt;

&lt;h4&gt;
  
  
  Unreasonable Ambition
&lt;/h4&gt;

&lt;p&gt;Ambition is important, but spreading yourself too thin across multiple programming languages, frameworks, or domains can backfire. Trying to master backend, frontend, mobile, desktop, and game development simultaneously is unrealistic for beginners, and even seasoned developers struggle with that. Focus on one area to specialize in, while maintaining a general understanding of other areas - that's actually where I made a huge mistake.&lt;/p&gt;

&lt;h4&gt;
  
  
  Lack of Goals or Discipline
&lt;/h4&gt;

&lt;p&gt;Having no clear goal or system for growth can be isolating in software engineering. Regardless of how well you're doing at work, personal projects, learning, certifications, research, blogging, or tutorials give your career purpose. To make progress:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Plan your day and allocate time for meaningful work outside of your job.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be mindful of time spent on low-value activities, such as endless scrolling on social media, and replace part of it with growth-oriented activities. Avoid rotting your brain.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recognize that "relaxing" isn't always restorative if it doesn't align with your personal goals. Sometimes burnout comes from passive downtime that doesn't feel productive.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Remember the car analogy? Standing still, engine working, but still slowly getting rusty. The only thing that car needs to start moving forward is to shift into drive.&lt;/strong&gt; For you, finding your "D" gear means identifying the part of your system that actually gets you moving toward meaningful progress, whether it's a disciplined daily routine, a focused learning plan, or a personal project that excites you. Once you engage it, you start moving again, and the rust of stagnation begins to wear off.&lt;/p&gt;

&lt;p&gt;The key is to experiment, reflect, and build your own system. Burnout often comes from a mismatch between your ambitions, your approach to work, and the way you spend your time. Being honest with yourself about these factors is the first step toward breaking the cycle.&lt;/p&gt;

&lt;p&gt;The bottom line is this: break the loop. You need to do something different, anything. Even the wildest idea can work. For example, if you're a back-end engineer, try a front-end project: learn the basics, pick up the prerequisites, and dive in. Don't get stuck in tutorial hell, it only amplifies stress.&lt;/p&gt;

&lt;p&gt;Or start writing tech blogs. Sure, they won't be perfect right off the bat... &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT THAT'S EXACTLY THE POINT!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The excitement of creating something from scratch is &lt;strong&gt;massively&lt;/strong&gt; underrated. It's like entering a whole new world where everything is fresh and exciting.&lt;/p&gt;

&lt;p&gt;That feeling of discomfort and inconvenience? It's actually one of the best feelings you can experience. &lt;strong&gt;Convenience is boring, really boring.&lt;/strong&gt; Living on autopilot is dull, and it slowly but absolutely surely rots your brain. Breaking out of routine and doing something new is how you reconnect with the joy of learning and building again.&lt;/p&gt;

&lt;h2&gt;
  
  
  And This Is Where the Navy SEALs Reference Comes Into Play
&lt;/h2&gt;

&lt;p&gt;I'm not saying you should go through the "Hell Week" on a San Diego beach, carrying boats and logs in freezing water without sleep for five days, like real Navy SEALs do in training that shapes their future (I'd love to try though).&lt;/p&gt;

&lt;p&gt;But let's think about it for a second. Any SEAL can end that excruciating ordeal at any time by simply saying, &lt;em&gt;"I quit"&lt;/em&gt; and the instructors will gladly lead them off the beach to a warm shower.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BUT&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here's a particularly interesting part from one of the books I read a few years ago:&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.amazonaws.com%2Fuploads%2Farticles%2Fua67vh1lvwlhsztapneu.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.amazonaws.com%2Fuploads%2Farticles%2Fua67vh1lvwlhsztapneu.png" alt="Quote" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Which can lead to a lifetime of regret" is the key part here. Even though I had already overcome burnout by the time I read this book, it still offered incredibly valuable lessons. Burnout is closely related to stress, but stress rarely comes from working too much. More often, it comes from feeling like you're not achieving anything or losing control of your career. Regret comes from realizing you've been going about it the wrong way all along.&lt;/p&gt;

&lt;p&gt;Yes, you're in the "warm shower," which is supposed to feel comfortable and safe, but deep down, it doesn't truly make you feel accomplished. Think about it. In hindsight, you'd rather have traded that comfort for a real achievement, but that chance is gone. All you're left with is the warm shower - a fleeting dopamine hit that ultimately gives you absolutely nothing.&lt;/p&gt;

&lt;p&gt;If you had stayed on the beach, continued grinding through discomfort, inconvenience, and pain, even knowing that more challenges awaited, you'd have been growing toward your ultimate goal. Navy SEALs don't train to earn warm showers, they endure the impossible because they want to become elite, doing things most people can't. The discomfort itself is part of the goal.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does This Relate to Our Field?
&lt;/h3&gt;

&lt;p&gt;Yes, it's a completely different game, but most of us sign up to become engineers or tech leads because we genuinely love what we do and believe we can handle the toughness that comes with it. This profession was never meant to be easy.&lt;/p&gt;

&lt;p&gt;Just like a Navy SEAL must stay in shape mentally, physically, and psychologically at all times, tech professionals must constantly learn new skills, practice them, and stay alert to avoid falling behind. In many ways, it's closer to being a professional athlete than to a regular 9–5 job. If you stop training, you just start going backwards right away.&lt;/p&gt;

&lt;p&gt;I personally chose this profession because it isn't something just anyone can do. Not because it's impossible to learn, but because it demands a very specific mindset to stay relevant and competitive over time. Skill alone isn't enough, discipline, curiosity, and consistency are non-negotiable.&lt;/p&gt;

&lt;p&gt;If you truly live and breathe what you do on a daily basis, burnout becomes unlikely. In fact, the opposite happens. Burnout often starts the moment you stop doing that, when learning slows down, growth stalls, and you feel the pressure of standing still while everyone else keeps moving forward.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discipline, Discipline, Discipline!
&lt;/h3&gt;

&lt;p&gt;I've mentioned discipline many times throughout this article and for a very good reason. One thing Navy SEALs are exceptional at, and something without which it's literally impossible to become one, is discipline.&lt;/p&gt;

&lt;p&gt;I believe discipline is one of the most underrated skills anyone can have, especially in a field like software engineering. Reading books about Navy SEALs made me painfully aware of just how undisciplined I had been in comparison. That contrast was eye-opening.&lt;/p&gt;

&lt;p&gt;What I quickly realized is this: an unclear mind and an unstructured life are among the biggest contributors to stress and burnout. Chaos isn't just external, it lives in your daily habits, your routines, and the way you make decisions.&lt;/p&gt;

&lt;p&gt;Discipline removes that chaos. When you're disciplined, you do the work regardless of whether you feel like doing it or not. You don't negotiate with your mood, your motivation, or your temporary emotions. You simply execute.&lt;/p&gt;

&lt;p&gt;And that's exactly why discipline isn't restrictive, it's liberating. It frees your mind from constant decision-making, reduces mental noise, and gives you forward momentum even on the days when motivation is nowhere to be found.&lt;/p&gt;

&lt;p&gt;Discipline builds self-respect, because it proves to you that you do what you said you would and you'll have more trust in yourself in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you want to test your level of discipline, ask yourself this:&lt;br&gt;
Can you stay productive every single day and follow predefined patterns that keep you consistent, or are you productive only when you're forced to be?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example if you wake up at 6:00 AM on weekdays because you have no choice, but sleep until 9:00 AM on weekends and waste the day binge-watching shows or doom-scrolling reels, that's not discipline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Discipline doesn't turn off when your calendar is empty or someone's not watching.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Most Navy SEALs keep their routines long after they retire, often for the rest of their lives. No one is yelling at them anymore. No one is forcing them to wake up early, train, or stay sharp. They do it because comfort makes them weak and structure keeps them dangerous and useful in the best possible sense. They've trained their minds to reject convenience because they've learned a hard truth: comfort feels good short-term, but it destroys you long-term. Discipline, on the other hand, is uncomfortable, but it's the only thing that keeps you useful, relevant, and mentally sharp.&lt;/p&gt;

&lt;p&gt;Being decisive and a doer is one of the strongest traits you can develop to keep burnout away. Overthinking can lead to disaster, in a silent way. Learn to respect the idea of "good enough".&lt;/p&gt;

&lt;p&gt;If your knowledge is good enough to start a new project, pursue a certification, apply for a new job, or even pivot to a new career, just stop hesitating. &lt;strong&gt;Start, and start NOW!&lt;/strong&gt; Put the gear lever into D. The light has been green for a long time, it's been waiting for you to move 🟢.&lt;/p&gt;

&lt;p&gt;Real action is what breaks vicious cycles. Not planning. Not thinking. Not consuming more content. Action. And once you break through that cycle, you prove to yourself that burnout and stress aren't permanent states, they're symptoms of stagnation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;All you need is traction.&lt;br&gt;
Once you have that, acceleration becomes inevitable.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Burnout Hits Software Engineers Differently
&lt;/h2&gt;

&lt;p&gt;As I mentioned at the beginning of this article, burnout exists in every profession. But burnout in software engineering is particularly brutal. Not because we're special or entitled, but because the tech world is unforgiving in ways most fields aren't.&lt;/p&gt;

&lt;p&gt;The pace is relentless. The uncertainty is constant. Technologies change, expectations shift, and the definition of "good enough" keeps moving forward. It's a career that constantly makes you question your skills, your decisions, and sometimes even your choice of profession.&lt;/p&gt;

&lt;p&gt;That persistent doubt is what makes burnout in software engineering so severe.&lt;/p&gt;

&lt;p&gt;Here's a short list of things that often overwhelm software engineers and tech leaders:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Balancing being generalist vs. specialist: should you focus deeply on one area or spread yourself across multiple domains? Finding the right balance is stressful and often feels impossible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design decisions and self-doubt: even when you make the most optimal design choices, you constantly question yourself: could it have been better? What if I missed something?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The endless sea of frameworks and tools: new programming languages, libraries, and frameworks appear constantly. Just keeping up with the pace, especially in fast-moving ecosystems like for example JavaScript is exhausting.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Choice paralysis for learning: you want to stay relevant, but picking what to learn next can feel impossible. It has to be useful, interesting, and applicable in real projects, otherwise it's wasted effort.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Fear of getting rusty: at work, you only use a limited set of skills. Even the most exciting projects can leave you in a routine for months or years. Without coding outside work, other skills atrophy, and anxiety about becoming irrelevant builds.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI and automation fears: while AI can boost productivity, many engineers worry it will replace them. This uncertainty only amplifies stress and burnout.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Changing industry trends: the tech boom of the 2010s made job security feel abundant. Today, layoffs, slowdowns, and shifts caused partially by AI have made the future feel unstable, adding more pressure for every engineer.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Yes, it's tough. Yes, it's real. And yes, it's stressful and worrying. I'm on the same page. But how we position ourselves in the market is entirely up to us. We have every tool we need to become exceptional professionals.&lt;/p&gt;

&lt;p&gt;From my experience, stress and burnout don't help you, not even a little. They don't push you forward, they freeze you in place for weeks, months, or even years. And that's exactly what you don't want as a tech professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Method That Keeps Me Running and Avoids Burnout
&lt;/h2&gt;

&lt;p&gt;My best technique for avoiding stress is embracing the privilege of being in a field that demands nothing less than your absolute best, just like Navy SEALs. They spend their entire careers training, mastering new skills, and taking on missions most minds can barely imagine. But they see it as a privilege, not a burden.&lt;/p&gt;

&lt;p&gt;The same applies to doctors, pilots, professional athletes, CEOs, and other high-stakes professions. These roles are tough, full of responsibility, and often stressful, but when you rise to the challenge, they're also deeply rewarding. Stress becomes a signal of growth, not a trap.&lt;/p&gt;

&lt;p&gt;Who needs a boring job anyway?&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and Exercise for You
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Summary
&lt;/h3&gt;

&lt;p&gt;Burnout is a tricky topic. It's more about psychological exhaustion than physical fatigue, and surprisingly, it's often caused by not using your full potential, not by overworking.&lt;/p&gt;

&lt;p&gt;Finding the most effective ways for using your potential is like driving an F1 car at its limit through a corner. When approaching the corner, you need to slow down by pressing the brake pedal just hard enough not to lock up the tire in the process. Go in too hot and you'll miss the corner. When exiting the corner you need to apply just the right amount of throttle and steering lock not to spin the rear tires, lose the grip and spin around, causing losing a significant amount of time.&lt;/p&gt;

&lt;p&gt;Developer burnout is much the same. Spin your tires in the wrong way - mismanage your energy, progress, or focus and friction builds up, smoke rises, and you stall. The solution? Be methodical. Balance your pace, check your progress, and manage your energy carefully. That's how you win the race and your career.&lt;/p&gt;

&lt;p&gt;And the foundation of all this? Discipline. Everything else like skills, growth, success builds on top of it. &lt;strong&gt;Everything!&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The Excercise
&lt;/h3&gt;

&lt;p&gt;I'm not going to give you strict step-by-step rules, because everyone's personality and situation is different. Instead, here's a high-level framework, you can customize it to what works best for you.&lt;/p&gt;

&lt;p&gt;If you're suffering from burnout, try the following for the next full month:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Map your vicious cycle: pick a day to sit down and identify where you're stuck. Physically draw the cycle that stresses you out.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Find the weakest point: where can the cycle be broken? For example, if you're not doing personal projects but have time, start there. Pick an idea, it doesn't need to be groundbreaking. Even something simple, like a todo app, works.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit fully, take it seriously: attach yourself to your idea, project, certification, or blog. Think about it often, the more you engage, the easier and more exciting it becomes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Avoid quick dopamine hits: please stay off social media, reels, and other brain-rotting distractions. Instead, focus on the long-term satisfaction of completing your project and the impact it can have.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use AI wisely: tools are helpful, but you're the operator. Find a balance between using it too much and not using it at all.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Stick to a strict morning routine: wake up early and follow the routine every day, &lt;strong&gt;even on weekends or holidays.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Be mindful of your time: plan, track, and manage it carefully.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Document your progress: keep a log of what you do daily.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit daily: make GitHub commits or other measurable actions to track consistency.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Whenever you have to do something, do it now: don't procrastinate. Bugs, refactoring, learning, or tests, do it now. &lt;strong&gt;There's no better moment than the present.&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After a month, compare how you feel now to how you felt at the start. Don't worry if your project isn't finished, that's not the goal. The goal is consistency, reflection, and growth.&lt;/p&gt;

&lt;p&gt;If you love the process, keep going, it will do wonders for you. If you hate it, first check honestly: were you consistent, or did you slack off? Either way, you'll gain clarity on what you need to improve to reduce stress and burnout.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Remember: you're in a privileged position, don't waste it!&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>productivity</category>
      <category>discuss</category>
      <category>devjournal</category>
    </item>
    <item>
      <title>.NET 10: The Performance Beast That's Redefining Modern Application Development</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sun, 14 Dec 2025 13:47:37 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/net-10-the-performance-beast-thats-redefining-modern-application-development-35jn</link>
      <guid>https://forem.com/georgekobaidze/net-10-the-performance-beast-thats-redefining-modern-application-development-35jn</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
Introduction

&lt;ul&gt;
&lt;li&gt;Microsoft's Boldest .NET Release Yet&lt;/li&gt;
&lt;li&gt;What This Article Covers and Who Should Read It?&lt;/li&gt;
&lt;li&gt;.NET Support Policy&lt;/li&gt;
&lt;li&gt;Playground Repository&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

C# 14: Language Features

&lt;ul&gt;
&lt;li&gt;Extension Members&lt;/li&gt;
&lt;li&gt;Null Conditional Assignment&lt;/li&gt;
&lt;li&gt;Field Access in Auto Properties&lt;/li&gt;
&lt;li&gt;Simple Lambda Parameters With Modifiers&lt;/li&gt;
&lt;li&gt;User-Defined Compound Assignment Operators&lt;/li&gt;
&lt;li&gt;Partial Events and Constructors&lt;/li&gt;
&lt;li&gt;Unbound Generic Types in nameof&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

.NET 10 New Features

&lt;ul&gt;
&lt;li&gt;File-Based Apps&lt;/li&gt;
&lt;li&gt;Validation in Minimal APIs&lt;/li&gt;
&lt;li&gt;MCP for .NET Developers&lt;/li&gt;
&lt;li&gt;Security Improvements&lt;/li&gt;
&lt;li&gt;Aspire 13&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Other Changes

&lt;ul&gt;
&lt;li&gt;Visual Studio 2026&lt;/li&gt;
&lt;li&gt;Github Copilot App Modernization&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

Summary

&lt;ul&gt;
&lt;li&gt;What We Covered&lt;/li&gt;
&lt;li&gt;Migration Recommendations&lt;/li&gt;
&lt;li&gt;Final Thoughts&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




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

&lt;h3&gt;
  
  
  Microsoft's Boldest .NET Release Yet
&lt;/h3&gt;

&lt;p&gt;After years of relentless innovation Microsoft drops &lt;strong&gt;.NET 10&lt;/strong&gt; in November 2025 with a clear message: &lt;strong&gt;performance, developer productivity, AI, and cloud-native excellence are no longer competing priorities they're table stakes.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;.NET 10 isn't just an incremental update. It represents a fundamental shift in how we think about building applications in an AI-first, cloud-native world. With major performance improvements in critical paths, C# 14's game-changing language features, and ASP.NET Core's radical simplification of web development, this release challenges everything we thought we knew about the limits of managed runtime performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  What This Article Covers and Who Should Read It?
&lt;/h3&gt;

&lt;p&gt;This article is for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.NET developers&lt;/strong&gt; who are unsure about upgrading to the latest version &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-.NET developers&lt;/strong&gt; who are hesitant about adopting .NET&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you're a:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backend developer&lt;/strong&gt; drowning in latency requirements and looking for legitimate performance gains&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend developer&lt;/strong&gt; who's fed up with endless JavaScript churn and tangled toolchains, Blazor and MAUI offer a cleaner, unified, C#-powered alternative that actually lets you focus on building, not babysitting frameworks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Architect&lt;/strong&gt; evaluating whether .NET 10's LTS stability combined with cutting-edge features makes it the right choice for new projects&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engineering manager / Tech Lead&lt;/strong&gt; making platform decisions that will impact the next 3-5 years while balancing delivery pressure, team productivity, and long-term maintainability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full-stack engineer&lt;/strong&gt; tired of maintaining separate frontend and backend codebases&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevOps engineer&lt;/strong&gt; optimizing container costs and deployment pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll find concrete, actionable insights backed by benchmarks, code examples, and real-world migration experiences.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Disclaimer: This is a large article with a lot of information and reasonable depth. However it still doesn't cover everything introduced recently, doing that would require a 900-page book (or more).&lt;/p&gt;

&lt;p&gt;The goal here is to highlight the most interesting and useful additions from my perspective, share my opinions and trade-offs, and provide demo examples that make each topic easier to understand.&lt;/p&gt;

&lt;p&gt;As a principal software engineer myself, I'll need to work with this framework at some point, so this article also serves as structured notes for my future self - a way to quickly regain context and insights without relearning everything from scratch.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  .NET Support Policy
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Here's the best part&lt;/strong&gt;: .NET 10 is a Long Term Support (LTS) release, supported for three full years until November 2028. Unlike .NET 9 (STS) which only receives 18 months of support, .NET 10 combines cutting-edge features with enterprise-grade stability.&lt;/p&gt;

&lt;p&gt;Check out the .NET lifecycle table for the currently supported versions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Version&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Original Release Date&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Release Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;End of Support&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.NET 10&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;November 11, 2025&lt;/td&gt;
&lt;td&gt;LTS&lt;/td&gt;
&lt;td&gt;November 14, 2028&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.NET 9&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;November 12, 2024&lt;/td&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;November 10, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;.NET 8&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;November 14, 2023&lt;/td&gt;
&lt;td&gt;LTS&lt;/td&gt;
&lt;td&gt;November 10, 2026&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;.NET follows a predictable release cadence where even-numbered versions receive Long Term Support (LTS). This makes .NET 10 the perfect storm for adoption: you get bleeding-edge features wrapped in enterprise-grade support commitments. Unlike .NET 9 which forces you to choose between cutting-edge capabilities and long-term stability, .NET 10 delivers both. This is the sweet spot: groundbreaking performance improvements with the long-term commitment that production systems demand. Sounds like a great deal doesn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Playground Repository
&lt;/h3&gt;

&lt;p&gt;Some of the code examples in this article comes from real, runnable code in my repository. Rather than trust code snippets and demos, you can clone the repository, run the code on your own hardware, and see how it all plays out for yourself.&lt;/p&gt;

&lt;p&gt;Also, feel free to fork the repository add your own code and create pull requests to contribute.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/georgekobaidze" rel="noopener noreferrer"&gt;
        georgekobaidze
      &lt;/a&gt; / &lt;a href="https://github.com/georgekobaidze/dotnet10-playground" rel="noopener noreferrer"&gt;
        dotnet10-playground
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;.NET 10 &amp;amp; C# 14 Playground&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;A lightweight playground repository for experimenting with and testing new features introduced in .NET 10 and C# 14.&lt;/p&gt;
&lt;p&gt;Use it to explore language changes, try out APIs, and validate ideas in isolation without production constraints.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/georgekobaidze/dotnet10-playground" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;p&gt;If you'd like to follow along, start by downloading and installing .NET 10 from the following link: &lt;a href="https://dotnet.microsoft.com/en-us/download/dotnet/10.0" rel="noopener noreferrer"&gt;https://dotnet.microsoft.com/en-us/download/dotnet/10.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To generate a repository with a structure similar to mine, it's much easier to use the CLI than to manually create files and folders through a GUI. You can follow the instructions I outlined in one of my previous articles:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/kickstarting-a-net-solution-from-scratch-with-the-cli-1m97" class="crayons-story__hidden-navigation-link"&gt;Kickstarting a .NET Solution from Scratch with the CLI&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2492350" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/kickstarting-a-net-solution-from-scratch-with-the-cli-1m97" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 15 '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/kickstarting-a-net-solution-from-scratch-with-the-cli-1m97" id="article-link-2492350"&gt;
          Kickstarting a .NET Solution from Scratch with the CLI
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&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/softwareengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwareengineering&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/terminal"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;terminal&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/kickstarting-a-net-solution-from-scratch-with-the-cli-1m97" 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;15&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/kickstarting-a-net-solution-from-scratch-with-the-cli-1m97#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&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;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;Now that the groundwork is laid, let's dive in.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  C# 14: Language Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Extension Members
&lt;/h3&gt;

&lt;p&gt;This is an interesting new feature that could reshape how we write extension methods. And on top of that, we now also have things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extension properties&lt;/li&gt;
&lt;li&gt;Extension operators&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best way to describe the purpose of extension methods is that they &lt;em&gt;"enable you to "add" methods to existing types without creating a derived type, recompiling, or modifying the original type."&lt;/em&gt; This definition comes straight from Microsoft's official documentation.&lt;/p&gt;

&lt;p&gt;The most interesting part is that this feature isn't just more syntactic sugar, it's something new to C#, with real potential to simplify code and make it more elegant and readable. And, of course, it's completely optional, whether you choose to use it is entirely up to you.&lt;/p&gt;

&lt;h4&gt;
  
  
  Syntax
&lt;/h4&gt;

&lt;p&gt;Instead of the traditional way &lt;code&gt;(static class + this keyword in method parameter)&lt;/code&gt;, C# 14 allows a cleaner &lt;code&gt;extension(...) { ... }&lt;/code&gt; block inside a static class.&lt;/p&gt;

&lt;p&gt;Inside this block, you define extension methods, properties, or even operators, and the "receiver" type (the type you're extending) is declared just once.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example
&lt;/h4&gt;

&lt;p&gt;Let's implement examples for each type of extension member so we can explore their full potential and see exactly how they behave.&lt;/p&gt;

&lt;p&gt;I'm going to use the &lt;code&gt;ConsolePlayground&lt;/code&gt; project for this task from my repository.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The "Point"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's make our example about a Point, because, well, what's the point without a point, right? Get it?😏 OK, I see myself out.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ever taken a math class? Then you probably remember that a point has two coordinates: &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt;. (Sure, it can have more, but we're just trying to make up an example alright? We're not trying to launch a Mars rover here. Not yet, anyway.)&lt;/p&gt;

&lt;p&gt;This definition opens the door pretty wide for modeling a point mathematically and turning all that into code. Don't worry, we're not going full "mad scientist" here. We'll just add a few properties, methods, and operators for demo purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Let's define the following members:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extension properties:&lt;/strong&gt; &lt;code&gt;Magnitude&lt;/code&gt; and &lt;code&gt;IsAtOrigin&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static extension properties:&lt;/strong&gt; &lt;code&gt;Origin&lt;/code&gt; and &lt;code&gt;UnitX&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Instance Extension Methods:&lt;/strong&gt; &lt;code&gt;Translate&lt;/code&gt; and &lt;code&gt;DistanceTo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Static Extension Method:&lt;/strong&gt; &lt;code&gt;FromPolar&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extension Operators (Binary):&lt;/strong&gt; &lt;code&gt;+&lt;/code&gt; and &lt;code&gt;*&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extension operator (Unary):&lt;/strong&gt; &lt;code&gt;-&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let's create the &lt;code&gt;Point.cs&lt;/code&gt; file, which will contain a record for Point.&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;record&lt;/span&gt; &lt;span class="nc"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And a separate file for the extensions: &lt;code&gt;PointExtensions.cs&lt;/code&gt;&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;class&lt;/span&gt; &lt;span class="nc"&gt;PointExtensions&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;extension&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Instance Extension Properties&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Magnitude&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;IsAtOrigin&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// Static Extension Properties&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;Origin&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&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="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;UnitX&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Instance Extension Methods&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="nf"&gt;Translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;DistanceTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dx&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dx&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dy&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// Static Extension Method&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="nf"&gt;FromPolar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;radius&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;angleRadians&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="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&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="n"&gt;angleRadians&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;radius&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&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="n"&gt;angleRadians&lt;/span&gt;&lt;span class="p"&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;// Extension Operators (Binary)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;+(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;left&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;right&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&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="n"&gt;Point&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;*(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;scalar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Extension Operator (Unary)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;-(&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&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;p&gt;This shows how each extension member works. It's all very straightforward. The only truly new piece of syntax here is &lt;code&gt;extension(...) { ... }&lt;/code&gt;, and even that feels pretty intuitive.&lt;/p&gt;

&lt;p&gt;Now, to make things even clearer, let's open &lt;code&gt;Program.cs&lt;/code&gt; and see how we can actually use these extension members.&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;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=== C# 14 Extension Members Demo ===\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Static Extension Properties&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1. Static Extension Properties:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Point.Origin = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Origin&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Point.UnitX = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnitX&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="c1"&gt;// Static Extension Method&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n2. Static Extension Method:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;polar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromPolar&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;span class="n"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PI&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Point.FromPolar(5, π/4) = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;polar&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="c1"&gt;// Instance Extension Properties&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n3. Instance Extension Properties:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;point1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Point&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="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   point1 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;point1&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   point1.Magnitude = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Magnitude&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   point1.IsAtOrigin = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsAtOrigin&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="c1"&gt;// Instance Extension Methods&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n4. Instance Extension Methods:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;point2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;(-&lt;/span&gt;&lt;span class="m"&gt;2&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;translated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Translate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   point1.Translate(1, 1) = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;translated&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DistanceTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;point2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   point1.DistanceTo(point2) = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;F2&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="c1"&gt;// Extension Operators&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n5. Extension Operators:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;point2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&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="n"&gt;point1&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="n"&gt;point2&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="n"&gt;sum&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;point1&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&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="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; * 2 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;product&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;negated&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;point1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&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="n"&gt;point1&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="n"&gt;negated&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="c1"&gt;// Combined Usage&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n6. Combined Usage:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;complexExpression&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Origin&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;Point&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;UnitX&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Origin + UnitX*2 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;complexExpression&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n=== Demo Complete ==="&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It'll output the following result:&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.amazonaws.com%2Fuploads%2Farticles%2F3jlrbd6rjdppub5femm3.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.amazonaws.com%2Fuploads%2Farticles%2F3jlrbd6rjdppub5femm3.png" alt="Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I'm sold!&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  Null Conditional Assignment
&lt;/h3&gt;

&lt;p&gt;If you've been writing C# for a while, you're probably familiar with the null-conditional operator (&lt;code&gt;?.&lt;/code&gt;) and the null-coalescing operator (&lt;code&gt;??&lt;/code&gt;). These have been lifesavers for avoiding &lt;code&gt;NullReferenceException&lt;/code&gt; and writing cleaner null-handling code. But there's always been one annoying gap: &lt;strong&gt;you couldn't use &lt;code&gt;?.&lt;/code&gt; on the left side of an assignment&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Consider this common scenario: you have a nested object, and you only want to assign a value to a property if the parent object isn't null. Before C# 14, you had to write something like 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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Address&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="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Seattle"&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;Or the slightly more verbose version:&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;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="k"&gt;not&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Seattle"&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;It works, but it's clunky. You're essentially checking for null twice, once in your condition and once implicitly when you access the property.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C# 14 fixes this with null-conditional assignment.&lt;/strong&gt; You can now write:&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;person&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Seattle"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it. One line. If &lt;code&gt;person&lt;/code&gt; is null, nothing happens. If &lt;code&gt;person.Address&lt;/code&gt; is null, nothing happens. Only if both are non-null does the assignment occur. No exception, no ceremony, just clean, readable code.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Is This Important?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduced boilerplate&lt;/strong&gt;: You no longer need verbose null checks scattered throughout your code just to safely assign values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: The &lt;code&gt;?.&lt;/code&gt; operator already works for method calls and property access. Now it works for assignments too, making the language more consistent and predictable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Fewer bugs&lt;/strong&gt;: Every time you write an &lt;code&gt;if&lt;/code&gt; statement, there's a chance you'll get it wrong. Maybe you forget to check one level of nesting, or you accidentally use &lt;code&gt;||&lt;/code&gt; instead of &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt;. Null-conditional assignment eliminates these opportunities for mistakes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Better readability&lt;/strong&gt;: Code intent is immediately clear. When someone reads &lt;code&gt;person?.Address?.City = "Seattle"&lt;/code&gt;, they instantly understand: "assign this value only if the path is valid."&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Demo Example
&lt;/h4&gt;

&lt;p&gt;Let's see this in action. I'll use the &lt;code&gt;ConsolePlayground&lt;/code&gt; project to demonstrate a practical scenario.&lt;/p&gt;

&lt;p&gt;Imagine we're building a user profile system where users can optionally have address information:&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;record&lt;/span&gt; &lt;span class="nc"&gt;Address&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Street&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Country&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&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;record&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&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;p&gt;Now let's write some code that updates the address information using null-conditional assignment:&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;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=== C# 14 Null Conditional Assignment Demo ===\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Scenario 1: Person with an address&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;personWithAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Alice"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Address&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Street&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"123 Main St"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Portland"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Before update:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&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="n"&gt;personWithAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'s city: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;personWithAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&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="c1"&gt;// Using null-conditional assignment&lt;/span&gt;
&lt;span class="n"&gt;personWithAddress&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Seattle"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"After update:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&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="n"&gt;personWithAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;'s city: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;personWithAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&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="c1"&gt;// Scenario 2: Person without an address&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;personWithoutAddress&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bob"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"\n&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;personWithoutAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; has no address."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Attempting to set city using null-conditional assignment..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This safely does nothing because Address is null&lt;/span&gt;
&lt;span class="n"&gt;personWithoutAddress&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"New York"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"  City after attempted assignment: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;personWithoutAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="s"&gt;"(no address)"&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="c1"&gt;// Scenario 3: Null person reference&lt;/span&gt;
&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;nullPerson&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;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\nAttempting to set city on a null person reference..."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// This safely does nothing because nullPerson is null&lt;/span&gt;
&lt;span class="n"&gt;nullPerson&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;City&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Chicago"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"  No exception thrown! Assignment was safely skipped."&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n=== Demo Complete ==="&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running this code produces the following output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== C# 14 Null Conditional Assignment Demo ===

Before update:
  Alice's city: Portland
After update:
  Alice's city: Seattle

Bob has no address.
Attempting to set city using null-conditional assignment...
  City after attempted assignment: (no address)

Attempting to set city on a null person reference...
  No exception thrown! Assignment was safely skipped.

=== Demo Complete ===
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;As you can see, the null-conditional assignment gracefully handles all three scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the full path exists, the assignment works as expected&lt;/li&gt;
&lt;li&gt;When part of the path is null, the assignment is simply skipped&lt;/li&gt;
&lt;li&gt;When the root object is null, no exception is thrown&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  The Old Way vs. The New Way
&lt;/h4&gt;

&lt;p&gt;Here's a side-by-side comparison to really drive home how much cleaner this is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before C# 14:&lt;/strong&gt;&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;if&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;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;order&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;null&lt;/span&gt; &lt;span class="p"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;order&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="n"&gt;Preferences&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="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="n"&gt;Customer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Preferences&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NotificationsEnabled&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;C# 14:&lt;/strong&gt;&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;order&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="n"&gt;Preferences&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;NotificationsEnabled&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;The improvement speaks for itself. Less code, fewer chances for bugs, and the intent is crystal clear.&lt;/p&gt;

&lt;p&gt;This might seem like a small change, but it's exactly the kind of quality-of-life improvement that makes a language more enjoyable to use day-to-day. It's one less thing to think about, one less pattern to remember, and one less source of potential bugs.&lt;/p&gt;


&lt;h3&gt;
  
  
  Field Access in Auto Properties
&lt;/h3&gt;

&lt;p&gt;Auto-properties have been one of C#'s most beloved features since their introduction. They let you write &lt;code&gt;public string Name { get; set; }&lt;/code&gt; instead of manually declaring a backing field and wiring up the getter and setter. Clean, simple, elegant.&lt;/p&gt;

&lt;p&gt;But here's the problem: the moment you need to add any logic to your property, like validation, transformation, or lazy initialization, you lose the auto-property syntax entirely. You have to fall back to the old-school approach:&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name cannot be empty"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&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;p&gt;Suddenly you're back to declaring backing fields, picking naming conventions (&lt;code&gt;_name&lt;/code&gt;, &lt;code&gt;m_name&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;), and dealing with extra boilerplate. For a single property it's fine, but when you have a dozen properties (or hundreds of properties) that all need validation, your class becomes a wall of repetitive code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C# 14 introduces the &lt;code&gt;field&lt;/code&gt; keyword&lt;/strong&gt;, which gives you direct access to the compiler-generated backing field within your property accessors. Now you can write:&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="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Name cannot be empty"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&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;p&gt;No explicit backing field declaration needed. The compiler creates one for you, and you access it using the contextual keyword &lt;code&gt;field&lt;/code&gt;. You get the best of both worlds: the conciseness of auto-properties with the flexibility of custom logic.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Is This Important?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Less boilerplate&lt;/strong&gt;: You don't need to declare backing fields manually anymore. The compiler handles it, and you just reference &lt;code&gt;field&lt;/code&gt; when you need it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cleaner code&lt;/strong&gt;: Your classes stay focused on what matters, the logic, rather than being cluttered with field declarations and naming conventions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: No more debates about &lt;code&gt;_name&lt;/code&gt; vs &lt;code&gt;m_name&lt;/code&gt; vs &lt;code&gt;name&lt;/code&gt;. The backing field is anonymous and accessed uniformly via &lt;code&gt;field&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gradual enhancement&lt;/strong&gt;: You can start with a simple auto-property and add logic later without restructuring your code. Just add the accessor body and use &lt;code&gt;field&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Works with both get and set&lt;/strong&gt;: You can use &lt;code&gt;field&lt;/code&gt; in either accessor, or both, depending on your needs.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  Demo Example
&lt;/h4&gt;

&lt;p&gt;Let's build a practical example. Imagine we're creating a &lt;code&gt;Product&lt;/code&gt; class for an e-commerce system with properties that need validation and transformation:&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;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simple validation: price must be non-negative&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&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="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"Price cannot be negative"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&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;// Transformation: automatically trim and capitalize the name&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsNullOrWhiteSpace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Product name cannot be empty"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Lazy initialization with field access in getter&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Slug&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;??=&lt;/span&gt; &lt;span class="nf"&gt;GenerateSlug&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Stock quantity with change tracking&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;StockQuantity&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&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="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"Stock cannot be negative"&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;oldValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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="n"&gt;oldValue&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Stock changed from &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;oldValue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; to &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;value&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="p"&gt;}&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="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;GenerateSlug&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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now let's test this class:&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;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=== C# 14 Field Keyword Demo ===\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;productItem&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Test Name with trimming&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"1. Setting product name with extra whitespace:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"   Wireless Headphones   "&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Stored name: \"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&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="c1"&gt;// Test Price validation&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n2. Setting valid price:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;99.99m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Price: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;C&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n3. Attempting to set negative price:"&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="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="m"&gt;10m&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="n"&gt;ArgumentOutOfRangeException&lt;/span&gt; &lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Caught exception: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&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="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Test lazy slug generation&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n4. Accessing slug (lazy initialization):"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"   Slug: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Slug&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="c1"&gt;// Test stock quantity with change tracking&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n5. Updating stock quantity:"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StockQuantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StockQuantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;productItem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StockQuantity&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;95&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// No change, no message&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n=== Demo Complete ==="&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Running this produces:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== C# 14 Field Keyword Demo ===

1. Setting product name with extra whitespace:
   Stored name: "Wireless Headphones"

2. Setting valid price:
   Price: $99.99

3. Attempting to set negative price:
   Caught exception: Price cannot be negative (Parameter 'value')

4. Accessing slug (lazy initialization):
   Slug: wireless-headphones

5. Updating stock quantity:
Stock changed from 0 to 100
Stock changed from 100 to 95

=== Demo Complete ===
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  The Old Way vs. The New Way
&lt;/h4&gt;

&lt;p&gt;Let's compare a class with multiple validated properties:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before C# 14:&lt;/strong&gt;&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;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;_age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;_username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_email&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'@'&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;_email&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;150&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="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="n"&gt;_age&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_username&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;3&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Username too short"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;_username&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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="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;strong&gt;C# 14:&lt;/strong&gt;&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;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Email&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'@'&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Invalid email"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToLowerInvariant&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Age&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;||&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;150&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="nf"&gt;ArgumentOutOfRangeException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Username&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&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="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;3&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="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Username too short"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&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="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;The C# 14 version eliminates all the backing field declarations at the top of the class. It's cleaner, more focused, and the relationship between each property and its validation logic is immediately clear.&lt;/p&gt;
&lt;h4&gt;
  
  
  Why Did This Take So Long?
&lt;/h4&gt;

&lt;p&gt;If you've been following C# development, you might know that this feature has been on the wishlist for &lt;em&gt;years&lt;/em&gt;. Developers have been asking for it since auto-properties were first introduced. So why did it take until C# 14?&lt;/p&gt;

&lt;p&gt;The answer is simple but important: &lt;strong&gt;BREAKING CHANGES&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The word &lt;code&gt;field&lt;/code&gt; is not a reserved keyword in C#. It's a perfectly valid identifier. That means there's existing code out there that looks like 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="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeClass&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// A variable literally named "field"&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&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;p&gt;If Microsoft had simply made &lt;code&gt;field&lt;/code&gt; a full keyword, this code would break. Every project using &lt;code&gt;field&lt;/code&gt; as a variable name would suddenly fail to compile. That's millions of lines of code across the ecosystem potentially affected.&lt;/p&gt;

&lt;p&gt;The .NET team had to be extremely careful here. They needed to introduce the feature without breaking existing codebases. The solution? Make &lt;code&gt;field&lt;/code&gt; a &lt;strong&gt;contextual keyword&lt;/strong&gt;, meaning it only has special meaning in a specific context, inside property accessors where there's no local variable or parameter named &lt;code&gt;field&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What if you have an existing member named &lt;code&gt;field&lt;/code&gt;?&lt;/strong&gt; If your class already has a field literally named &lt;code&gt;field&lt;/code&gt; and you want to access it inside a property accessor (where the keyword takes precedence), you have two options:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use the &lt;code&gt;this&lt;/code&gt; keyword: &lt;code&gt;this.field&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use the &lt;code&gt;@&lt;/code&gt; escape: &lt;code&gt;@field&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these explicitly tell the compiler "I mean my variable, not the backing field keyword."&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;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;42&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Your own field named 'field'&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;set&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Refers to the class member (42)&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;@field&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// Also refers to the class member (42)&lt;/span&gt;
            &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                  &lt;span class="c1"&gt;// Refers to the backing field keyword&lt;/span&gt;
        &lt;span class="p"&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;p&gt;This careful approach means your existing code continues to work exactly as before. The new feature is purely additive, and when naming conflicts arise, you have clear escape hatches to disambiguate.&lt;/p&gt;

&lt;p&gt;This is a great example of how language design isn't just about adding cool features. It's about doing so responsibly, respecting the vast ecosystem of existing code, and maintaining the trust that developers have placed in backward compatibility.&lt;/p&gt;
&lt;h4&gt;
  
  
  Important Notes
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;field&lt;/code&gt; keyword is contextual, it only has special meaning inside property accessors. If you have an existing field named &lt;code&gt;field&lt;/code&gt; in your code, it will still work, but you might want to rename it for clarity to avoid confusion.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You can use &lt;code&gt;field&lt;/code&gt; with property initializers: &lt;code&gt;public string Name { get; set =&amp;gt; field = value.Trim(); } = "Default";&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;This feature works with &lt;code&gt;init&lt;/code&gt; accessors too, not just &lt;code&gt;set&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is one of those features that might seem minor at first glance, but once you start using it, you'll wonder how you ever lived without it. It removes friction from a very common pattern and makes C# properties even more powerful.&lt;/p&gt;


&lt;h3&gt;
  
  
  Simple Lambda Parameters With Modifiers
&lt;/h3&gt;

&lt;p&gt;Lambda expressions in C# support type inference, so you can write &lt;code&gt;x =&amp;gt; x * 2&lt;/code&gt; instead of &lt;code&gt;(int x) =&amp;gt; x * 2&lt;/code&gt;. But there's been one annoying exception: &lt;strong&gt;the moment you add a parameter modifier, you lose the concise syntax&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Before C# 14, if you wanted to use &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;out&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, or &lt;code&gt;params&lt;/code&gt; in a lambda, you had to explicitly specify the type:&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;// Without modifier - type is inferred&lt;/span&gt;
&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;square&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// With modifier - forced to specify type&lt;/span&gt;
&lt;span class="n"&gt;RefAction&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;doubleIt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;C# 14 removes this limitation.&lt;/strong&gt; You can now use modifiers without specifying the type:&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;RefAction&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;doubleIt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Supported Modifiers
&lt;/h4&gt;

&lt;p&gt;All parameter modifiers work with implicit typing: &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;out&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, &lt;code&gt;ref readonly&lt;/code&gt;, &lt;code&gt;scoped&lt;/code&gt;, and &lt;code&gt;params&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  The Old Way vs. The New Way
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Before C# 14:&lt;/strong&gt;&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;ProcessData&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;TryParseAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&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;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Vector3&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;C# 14:&lt;/strong&gt;&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;ProcessData&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;TryParseAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;TryParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nf"&gt;Calculate&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The improvement is especially valuable in high-performance code where &lt;code&gt;ref&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, and &lt;code&gt;Span&amp;lt;T&amp;gt;&lt;/code&gt; are common. Instead of cluttering your lambdas with type annotations that the compiler can already infer, you just add the modifier you need and move on.&lt;/p&gt;


&lt;h3&gt;
  
  
  User-Defined Compound Assignment Operators
&lt;/h3&gt;

&lt;p&gt;In C#, when you write &lt;code&gt;x += 5&lt;/code&gt;, the compiler translates it to &lt;code&gt;x = x + 5&lt;/code&gt;. This works fine for most cases, but there's a problem: &lt;strong&gt;what if you want &lt;code&gt;+=&lt;/code&gt; to behave differently than &lt;code&gt;+&lt;/code&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This matters for performance-sensitive types. Consider a &lt;code&gt;StringBuilder&lt;/code&gt;-like type or a collection. When you write &lt;code&gt;list = list + item&lt;/code&gt;, you're creating a new object and reassigning. But &lt;code&gt;list += item&lt;/code&gt; could modify the existing object in place, which is far more efficient.&lt;/p&gt;

&lt;p&gt;Before C# 14, you couldn't express this distinction. Compound assignment always expanded to the binary operator plus assignment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C# 14 lets you define compound assignment operators separately.&lt;/strong&gt; The &lt;code&gt;+=&lt;/code&gt; operator can now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Return &lt;code&gt;void&lt;/code&gt; instead of the type&lt;/li&gt;
&lt;li&gt;Take the first parameter by &lt;code&gt;ref&lt;/code&gt;, allowing in-place modification&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Demo Example
&lt;/h4&gt;

&lt;p&gt;Let's create a custom 2D vector type to demonstrate this feature:&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;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"=== C# 14 User-Defined Compound Assignment Operators Demo ===\n"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vec2D&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="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vec2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"v1 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v1&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"v2 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v2&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="c1"&gt;// Using + operator (creates new instance)&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\nUsing + operator (creates new instance):"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;v3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"v3 = v1 + v2 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v3&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="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"v1 is still: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (unchanged)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Using += operator (modifies in place)&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\nUsing += operator (modifies in place):"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Before: v1 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v1&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="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"After v1 += v2: v1 = &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; (modified!)"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"\n=== Demo Complete ==="&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Custom 2D vector struct&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Vec2D&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Vec2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Regular + operator - creates new instance&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Vec2D&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;+(&lt;/span&gt;&lt;span class="n"&gt;Vec2D&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Vec2D&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Vec2D&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// C# 14: Compound assignment operator - modifies in place&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="p"&gt;+=(&lt;/span&gt;&lt;span class="k"&gt;ref&lt;/span&gt; &lt;span class="n"&gt;Vec2D&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Vec2D&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Y&lt;/span&gt;&lt;span class="p"&gt;;&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;override&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"(&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;X&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="n"&gt;Y&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;=== C# 14 User-Defined Compound Assignment Operators Demo ===

v1 = (3, 4)
v2 = (1, 2)

Using + operator (creates new instance):
v3 = v1 + v2 = (4, 6)
v1 is still: (3, 4) (unchanged)

Using += operator (modifies in place):
Before: v1 = (3, 4)
After v1 += v2: v1 = (4, 6) (modified!)

=== Demo Complete ===
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h4&gt;
  
  
  Why Is This Important?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance&lt;/strong&gt;: Avoid unnecessary allocations by modifying objects in place instead of creating new ones.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Semantic clarity&lt;/strong&gt;: &lt;code&gt;+&lt;/code&gt; means "combine and create new", while &lt;code&gt;+=&lt;/code&gt; means "append to existing". Now your code can reflect that distinction.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Mutable collections&lt;/strong&gt;: Types like &lt;code&gt;List&amp;lt;T&amp;gt;&lt;/code&gt; or custom buffers can now have &lt;code&gt;+=&lt;/code&gt; mean "add to this collection" rather than "create a new collection with this item added".&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;
  
  
  The Old Way vs. The New Way
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Before C# 14:&lt;/strong&gt;&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;// Both operations did the same thing - create new instance&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// Creates new instance&lt;/span&gt;
&lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// What += expanded to - also creates new instance&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;C# 14:&lt;/strong&gt;&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="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Creates new instance&lt;/span&gt;
&lt;span class="n"&gt;v1&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;v2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// Modifies v1 in place (if custom += is defined)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This feature is particularly useful for numeric types, buffers, builders, and any scenario where in-place mutation is more efficient than creating new instances. It's a niche but powerful addition for library authors and performance-critical code.&lt;/p&gt;


&lt;h3&gt;
  
  
  Partial Events and Constructors
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;partial&lt;/code&gt; keyword has been in C# for a long time, allowing you to split a class across multiple files. More recently, C# added partial methods and partial properties. &lt;strong&gt;C# 14 completes the picture by adding partial events and partial constructors.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is especially useful for &lt;strong&gt;source generators&lt;/strong&gt;. A generator can declare a partial constructor or event, and you provide the implementation in your own code. It keeps generated code separate from hand-written code while allowing them to work together seamlessly.&lt;/p&gt;
&lt;h4&gt;
  
  
  Partial Constructors
&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;// File: MyClass.Generated.cs (from source generator)&lt;/span&gt;
&lt;span class="k"&gt;public&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;MyClass&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;partial&lt;/span&gt; &lt;span class="nf"&gt;MyClass&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;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// Declaration&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// File: MyClass.cs (your code)&lt;/span&gt;
&lt;span class="k"&gt;public&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;MyClass&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;partial&lt;/span&gt; &lt;span class="nf"&gt;MyClass&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;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;// Implementation&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nf"&gt;Initialize&lt;/span&gt;&lt;span class="p"&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;h4&gt;
  
  
  Partial Events
&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;// File: MyComponent.Generated.cs&lt;/span&gt;
&lt;span class="k"&gt;public&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;MyComponent&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;partial&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;StatusChanged&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// Declaration&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// File: MyComponent.cs&lt;/span&gt;
&lt;span class="k"&gt;public&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;MyComponent&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;partial&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;StatusChanged&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;add&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_statusChanged&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;remove&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;_statusChanged&lt;/span&gt; &lt;span class="p"&gt;-=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;EventHandler&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;_statusChanged&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;h4&gt;
  
  
  Why Is This Important?
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Source generator friendly&lt;/strong&gt;: Generators can declare the shape of constructors and events, while you control the implementation details.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Clean separation&lt;/strong&gt;: Keep auto-generated code in separate files without merge conflicts or manual edits to generated files.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consistency&lt;/strong&gt;: The &lt;code&gt;partial&lt;/code&gt; keyword now works uniformly across all member types: methods, properties, events, and constructors.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This feature is primarily aimed at source generator authors and scenarios where code is split across generated and hand-written files. If you're not using source generators, you might not need this often, but it's a welcome addition that rounds out the partial member story in C#.&lt;/p&gt;


&lt;h3&gt;
  
  
  Unbound Generic Types in nameof
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;nameof&lt;/code&gt; operator returns the name of a type or member as a string. When used with generic types, it only returns the base name, ignoring type arguments:&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;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;    &lt;span class="c1"&gt;// Returns "List", not "List&amp;lt;int&amp;gt;"&lt;/span&gt;
&lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Also returns "List"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The problem? Before C# 14, you &lt;em&gt;had&lt;/em&gt; to provide type arguments even though they're completely ignored. This forces you to make an arbitrary choice that has no effect on the result.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;C# 14 lets you skip the unnecessary type arguments:&lt;/strong&gt;&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;// Before C# 14 - must provide type arguments (even though they're ignored)&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;);&lt;/span&gt;              &lt;span class="c1"&gt;// "List"&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// "Dictionary"&lt;/span&gt;

&lt;span class="c1"&gt;// C# 14 - use unbound generic types directly&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&amp;gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// "List"&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;name2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;nameof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;,&amp;gt;);&lt;/span&gt; &lt;span class="c1"&gt;// "Dictionary"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Use empty angle brackets, with commas separating multiple type parameters (just like &lt;code&gt;typeof(Dictionary&amp;lt;,&amp;gt;)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This is a minor improvement, but it makes your intent clearer: "I want the name of this generic type, and the type arguments don't matter."&lt;/p&gt;


&lt;h2&gt;
  
  
  .NET 10 New Features
&lt;/h2&gt;
&lt;h3&gt;
  
  
  File-Based Apps
&lt;/h3&gt;

&lt;p&gt;This is one of the most significant changes Microsoft has introduced. Despite being one of the most popular languages, C# has always had one major drawback: adoptability. For a new developer trying out C#, even the simplest "Hello World" console app requires a surprising amount of ceremony. You need a solution (an &lt;code&gt;.sln&lt;/code&gt; file), a project (a &lt;code&gt;.csproj&lt;/code&gt; file), a &lt;code&gt;Program.cs&lt;/code&gt; file with usings, namespaces, a &lt;code&gt;Program&lt;/code&gt; class, all before you even write your first line of code. Nobody enjoys that, even us, .NET developers who are relatively more used to that.&lt;/p&gt;

&lt;p&gt;Compare this to languages like Python, where you can create a single &lt;code&gt;.py&lt;/code&gt; file and immediately run &lt;code&gt;print("Hello World!")&lt;/code&gt;. Microsoft is now pushing C# in that same direction, making it more approachable for beginners. And to be honest, this change isn't just for newcomers. I've been writing .NET for almost eight years now, and I've always missed this simplicity. Sometimes all you want to do is just test a quick snippet without spinning up an entire solution. This update finally makes that possible.&lt;/p&gt;

&lt;p&gt;I've actually written a dedicated article about this change and why it's such a big leap forward. Check out the link below for more details.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/why-i-believe-dotnet-run-appcs-is-a-huge-leap-forward-2emh" class="crayons-story__hidden-navigation-link"&gt;Why I Believe 'dotnet run app.cs' Is a Huge Leap Forward&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2534280" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/why-i-believe-dotnet-run-appcs-is-a-huge-leap-forward-2emh" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;May 27 '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/why-i-believe-dotnet-run-appcs-is-a-huge-leap-forward-2emh" id="article-link-2534280"&gt;
          Why I Believe 'dotnet run app.cs' Is a Huge Leap Forward
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/dotnet"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;dotnet&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/softwareengineering"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;softwareengineering&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/why-i-believe-dotnet-run-appcs-is-a-huge-leap-forward-2emh" 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; reaction&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/why-i-believe-dotnet-run-appcs-is-a-huge-leap-forward-2emh#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              5&lt;span class="hidden s:inline"&gt; 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;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;/div&gt;





&lt;p&gt;Alright, let's give it a try and create our own file-based app. In my repository, I've set up a folder called &lt;code&gt;SingleFileApp&lt;/code&gt;, which contains just one file: &lt;code&gt;HeyThere.cs&lt;/code&gt;. That's literally all you need, no additional files or setup required to run C# code.&lt;/p&gt;

&lt;p&gt;Let's start with a simple line of code that prints a greeting message. Open your command prompt, navigate to the folder containing your file, and run the following:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Quick note: I'm using PowerShell as my CLI. The commands will be similar in other CLIs, but there may be a few subtle differences if you're using Bash or another shell.&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;'Console.WriteLine($"Hey there {args[0]}!");'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;HeyThere.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\HeyThere.cs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Folks"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Or simply:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\HeyThere.cs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Folks"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Yes! You can actually run the file without explicitly using &lt;code&gt;run&lt;/code&gt;. Notice that "Folks" is passed as an argument, this is used by the code to display a customized greeting message.&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.amazonaws.com%2Fuploads%2Farticles%2Fv118skx13xtl1rj7p29y.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.amazonaws.com%2Fuploads%2Farticles%2Fv118skx13xtl1rj7p29y.png" alt="Powershell"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now, what if your app needs external dependencies or packages?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let's make things a bit more interesting: suppose we want to display a calendar below our greeting message. To do this, we'll use the &lt;a href="https://spectreconsole.net/" rel="noopener noreferrer"&gt;Spectre.Console&lt;/a&gt; library.&lt;/p&gt;

&lt;p&gt;If you're familiar with C#, you know that dependencies are typically defined in a &lt;code&gt;.csproj&lt;/code&gt; file. For example, to add a dependency on this library, you would write something like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;ItemGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;PackageReference&lt;/span&gt; &lt;span class="na"&gt;Include=&lt;/span&gt;&lt;span class="s"&gt;"Spectre.Console.Cli"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"0.53.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/ItemGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And the &lt;code&gt;.csproj&lt;/code&gt; file would look like the following:&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.amazonaws.com%2Fuploads%2Farticles%2Fvvtxa4b53dir9w45m86e.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.amazonaws.com%2Fuploads%2Farticles%2Fvvtxa4b53dir9w45m86e.png" alt="csproj file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Except now there's no &lt;code&gt;.csproj&lt;/code&gt; file, because that's the whole point of the file-based app approach. So how do we handle dependencies?&lt;/p&gt;

&lt;p&gt;Well, handling dependencies is quite easy, you just specify the required packages right in the file using the following syntax:&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Spectre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cli&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="m"&gt;0.53&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;#:&lt;/code&gt; directive is officially called an &lt;strong&gt;Ignored Directive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can even specify an SDK the similar way you specify the package, if you need to, for example, in case you need to include the Aspire AppHost SDK:&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt; &lt;span class="n"&gt;Aspire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AppHost&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sdk&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="m"&gt;13.0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;But we don't need the SDK at this moment so let's just focus on the package. Add the following code to the file:&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt; &lt;span class="n"&gt;Spectre&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cli&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="m"&gt;0.53&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;

&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;Spectre.Console&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;calendar&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Calendar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddCalendarEvent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2025&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;HighlightStyle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"blue bold"&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;AnsiConsole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;calendar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Since we don't have to pass any arguments, we can simply run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\HeyThere.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The first time you run it, fetching all dependencies and setting everything up may take a little time. Subsequent runs will be much faster.&lt;/p&gt;

&lt;p&gt;It will display a neat little calendar right in the console.&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.amazonaws.com%2Fuploads%2Farticles%2F7st44ko9enae6j01cf40.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.amazonaws.com%2Fuploads%2Farticles%2F7st44ko9enae6j01cf40.png" alt="Console calendar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can use the ignore directive for more than just packages. &lt;code&gt;.csproj&lt;/code&gt; files contain lots of properties, and the directive can be applied there too.&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt; &lt;span class="n"&gt;TargetFramework&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;net8&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;But what if your app also needs to reference other projects?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You can reference other projects in classic &lt;code&gt;.csproj&lt;/code&gt; setups. If you're hoping for the same capability in file-based apps, you're in luck, it's already supported.&lt;/p&gt;

&lt;p&gt;Imagine this: you have a class library project in your solution and want to reference it from your file-based app. Let's see how we can make that work using our example.&lt;/p&gt;

&lt;p&gt;Let's add a class library containing a single method: &lt;code&gt;string TellMeAJoke();&lt;/code&gt;. It will return a random, perfectly awful "knock, knock" joke.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;classlib&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;KnockKnock&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sln&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\src\KnockKnock\KnockKnock.csproj&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And let's add a new static class where our method will be implemented.&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;class&lt;/span&gt; &lt;span class="nc"&gt;Joke&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;jokes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nLettuce.\nLettuce who?\nLettuce in, it's cold out here!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nCow says.\nCow says who?\nNo, silly—cow says mooooo!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nTank.\nTank who?\nYou're welcome!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nBoo.\nBoo who?\nAw, don’t cry!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nEtch.\nEtch who?\nBless you!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nNana.\nNana who?\nNana your business!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nIce cream.\nIce cream who?\nICE CREAM every time I see a scary movie!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nHarry.\nHarry who?\nHarry up and answer the door!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nInterrupting cow.\nInterrupting cow wh—\nMOOOO!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;"Knock, knock.\nWho’s there?\nWooden shoe.\nWooden shoe who?\nWooden shoe like to hear another joke?"&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;string&lt;/span&gt; &lt;span class="nf"&gt;TellMeAJoke&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rnd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&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;index&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;jokes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;jokes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&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;p&gt;Now, we need to reference that project in our file-based app. Take a look at the screenshot:&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.amazonaws.com%2Fuploads%2Farticles%2Fvygz6ytbbdmv1qap742n.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.amazonaws.com%2Fuploads%2Farticles%2Fvygz6ytbbdmv1qap742n.png" alt="File-based app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now let's run the application to see the output:&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.amazonaws.com%2Fuploads%2Farticles%2Fe4wmy2qvybmzojbi8wyt.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.amazonaws.com%2Fuploads%2Farticles%2Fe4wmy2qvybmzojbi8wyt.png" alt="Output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;You can even build entire web APIs as file-based apps. To do this, you'll need a web SDK, this is exactly where the #:sdk comes into play.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to add the following to enable your file-based app to act like a web API:&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="err"&gt;#&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;sdk&lt;/span&gt; &lt;span class="n"&gt;Microsoft&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NET&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sdk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Web&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once that's set up, you can start exposing your endpoints and handling requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But wait, there's more!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine this scenario: you wrote your code in a single file, and now you want to turn it into a full project. You don't have to do anything manually, there's a handy CLI command that converts it for you. Let's try it:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;project&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;convert&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;\HeyThere.cs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will likely ask you to specify an output folder. Once you do, it will generate a new project there. If you take a look inside, you'll see that it also includes a freshly created &lt;code&gt;.csproj&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;Let's open it in Visual Studio Code and take a closer look:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.cs file:&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2F8nreq2xarrwhujhyoaoz.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.amazonaws.com%2Fuploads%2Farticles%2F8nreq2xarrwhujhyoaoz.png" alt="HeyThere file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.csproj file:&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2Fes58d048so6fyhk1eirx.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.amazonaws.com%2Fuploads%2Farticles%2Fes58d048so6fyhk1eirx.png" alt="csproj file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.sln file&lt;/strong&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.amazonaws.com%2Fuploads%2Farticles%2Fqzt4f45fxhwfeaayxl2r.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.amazonaws.com%2Fuploads%2Farticles%2Fqzt4f45fxhwfeaayxl2r.png" alt="sln file"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it's now a regular .NET project with both &lt;code&gt;.csproj&lt;/code&gt; and &lt;code&gt;.sln&lt;/code&gt; files. The dependencies are no longer listed inside &lt;code&gt;HeyThere.cs&lt;/code&gt;, instead they've been moved into the &lt;code&gt;.csproj&lt;/code&gt; file, just like in a traditional setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you're a beginner and just want to experiment or see how things work, the file-based app approach is a great starting point. However, for medium to large projects, I wouldn't really recommend it, it simply isn't suited for complex scenarios. Trying to manage a full enterprise application in a single &lt;code&gt;.cs&lt;/code&gt; file quickly becomes counterproductive. &lt;code&gt;.sln&lt;/code&gt; and &lt;code&gt;.csproj&lt;/code&gt; files exist for a good reason, so use them to your advantage.&lt;/p&gt;


&lt;h3&gt;
  
  
  Validation in Minimal APIs
&lt;/h3&gt;

&lt;p&gt;.NET has introduced built-in, attribute-based validation for Minimal APIs, addressing one of their biggest pain points. Previously, validation had to be handled manually. While this is not a complete disaster, it was far from ideal and often led to cluttered, harder-to-maintain code.&lt;/p&gt;

&lt;p&gt;Let's try it out ourselves.&lt;/p&gt;

&lt;p&gt;First things first, let's create a new minimal API.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;webapi&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;TheMostMinimalisticApiOnEarth&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now open the project in Visual Studio 2026. You'll notice quite a bit of code generated by the default template. I'll remove anything unnecessary to keep the solution clean and focused, but feel free to keep everything as is if you prefer.&lt;/p&gt;

&lt;p&gt;Once we've removed the unnecessary pieces, add the following endpoint&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.amazonaws.com%2Fuploads%2Farticles%2F89na9ddsgyl35y9sl7xq.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.amazonaws.com%2Fuploads%2Farticles%2F89na9ddsgyl35y9sl7xq.png" alt="Endpoint"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is just a dummy endpoint for testing validations, so nothing fancy is needed. It accepts a username, email, and password in the request and registers the user. Next, we'll add validation to the model. But how do we do that?&lt;/p&gt;

&lt;p&gt;First, let's enable validations by adding the required service:&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;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;AddValidation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now, let's apply validation attributes directly to the record. Yes, you can do that! Let me show you how:&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.amazonaws.com%2Fuploads%2Farticles%2Fbxfixrm76khs3e3k0e60.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.amazonaws.com%2Fuploads%2Farticles%2Fbxfixrm76khs3e3k0e60.png" alt="Validations"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, let's test these properties using Postman:&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.amazonaws.com%2Fuploads%2Farticles%2Fjf2xic8shqodb04jv2b5.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.amazonaws.com%2Fuploads%2Farticles%2Fjf2xic8shqodb04jv2b5.png" alt="Postman"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It works!&lt;/p&gt;

&lt;p&gt;When registering anywhere, you usually need to confirm your password to ensure it matches the original. You could compare passwords manually without validation attributes, but that's not particularly the best practice, this check is part of proper validation.&lt;/p&gt;

&lt;p&gt;Let's add a &lt;code&gt;ConfirmPassword&lt;/code&gt; property and use attributes to make sure it matches the original:&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.amazonaws.com%2Fuploads%2Farticles%2F1cishfm6ffwwoh1huqtv.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.amazonaws.com%2Fuploads%2Farticles%2F1cishfm6ffwwoh1huqtv.png" alt="ConfirmPassword"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Uh-oh, looks like we have a red underline situation. Time to investigate and see what's causing the issue:&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.amazonaws.com%2Fuploads%2Farticles%2Falwi074mvjno7sdb3mft.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.amazonaws.com%2Fuploads%2Farticles%2Falwi074mvjno7sdb3mft.png" alt="Issue Description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, now it makes sense. Let's fix it by using the &lt;code&gt;property:&lt;/code&gt; keyword:&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.amazonaws.com%2Fuploads%2Farticles%2Fngttwil2fx6rkofnh8mw.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.amazonaws.com%2Fuploads%2Farticles%2Fngttwil2fx6rkofnh8mw.png" alt="property: keyword"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The error is gone! Let's test it now. This time, we'll provide both correct values and mismatched passwords to see the validation in action.&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.amazonaws.com%2Fuploads%2Farticles%2F8e05t26q5ye337sf11uq.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.amazonaws.com%2Fuploads%2Farticles%2F8e05t26q5ye337sf11uq.png" alt="Validation in action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, let's enter all the correct values and see the demo end with a successful response:&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.amazonaws.com%2Fuploads%2Farticles%2Fr6xaqe4g3xwnrv0siboc.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.amazonaws.com%2Fuploads%2Farticles%2Fr6xaqe4g3xwnrv0siboc.png" alt="Successful response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important!&lt;/strong&gt; To ensure validations work, your classes or records must be public. If you make them internal, the request will still go through, but the validation won't run.&lt;/p&gt;

&lt;p&gt;To be honest, I'm not entirely sure why this is the case, it's a bit counter-intuitive, but it's a quirk you need to keep in mind when using attribute-based validation in Minimal APIs.&lt;/p&gt;


&lt;h3&gt;
  
  
  MCP for .NET Developers
&lt;/h3&gt;
&lt;h4&gt;
  
  
  What Exactly Is MCP?
&lt;/h4&gt;

&lt;p&gt;If you're not familiar with it, MCP is an open-source standard created by Anthropic for connecting AI applications to external systems. Think of it like this: you're building an app that uses an AI model, and you need that model to interact with external tools or data sources, databases, APIs, services, whatever. You can't just tell an AI model to "go get 'em" because models don’t have native access to external systems, they run in isolated environments for security and safety reasons.&lt;/p&gt;

&lt;p&gt;Instead, you'd have to build your own API layer or integration for each external system. And if you need to connect to several of them, you end up writing a bunch of custom integrations, which quickly becomes tedious and hard to maintain.&lt;/p&gt;

&lt;p&gt;MCP solves this by acting as a universal hub, a standardized protocol for hooking AI systems into external tools. With MCP, developers can build context-aware applications without writing custom integrations for every AI-to-system combination.&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.amazonaws.com%2Fuploads%2Farticles%2Fpmstvbcus02c1zke77yo.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.amazonaws.com%2Fuploads%2Farticles%2Fpmstvbcus02c1zke77yo.png" alt="MCP Diagram"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  MCP in .NET
&lt;/h4&gt;

&lt;p&gt;Microsoft is partnering with Anthropic to develop the official MCP SDK for .NET, with the goal of bringing first-class MCP server support to Microsoft products.&lt;/p&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/modelcontextprotocol/csharp-sdk" rel="noopener noreferrer"&gt;Repository&lt;/a&gt; and &lt;a href="https://modelcontextprotocol.github.io/csharp-sdk/" rel="noopener noreferrer"&gt;docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There's already a project template you can use to create an MCP server yourself. To install the template, run the following command:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Microsoft.Extensions.AI.Templates&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once you run this script, the following templates will be installed:&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.amazonaws.com%2Fuploads%2Farticles%2Fyjmbfeljoin8uli6k08s.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.amazonaws.com%2Fuploads%2Farticles%2Fyjmbfeljoin8uli6k08s.png" alt="Installed templates"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now let's create a new MCP server:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;mcpserver&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;AwesomeMcpServer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Let's open Visual Studio 2026 and take a look at what the template has generated for us:&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.amazonaws.com%2Fuploads%2Farticles%2Fv6bh7jx47m0zafkrudm4.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.amazonaws.com%2Fuploads%2Farticles%2Fv6bh7jx47m0zafkrudm4.png" alt="MCP project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this screenshot, you can also see the contents of the &lt;code&gt;Program.cs&lt;/code&gt; file for the MCP server project. I won't walk through every file and folder in this template, that's a topic for a separate article, but let's open &lt;code&gt;Tools/RandomNumberTools.cs&lt;/code&gt; to see what's inside:&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.amazonaws.com%2Fuploads%2Farticles%2Fh5gbml71j274b79ks40m.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.amazonaws.com%2Fuploads%2Farticles%2Fh5gbml71j274b79ks40m.png" alt="RandomNumberTools"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the default file includes a simple random number generator. It's not something you'd typically use in a real-world scenario, but it serves as a basic demonstration of how MCP works. At this point, you could just as easily connect to an external source, like a database, and feed real contextual data to your agent.&lt;/p&gt;

&lt;p&gt;You know what? Let's use an in-memory storage and save all the unfunny jokes we came up with earlier in this article.&lt;/p&gt;

&lt;p&gt;First let's add a new tool in the Tools folder containing our code:&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.amazonaws.com%2Fuploads%2Farticles%2Fo14gfg2zp7eo83nhi90g.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.amazonaws.com%2Fuploads%2Farticles%2Fo14gfg2zp7eo83nhi90g.png" alt="New Tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And change the &lt;code&gt;Program.cs&lt;/code&gt; file to include this tool instead of the random number generator:&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.amazonaws.com%2Fuploads%2Farticles%2Ft5kwdk0suidyu8zjtxlj.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.amazonaws.com%2Fuploads%2Farticles%2Ft5kwdk0suidyu8zjtxlj.png" alt="Program.cs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's add it to Copilot. Click the Tools button in the bottom-right corner of the Copilot chat, then click the green plus icon:&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.amazonaws.com%2Fuploads%2Farticles%2Fivew83uis0h3c5scncuw.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.amazonaws.com%2Fuploads%2Farticles%2Fivew83uis0h3c5scncuw.png" alt="Copilot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And add the new tool:&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.amazonaws.com%2Fuploads%2Farticles%2Fm0nsn3w8fsvu83g8wy9y.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.amazonaws.com%2Fuploads%2Farticles%2Fm0nsn3w8fsvu83g8wy9y.png" alt="New tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you do that, you'll see your tool listed in the window:&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.amazonaws.com%2Fuploads%2Farticles%2F0lz8b4khkqb385hz9kpf.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.amazonaws.com%2Fuploads%2Farticles%2F0lz8b4khkqb385hz9kpf.png" alt="Tool"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And now, I'm all set to ask my Copilot to generate either all the jokes or just a random one:&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.amazonaws.com%2Fuploads%2Farticles%2Fr716r78mgx66ujliyon9.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.amazonaws.com%2Fuploads%2Farticles%2Fr716r78mgx66ujliyon9.png" alt="Confirm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click 'Confirm':&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.amazonaws.com%2Fuploads%2Farticles%2F0sss14r7kvs7l98bystz.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.amazonaws.com%2Fuploads%2Farticles%2F0sss14r7kvs7l98bystz.png" alt="Confirmed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it outputted all the jokes, well, you can spot three here, but the full list is much longer, and this is just a part of it.&lt;/p&gt;

&lt;p&gt;Now, let's ask Copilot to use the second method and fetch a random joke:&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.amazonaws.com%2Fuploads%2Farticles%2Fb3fdts9xbatw6loxyqbr.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.amazonaws.com%2Fuploads%2Farticles%2Fb3fdts9xbatw6loxyqbr.png" alt="Random joke"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Awesome isn't it?&lt;/p&gt;

&lt;p&gt;This example is just scratching the surface, is a bit silly and simple. MCP can do much more, but as I mentioned, that deserves a separate article.&lt;/p&gt;


&lt;h3&gt;
  
  
  Security Improvements
&lt;/h3&gt;

&lt;p&gt;WebAuthN &amp;amp; Passkey support have been added. Passkeys are essentially cryptographic credentials that replace traditional passwords. They're resistant to phishing, easy to use, and secure by design. Passkeys are built in into the identity framework, though this is actually inspired by an open-source technology: &lt;a href="https://github.com/passwordless-lib/fido2-net-lib" rel="noopener noreferrer"&gt;fido2-net-lib&lt;/a&gt;, which is widely adopted and reliable.&lt;/p&gt;

&lt;p&gt;.NET project templates include passkey support by default. If you have an existing project that uses asp.net identity, you can actually add a passkey support to it, but keep in mind that you'll need a database schema migration.&lt;/p&gt;


&lt;h3&gt;
  
  
  Aspire 13
&lt;/h3&gt;

&lt;p&gt;Support for JavaScript and Python scripts have been added. It's not .NET Aspire anymore, it's Aspire, but it still runs on .NET.&lt;/p&gt;
&lt;h4&gt;
  
  
  Observability &amp;amp; Diagnostics
&lt;/h4&gt;

&lt;p&gt;Now that we've touched Aspire 13 and it's new upgrades, let's not skip one cool feature that can come in handy in quite a few cases. Let's see it by example. I'm going to generate a new Aspire Starter App from the template, check out the screenshot:&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.amazonaws.com%2Fuploads%2Farticles%2F92c303y67oe0onya6gbh.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.amazonaws.com%2Fuploads%2Farticles%2F92c303y67oe0onya6gbh.png" alt="Starter app"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It'll generate a project with a few different projects like AppHost, ApiService, Web, and ServiceDefaults. I won't go that deep to explain what each does in details, because that'll take a whole another artile, but in short, you have a whole stack ready to go with Aspire, which can be deployed directly to Azure for example. Let's run the application and see what's in there for us:&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.amazonaws.com%2Fuploads%2Farticles%2F1d4lduqtlo9ghfgfests.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.amazonaws.com%2Fuploads%2Farticles%2F1d4lduqtlo9ghfgfests.png" alt="App run"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's run the web application and execute a few requests. You can run the application directly from the aspire. Go to the Resources tab and click the URL in the webfrontend column. Now, let's check out the "Metrics" tab:&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.amazonaws.com%2Fuploads%2Farticles%2Fl175626tlvjw6aq9aync.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.amazonaws.com%2Fuploads%2Farticles%2Fl175626tlvjw6aq9aync.png" alt="Metrics tab"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go to the "Weather" tab and also the "Counter" tab and click the "Click Me" button several 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.amazonaws.com%2Fuploads%2Farticles%2F6rdrnzdo832mz5p1u0ba.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.amazonaws.com%2Fuploads%2Farticles%2F6rdrnzdo832mz5p1u0ba.png" alt="Web app view"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's get back to Aspire and see what has changed in the metrics:&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.amazonaws.com%2Fuploads%2Farticles%2Fd6uliw1fr3sj72k8zv35.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.amazonaws.com%2Fuploads%2Farticles%2Fd6uliw1fr3sj72k8zv35.png" alt="Metrics page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a bunch of different metrics right out of the box available for us to observe the performance of the application.&lt;/p&gt;

&lt;p&gt;OK let me show you where all this comes from:&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.amazonaws.com%2Fuploads%2Farticles%2Fgn3bpum21yakfbvmhb7h.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.amazonaws.com%2Fuploads%2Farticles%2Fgn3bpum21yakfbvmhb7h.png" alt="OpenTelemetry"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This actually comes from OpenTelemetry, which is an observability framework. This is a a cross-platform, open standard for collecting and emitting telemetry data.&lt;/p&gt;


&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Microsoft have been doing deep refinements in Jitter, garbage collection.&lt;/p&gt;

&lt;p&gt;.NET 10 executes high level C# with the efficiency of hand-tuned native code.&lt;/p&gt;

&lt;p&gt;.NET 10 uses 93% less memory than .NET 8, which was already very powerful and well-performing LTS version.&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.amazonaws.com%2Fuploads%2Farticles%2Fk8u6rft1qe2e448bn0a1.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.amazonaws.com%2Fuploads%2Farticles%2Fk8u6rft1qe2e448bn0a1.png" alt="Performance"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even if you don't change anything in your code and just update the version, you'll get huge performance gains.&lt;/p&gt;

&lt;p&gt;Improved Kestrel memory pool management. Previously the memory was retained in the pool. In .NET 10, this memory can be returned to the system to use it for other purposes.&lt;/p&gt;

&lt;p&gt;JSON deserialization performance has also improved by utilizing streaming deserialization technique, so JSON can be deserialized in stream instead of doing it all at once.&lt;/p&gt;

&lt;p&gt;There are tons of other performance improvements that definitely deserve their own article. However, a comprehensive article already covers pretty much everything, so there's not much to add here. I'll just link it for you, definitely check out that amazing work!&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-10/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevblogs.microsoft.com%2Fdotnet%2Fwp-content%2Fuploads%2Fsites%2F10%2F2025%2F09%2Fnet10perf.jpg" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-10/" rel="noopener noreferrer" class="c-link"&gt;
            Performance Improvements in .NET 10 - .NET Blog
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdevblogs.microsoft.com%2Fdotnet%2Fwp-content%2Fuploads%2Fsites%2F10%2F2024%2F10%2FMicrosoft-favicon-48x48.jpg"&gt;
          devblogs.microsoft.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;








&lt;h2&gt;
  
  
  Other Changes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Visual Studio 2026
&lt;/h3&gt;

&lt;p&gt;Visual Studio 2026 now uses your system resources more efficiently. The more CPU cores you have, the more tasks it can parallelize.&lt;/p&gt;

&lt;p&gt;Previously, the UI could hang during loading because the UI thread was blocked by ongoing tasks. In this version, those tasks are moved to background threads, keeping the interface responsive and preventing freezes.&lt;/p&gt;

&lt;p&gt;If you're still working with good old WinForms, or have never used it but need to, Visual Studio 2026 has your back! The WinForms Expert Agent helps make the process much less painful. Building or maintaining a WinForms UI can be confusing, especially if you're dealing with a legacy, complex codebase. Think of it like having someone pair-programming with you, handling the tedious stuff so you can focus on the fun parts.&lt;/p&gt;

&lt;p&gt;That's pretty cool, but still, please don't use WinForms for new projects, there are many modern, far superior alternatives, such as .NET MAUI.&lt;/p&gt;




&lt;h3&gt;
  
  
  Github Copilot App Modernization
&lt;/h3&gt;

&lt;p&gt;This feature can be a real lifesaver when upgrading to .NET 10. Not only does it help with the upgrade itself, but it can also deploy your updated application to Azure. Essentially, this assistant will handle the following tasks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upgrade your application to .NET 10&lt;/li&gt;
&lt;li&gt;Fix existing issues and apply best practices&lt;/li&gt;
&lt;li&gt;Take all dependencies into account&lt;/li&gt;
&lt;li&gt;Deploy your application to Azure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep in mind, this is a brand-new feature, so if you decide to fully delegate the upgrade and deployment to it, make sure to review the code and test your application thoroughly. This is especially important if you have many dependencies, a complex codebase, or an application that hasn't been touched in years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to use the feature?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Easy. You can right-click your solution in Visual Studio and you'll see a new menu item. Check out the screenshot below:&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.amazonaws.com%2Fuploads%2Farticles%2Fzsmupnquiwr0oadrb4d9.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.amazonaws.com%2Fuploads%2Farticles%2Fzsmupnquiwr0oadrb4d9.png" alt="Copilot app modernization"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively, you can open the GitHub Copilot Chat window, type &lt;code&gt;@modernize&lt;/code&gt;, and provide instructions on how you want to upgrade your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep in mind:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;There are a few requirements to use this feature:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Your codebase must be written on C#.&lt;/li&gt;
&lt;li&gt;You need to have Visual Studio 2026 or Visual Studio 2022 version 17.14.17 or newer.&lt;/li&gt;
&lt;li&gt;GitHub copilot and GitHub Copilot app modernization for .NET enabled&lt;/li&gt;
&lt;li&gt;Either of these Copilot subscription plans:

&lt;ul&gt;
&lt;li&gt;Copilot Pro&lt;/li&gt;
&lt;li&gt;Copilot Pro+&lt;/li&gt;
&lt;li&gt;Copilot Business&lt;/li&gt;
&lt;li&gt;Copilot Enterprise&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;.NET 10 represents an important moment in the platform's evolution. This isn't just another incremental update, it's a comprehensive reimagining of what a modern application development framework should deliver. With C# 14's powerful language enhancements, dramatic performance improvements, simplified development workflows, and enterprise-grade LTS support, .NET 10 checks every box that matters.&lt;/p&gt;

&lt;p&gt;At the end of the day, .NET gives you the freedom to build just about anything, making this an especially great time to be a .NET developer.&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.amazonaws.com%2Fuploads%2Farticles%2F4mqisukwa363mebzz7rr.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.amazonaws.com%2Fuploads%2Farticles%2F4mqisukwa363mebzz7rr.png" alt=".NET stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ecosystem and community is continuously growing, check out the stats:&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.amazonaws.com%2Fuploads%2Farticles%2Fnovfox2273qqk4zd61ov.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.amazonaws.com%2Fuploads%2Farticles%2Fnovfox2273qqk4zd61ov.png" alt="Stats"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What We Covered
&lt;/h3&gt;

&lt;p&gt;This article explored the most impactful and interesting features from my perspective.&lt;/p&gt;

&lt;p&gt;While this article dives deep into the features I find most compelling, .NET 10 includes many other significant improvements that deserve attention:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Runtime &amp;amp; Performance:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Native AOT compilation enhancements with better size and startup time&lt;/li&gt;
&lt;li&gt;Garbage collector improvements for specific workload patterns&lt;/li&gt;
&lt;li&gt;JIT compilation optimizations for ARM64 and other architectures&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Library Improvements:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;LINQ performance optimizations and new methods&lt;/li&gt;
&lt;li&gt;System.Text.Json serialization enhancements&lt;/li&gt;
&lt;li&gt;Collections improvements and new collection types&lt;/li&gt;
&lt;li&gt;Span and Memory improvements for zero-allocation scenarios&lt;/li&gt;
&lt;li&gt;Regex source generators and performance improvements&lt;/li&gt;
&lt;li&gt;Cryptography API updates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;ASP.NET Core:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazor improvements (rendering modes, streaming rendering, enhanced navigation)&lt;/li&gt;
&lt;li&gt;SignalR performance and reliability improvements&lt;/li&gt;
&lt;li&gt;Middleware pipeline optimizations&lt;/li&gt;
&lt;li&gt;Output caching enhancements&lt;/li&gt;
&lt;li&gt;Rate limiting improvements&lt;/li&gt;
&lt;li&gt;HTTP/3 and QUIC support enhancements&lt;/li&gt;
&lt;li&gt;Minimal API improvements beyond validation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Access:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Entity Framework Core 10 features (complex types, primitive collections, JSON columns enhancements)&lt;/li&gt;
&lt;li&gt;Database provider updates&lt;/li&gt;
&lt;li&gt;Query performance improvements&lt;/li&gt;
&lt;li&gt;Better database migration tooling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;.NET MAUI:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-platform UI improvements&lt;/li&gt;
&lt;li&gt;Performance optimizations for mobile&lt;/li&gt;
&lt;li&gt;New controls and gestures&lt;/li&gt;
&lt;li&gt;Better tooling support&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cloud &amp;amp; Containers:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container image size optimizations&lt;/li&gt;
&lt;li&gt;Better Kubernetes integration&lt;/li&gt;
&lt;li&gt;Azure-specific optimizations&lt;/li&gt;
&lt;li&gt;Improved health checks and metrics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Developer Tools:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SDK improvements&lt;/li&gt;
&lt;li&gt;MSBuild performance enhancements&lt;/li&gt;
&lt;li&gt;NuGet package management improvements&lt;/li&gt;
&lt;li&gt;Testing framework updates&lt;/li&gt;
&lt;li&gt;Debugging experience improvements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Covering all of these in detail would require a book (or several). The features I chose to highlight are the ones I believe will have the most immediate impact on day-to-day development work and demonstrate the direction Microsoft is taking the platform.&lt;/p&gt;




&lt;h3&gt;
  
  
  Migration Recommendations
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;For New Greenfield Projects:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.NET 10 is the obvious choice&lt;/strong&gt;: You get LTS stability (3 years of support) combined with all the latest features, performance improvements, and language enhancements. There's no reason to start a new project on an older version.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Existing .NET 8 Applications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Plan migration before November 2026&lt;/strong&gt;: .NET 8 support ends in November 2026, giving you about a year to plan and execute your migration&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Low-risk upgrade path&lt;/strong&gt;: Moving from one LTS to another LTS is the safest migration strategy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test thoroughly&lt;/strong&gt;: While .NET typically maintains excellent backward compatibility, always run comprehensive tests, especially if you use advanced features or third-party libraries&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Migration strategy&lt;/strong&gt;: Start with non-critical services or applications to gain confidence, then progressively migrate your core systems&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance gains&lt;/strong&gt;: Even without code changes, you'll likely see performance improvements just from the runtime enhancements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Existing .NET 9 Applications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Strongly consider upgrading to .NET 10&lt;/strong&gt;: .NET 9 support ends in November 2026, while .NET 10 extends support until November 2028&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extend support window&lt;/strong&gt;: Upgrading from .NET 9 to .NET 10 gives you 2 additional years of support&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Early adopter advantage&lt;/strong&gt;: If you adopted .NET 9 early, you're already comfortable with recent changes, making the .NET 10 migration straightforward&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Minimal breaking changes&lt;/strong&gt;: The jump from .NET 9 to .NET 10 is smaller than jumping major versions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For .NET 6 and Older Applications:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.NET 6 support already ended&lt;/strong&gt;: If you're still on .NET 6 (support ended November 2024), migration is urgent&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Multi-version jump considerations&lt;/strong&gt;: Migrating from .NET 6 or older requires careful planning due to accumulated breaking changes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use GitHub Copilot App Modernization&lt;/strong&gt;: This tool can help automate much of the upgrade process and identify potential issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Incremental migration&lt;/strong&gt;: You can also consider migrating to .NET 8 first if .NET 10 seems too large a jump, then plan for .NET 10 before .NET 8 support ends, but I wouldn't suggest that, you don't want to do it twice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dependencies audit&lt;/strong&gt;: Check all your NuGet packages and third-party libraries for .NET 10 compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;For Enterprise Systems:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;This is your LTS release—no need to wait&lt;/strong&gt;: .NET 10 combines cutting-edge features with the stability and long-term support enterprises require&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ROI considerations&lt;/strong&gt;: Performance improvements alone can justify the migration through reduced infrastructure costs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Risk mitigation&lt;/strong&gt;: Establish a comprehensive testing strategy including unit tests, integration tests, and performance benchmarks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Training investment&lt;/strong&gt;: Ensure your team is familiar with new C# 14 features and .NET 10 capabilities to maximize the benefits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;General Migration Best Practices:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Audit Dependencies&lt;/strong&gt;: Check all NuGet packages for .NET 10 compatibility. Most popular packages already support .NET 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Run Compatibility Analyzer&lt;/strong&gt;: Use .NET Upgrade Assistant and compatibility analyzers to identify potential issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitor Performance&lt;/strong&gt;: Establish performance baselines before migration to measure improvements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review Breaking Changes&lt;/strong&gt;: Check the official breaking changes documentation for your current version → .NET 10&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plan for C# 14&lt;/strong&gt;: If your team is using new C# 14 features, ensure everyone understands them through code reviews and documentation&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Update CI/CD Pipelines&lt;/strong&gt;: Update build agents and deployment scripts to use .NET 10 SDK&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Container Image Updates&lt;/strong&gt;: Update base images to .NET 10 runtime images&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Final Thoughts
&lt;/h3&gt;

&lt;p&gt;The timing couldn't be better for .NET 10. Organizations currently on .NET 8 LTS have a clear upgrade path to another LTS release with significant improvements. .NET 9 adopters can extend their support window by 2.5 years and gain substantial performance benefits. And teams starting new projects get the best of both worlds: cutting-edge capabilities wrapped in enterprise-grade support commitments.&lt;/p&gt;

&lt;p&gt;.NET 10 isn't just about adding features, it's about refining the entire development experience. From simplifying the getting-started experience with file-based apps to providing enterprise-grade observability and performance, every change feels intentional and well-considered.&lt;/p&gt;

&lt;p&gt;Microsoft has consistently demonstrated their commitment to making .NET the best platform for building modern applications, whether you're creating cloud-native microservices, AI-powered applications, cross-platform mobile apps, or high-performance backend systems. .NET 10 continues this tradition while pushing the boundaries of what's possible with a managed runtime.&lt;/p&gt;

&lt;p&gt;If you've been on the fence about upgrading or adopting .NET, this is your release. The combination of LTS stability, dramatic performance improvements, developer productivity enhancements, and future-forward features like AI integration makes .NET 10 an easy choice for serious application development.&lt;/p&gt;

&lt;p&gt;The .NET platform has never been in a better position. With .NET 10, Microsoft isn't just keeping pace with modern development needs, they're setting the standard for what a world-class application framework should deliver. This is the release that proves .NET isn't just relevant in 2025, it's essential.&lt;/p&gt;




&lt;p&gt;If you found this article helpful, consider checking out the &lt;a href="https://github.com/georgekobaidze/dotnet10-playground" rel="noopener noreferrer"&gt;playground repository&lt;/a&gt; to run these examples yourself. Feel free to share your .NET 10 migration experiences or questions in the comments below. Happy coding!&lt;/p&gt;

&lt;p&gt;Thank you for reading, and happy holidays!❄️☃️🎄🎉&lt;/p&gt;

</description>
      <category>microsoft</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>The Popstar Developer</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Wed, 05 Nov 2025 22:59:05 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/will-developers-survive-ai-takeover-part-4-the-popstar-developer-92b</link>
      <guid>https://forem.com/georgekobaidze/will-developers-survive-ai-takeover-part-4-the-popstar-developer-92b</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Previously in the Series&lt;/li&gt;
&lt;li&gt;Rockstar Developer 🎸&lt;/li&gt;
&lt;li&gt;Popstar Developer 🪩&lt;/li&gt;
&lt;li&gt;What Goes Into Understanding a New Technology&lt;/li&gt;
&lt;li&gt;Same Applies to LLMs and Their Versions&lt;/li&gt;
&lt;li&gt;When Does It Actually Make Sense to Go All In on New Tech?&lt;/li&gt;
&lt;li&gt;Be Extra Cautious When Your Decision Might Affect Others&lt;/li&gt;
&lt;li&gt;Make Sure You Pick Tech for Long-Term Use&lt;/li&gt;
&lt;li&gt;You Don't Have to Pick Sides, Don't Label Yourself&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Previously in the Series
&lt;/h2&gt;

&lt;p&gt;Last time, we dove into what it really means to stay old school in this chaotic, AI-powered era and the pros and cons that come with it. Catch up on the full article here:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g" class="crayons-story__hidden-navigation-link"&gt;What Happens If You Stay Old School in the AI Era?&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2983012" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 1 '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/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g" id="article-link-2983012"&gt;
          What Happens If You Stay Old School in the AI Era?
        &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/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/career"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;career&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/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g" 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;5&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              4&lt;span class="hidden s:inline"&gt; 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;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;




&lt;p&gt;We discovered that being too cool for school and proudly shouting "I'm old-school!" doesn't really do wonders for productivity, it's simply not pragmatic. And we, as software engineers, are supposed to be the most pragmatic people out there. &lt;/p&gt;

&lt;p&gt;To stay relevant, we've got to stay open-minded, ready to explore new ideas, frameworks, and languages. That's how we keep up with the rapid pace of innovation and avoid missing out on opportunities that could completely change our careers (and maybe even our lives).&lt;/p&gt;

&lt;p&gt;However, there's another extreme: the developers who chase every new shiny thing and just can't seem to focus on one thing for long. This post is about them, the &lt;strong&gt;Popstar Developers&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rockstar Developer
&lt;/h2&gt;

&lt;p&gt;As you might've guessed, the term that I've created "Popstar Developer" was inspired by the famous "Rockstar Developer." &lt;/p&gt;

&lt;p&gt;A rockstar developer is basically a software engineer who stands out for exceptional skill, speed, and creativity, basically someone who can tackle tough problems, deliver high-quality code, and often drive major progress within a team. It's like a &lt;strong&gt;10x developer&lt;/strong&gt;, but with more personality. &lt;/p&gt;

&lt;p&gt;Pretty cool, isn't it?&lt;/p&gt;

&lt;h2&gt;
  
  
  Popstar Developer
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;YOU KNOW AT LEAST ONE&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ever met a developer who gets way too excited about some shiny new piece of tech that hasn't even been properly released yet, let alone time-tested?&lt;/p&gt;

&lt;p&gt;Or someone who's following way too many "industry influencers" (with no technical knowledge) on different platforms and sharing their ideas and takes almost blindly without even asking questions? That's who I call a Popstar Developer.&lt;/p&gt;

&lt;p&gt;For the record, “vibe coders” don't fall into this category, because vibe coders simply aren't developers or engineers. &lt;br&gt;
&lt;strong&gt;Change my mind!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Another classic example: developers who instantly jump on social media or record a video the moment a new framework drops, claiming it's "10x faster", "10x more efficient", and "the future of everything..." or, sometimes, dramatically declaring the opposite. And I'm always like: "How did you even have time to research or use it in practice so deeply to be so confident about that?”&lt;/p&gt;

&lt;h2&gt;
  
  
  What Goes Into Understanding a New Technology
&lt;/h2&gt;

&lt;p&gt;A lot actually and no matter how much you test-drive it, real validation only comes with time.&lt;/p&gt;

&lt;p&gt;Let's say some new "X" has just been released. This X can be anything, including but not limited to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A new programming language&lt;/li&gt;
&lt;li&gt;A new framework&lt;/li&gt;
&lt;li&gt;A new LLM model&lt;/li&gt;
&lt;li&gt;A new library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...or even a new version of any of the above.&lt;/p&gt;

&lt;p&gt;Before jumping to conclusions (or straight onto the hype train 🚂), try asking yourself a few essential &lt;strong&gt;“WH”&lt;/strong&gt; questions first:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When was it released?&lt;/li&gt;
&lt;li&gt;What new features does this X bring?&lt;/li&gt;
&lt;li&gt;Who developed it? (Can be a company or an individual)&lt;/li&gt;
&lt;li&gt;What about potential security vulnerabilities?&lt;/li&gt;
&lt;li&gt;What dependencies does it introduce?&lt;/li&gt;
&lt;li&gt;How does it actually perform in real-world metrics?&lt;/li&gt;
&lt;li&gt;What problem is it trying to solve in general?&lt;/li&gt;
&lt;li&gt;What problem can it solve for me specifically?&lt;/li&gt;
&lt;li&gt;What alternatives exist, and how do they compare?&lt;/li&gt;
&lt;li&gt;Why is this tool supposedly better than what I'm using now?&lt;/li&gt;
&lt;li&gt;How can I simulate a realistic, production-level use case?&lt;/li&gt;
&lt;li&gt;Is it backwards-compatible to my current version?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are plenty more questions you could ask, but this is a solid starting point, enough to separate genuine innovation from temporary hype.&lt;/p&gt;

&lt;p&gt;As a professional, your goal is to deliver products that are high-quality, fast, and reliable, not to constantly jump between languages, frameworks, or even versions. In the real world, stability matters.&lt;/p&gt;

&lt;h2&gt;
  
  
  Same Applies to LLMs and Their Versions
&lt;/h2&gt;

&lt;p&gt;The other day, I had to quickly build a visual component for one of my personal projects. I'm a backend engineer, so whenever I need to create complex markup, I sometimes have to rely on a bit of AI assistance (otherwise, it could take me days, if not weeks).&lt;/p&gt;

&lt;p&gt;I won't name the specific LLM I was using, because it's not really about the model itself, it just happened to struggle in this one scenario. There were two different versions available, one newer and supposedly better, at least on paper. I decided to go with the older one.&lt;/p&gt;

&lt;p&gt;Then I ran into a tricky styling issue: making a component responsive and mobile-friendly across different screen sizes. Sounds simple, right? Nope. It turned into a complete nightmare, even for the LLM.&lt;/p&gt;

&lt;p&gt;I went several rounds with this LLM trying to make it work, but nothing clicked. Then it hit me, there was that other, supposedly better version I could've used. So I switched over and fed it all the context I had.&lt;/p&gt;

&lt;p&gt;Sadly, still nothing. The results were no better than before. In the end, I did manage to get a working solution, but only after what felt like an endless back-and-forth with the model.&lt;/p&gt;

&lt;p&gt;The point I want to make is simple: a new version or a new product doesn't inherently mean it's better. In fact, its newness can often be the main reason it comes with hidden drawbacks. Whenever I try anything new, I approach it cautiously — checking security, resource usage, correctness, and everything else that could impact my product negatively.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Does It Actually Make Sense to Go All In on New Tech?
&lt;/h2&gt;

&lt;p&gt;Sometimes, you don't even have a choice, a change is necessary. There are several scenarios where adopting new technology or upgrading a version makes sense:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Your company's tech stack is phasing out the old technology or version.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You need to upgrade because the previous version is no longer supported or is approaching its end-of-support deadline.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You've thoroughly researched the new tech or version and are confident it will improve your application's performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The new version enhances the security of your products.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You plan to add features that aren't supported by the old version.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...and plenty of other valid reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be Extra Cautious When Your Decision Might Affect Others
&lt;/h2&gt;

&lt;p&gt;When you're a one-person team, the impact of a decision mostly affects only you. But if you're a technical manager, architect, principal engineer, engineering manager, or anyone responsible for a team (or multiple teams), you need to be extra thorough when evaluating any new shiny technology you want to introduce.&lt;/p&gt;

&lt;p&gt;In enterprises or even mid-sized companies there's usually a process for adopting new tech, don't take it at face value. Review that process carefully, understand how it works, and look for ways to improve it. That way, you can make informed decisions that benefit your team and other teams, while minimizing risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make Sure You Pick Tech for Long-Term Use
&lt;/h2&gt;

&lt;p&gt;We've already covered several important criteria for deciding whether a new technology or version is worth adopting. But here's one more that often gets overlooked, especially by Popstar Engineers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At some point, things should become boring and routine.&lt;/strong&gt; Sounds counterintuitive, right? But it's true. Constantly switching frameworks, libraries, versions, or dependencies means you're not focusing on the product itself, or on selecting the right components for your project in the first place.&lt;/p&gt;

&lt;p&gt;Even updating a minor version of a library or framework can trigger a cascade of changes in your code. And even if you implement everything correctly, you could still end up with 50+ bugs in production. Fun times, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  You Don't Have to Pick Sides, Don't Label Yourself
&lt;/h2&gt;

&lt;p&gt;This was also covered in the previous article when we discussed why being entirely old-school can be limiting, and it wouldn't feel right to leave it out here.&lt;/p&gt;

&lt;p&gt;For some strange reason, people are obsessed with the idea that they should pick sides in literally everything, which is really strange. It's like they want to label themselves for no reason. I think that's because they want to build a personality they think is cool, one that might be based on someone they know or an imaginary person they're obsessed with becoming. And it's not only in tech. Let me give you a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rock music vs. Pop music - you might be a huge rock fan (just like I am) but you can't convince me that you haven't lip-synced and chair danced to a pop song while being alone, nobody watching (I have). It really depends on a particular song, not the genre.&lt;/li&gt;
&lt;li&gt;Ford vs. Chevy - while I'm a massive Ford fan (and owner), I appreciate quite a few Chevy cars that are out there. They're fun, cool, and do the job. It really depends on a particular model, not the brand.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Now a few examples from tech:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend vs. Frontend - why not both, depending on preferences, what you need currently, what you want to build and tons of other factors?&lt;/li&gt;
&lt;li&gt;Microservices vs. Monolith - how about you tell me what you're building first and then we discuss. Though some people consider a monolith as an anti-pattern. Guess what? Microservices can be an anti-pattern in equally many cases (if not more).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See? The same principle applies here. Which brings us to the final and logical conclusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;You don't become a good software engineer by typing fast, drinking too much coffee, having a flashy editor or terminal theme, driving an electric vehicle, or sharing memes. Those are all just gimmicks.&lt;/p&gt;

&lt;p&gt;Similarly, you don't become a "rockstar" or a "10X" engineer by constantly chasing every new shiny thing that comes out, you simply can't keep up with it all, whether it's a new LLM model, a JavaScript framework, or the latest VS Code release notes. What really matters is creating products, living them, diving deep into technical nuances, and finishing them. You can always update your tech stack or dependencies, but can you actually finish the project? That's the real question.&lt;/p&gt;

&lt;p&gt;What makes a good software engineer is flexibility and adaptability. Religiously following just one approach will only take you so far. To make meaningful progress in a project, or in your career, you need to be adaptive. Not by switching technologies every other day, but by developing situational awareness: knowing when it's better to stick with the tried-and-true, and when it's the right moment to embrace something new.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>career</category>
      <category>discuss</category>
    </item>
    <item>
      <title>What Happens If You Stay Old School in the AI Era?</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Sat, 01 Nov 2025 22:53:48 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g</link>
      <guid>https://forem.com/georgekobaidze/will-developers-survive-ai-takeover-part-3-what-happens-if-you-stay-old-school-4p5g</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AI Hype is Wearing Off Slowly But Surely&lt;/li&gt;
&lt;li&gt;
So Staying Old School Isn't That Bad After All?

&lt;ul&gt;
&lt;li&gt;0 or 1?&lt;/li&gt;
&lt;li&gt;You Don't Have to Pick Sides, Don't Label Yourself&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

What's so Cool in Old-School Anyway?

&lt;ul&gt;
&lt;li&gt;Picking the Right Tool for the Right Job&lt;/li&gt;
&lt;li&gt;Example: Can You Write a Website on C Programming Language?&lt;/li&gt;
&lt;li&gt;Now, Let's Apply That Context to AI&lt;/li&gt;
&lt;li&gt;Don't Be Too Cool for School&lt;/li&gt;
&lt;li&gt;"AI Makes You Dumber, AI Makes Your IQ Lower, AI This... AI That..."&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

When Does It Make Sense to Go Old-School?

&lt;ul&gt;
&lt;li&gt;There's Still No Excuse&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Summary and What's Next&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  AI Hype is Wearing Off Slowly But Surely
&lt;/h2&gt;

&lt;p&gt;AI is here to stay, it's not going anywhere despite videos and articles claiming its bubble will pop. While there's some truth to these concerns, most such titles are clickbait. Sure, people are realizing that AI won't solve all their problems or make them rich without effort, but let's not be too dramatic - AI is going to stay like it is now for the most part. Though, it's encouraging to see both software engineers and non-technical people recognize that "vibe coding" isn't something to trust your business and career on - it's a slippery slope.&lt;/p&gt;

&lt;p&gt;Check out my article about vibe coding:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__hidden-navigation-link"&gt;I'm All In on AI, But We Need to Talk About Vibe Coding&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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F55651%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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-2619292" 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%2F29e2a161-9d78-410b-a6e5-9aca17092fa3.jpeg" 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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jun 24 '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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" id="article-link-2619292"&gt;
          I'm All In on AI, But We Need to Talk About Vibe Coding
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&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/vibecoding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;vibecoding&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/machinelearning"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;machinelearning&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/coding"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;coding&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/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p" 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;126&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/georgekobaidze/im-all-in-on-ai-but-we-need-to-talk-about-vibe-coding-the-new-slippery-slope-2k6p#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              64&lt;span class="hidden s:inline"&gt; 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;
            16 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;But hey, let's be honest, if you're experienced enough in this field, you've seen this pattern before - it's the natural cycle of any hyped technology. Everything that gets hot eventually cools down, just like this race car brake rotor does after the race, and AI is no exception.&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.amazonaws.com%2Fuploads%2Farticles%2Fakb4kafwpnwhnj35ka9t.gif" 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.amazonaws.com%2Fuploads%2Farticles%2Fakb4kafwpnwhnj35ka9t.gif" alt="Racing Brakes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's a visual representation of how hype works for any new hot thing in tech.&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.amazonaws.com%2Fuploads%2Farticles%2F3rdxnzbgzv6vvho2bij6.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.amazonaws.com%2Fuploads%2Farticles%2F3rdxnzbgzv6vvho2bij6.png" alt="Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;We'll talk more about the AI bubble later in this series.&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So Staying Old School Isn't That Bad After All?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  0 or 1?
&lt;/h3&gt;

&lt;p&gt;Our field is completely built upon the idea of 0 and 1, but pretty much anything built on top of that concept involves one magic phrase - &lt;strong&gt;"it depends."&lt;/strong&gt; The higher the abstraction, the more "it depends" answers we encounter when discussing any topic, and AI is no exception. In fact, AI is the topic with the highest share of "it depends" right now.&lt;/p&gt;

&lt;p&gt;However, you're not wasting your time reading my article only to end up with me saying "it depends," right? So let's dive into this topic and find out what exactly it depends on.&lt;/p&gt;

&lt;h3&gt;
  
  
  You Don't Have to Pick Sides, Don't Label Yourself
&lt;/h3&gt;

&lt;p&gt;For some strange reason, people are obsessed with the idea that they should pick sides in literally everything, which is really strange. It's like they want to label themselves for no reason. I think that's because they want to build a personality they think is cool, one that might be based on someone they know or an imaginary person they're obsessed with becoming. And it's not only in tech. Let me give you a few examples:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rock music vs. Pop music - you might be a huge rock fan (just like I am) but you can't convince me that you haven't lip-synced and chair danced to a pop song while being alone, nobody watching (I have). It really depends on a particular song, not the genre.&lt;/li&gt;
&lt;li&gt;Ford vs. Chevy - while I'm a massive Ford fan (and owner), I appreciate quite a few Chevy cars that are out there. They're fun, cool, and do the job. It really depends on a particular model, not the brand.&lt;/li&gt;
&lt;li&gt;Pizza vs. Burger - now that's a tough one for me, I still don't know. Again, it depends on about 150 different factors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Now a few examples from tech:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backend vs. Frontend - why not both, depending on preferences, what you need currently, what you want to build and tons of other factors?&lt;/li&gt;
&lt;li&gt;Microservices vs. Monolith - how about you tell me what you're building first and then we discuss. Though some people consider a monolith as an anti-pattern. Guess what? Microservices can be an anti-pattern in equally many cases (if not more).&lt;/li&gt;
&lt;li&gt;Old school coding vs. modern coding - this one's quite vague and general, so let's discuss it in a more detailed way.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important: as the title suggests, this article is going to focus only on old-school. In the next article we'll talk about the modern approach. To make the comparison fair, the next article will also have a similar structure.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's so Cool in Old-School Anyway?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Picking the Right Tool for the Right Job
&lt;/h3&gt;

&lt;p&gt;The main appeal that old-school has is that when a person claims they're old-school, it's a social convention that this person is inherently cool, no matter the context, because they seem like someone who's been around for quite some time and is knowledgeable enough not to care about new trends and technologies... &lt;strong&gt;and that's a mindset issue&lt;/strong&gt;, well at least in software engineering. &lt;/p&gt;

&lt;p&gt;I think it goes without saying that as a software engineer, you should always be trying to improve your skills and effectively the products you make. You can't just pick any technology, framework, library, or language and create a product that will be efficient, maintainable, and performant at the same time. One of the best skills you can have as a software engineer is picking the right tool for the right job, and make no mistake, &lt;strong&gt;this skill is one of the hardest skills you can obtain, even though it sounds pretty straightforward, it's not.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Can You Write a Website on C Programming Language?
&lt;/h3&gt;

&lt;p&gt;Absolutely. You can... technically.&lt;/p&gt;

&lt;p&gt;However&lt;/p&gt;

&lt;p&gt;While it's entirely possible to develop a web server or even a complete website backend using the C programming language, it's generally not the most practical approach for modern web development. C provides very low-level control over networking, memory management, and I/O operations, which means a developer can, in theory, implement every layer of the HTTP stack manually, from parsing requests and generating responses to handling sockets and concurrency. However, this level of control comes at a significant cost in terms of development speed, security, and maintainability.&lt;/p&gt;

&lt;p&gt;Modern frameworks and languages such as Go, Rust, Node.js, Python (Flask, Django), or .NET abstract away most of the boilerplate network handling and offer robust standard libraries, concurrency models, and built-in HTTP servers. In contrast, writing a web server in C typically involves directly managing sockets via the Berkeley sockets API, implementing the HTTP protocol manually (including headers, content length, and encoding), and ensuring thread safety and memory correctness - tasks that are both error-prone and time-consuming.&lt;/p&gt;

&lt;p&gt;C-based web servers can be extremely efficient in performance-critical, embedded, or specialized environments (for instance, using libraries like Mongoose, libmicrohttpd, or CivetWeb), but for general-purpose website development, higher-level languages and frameworks deliver far better productivity and maintainability without sacrificing reliability. And to be honest, you don't lose that much in terms of speed and performance as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Now, Let's Apply That Context to AI
&lt;/h3&gt;

&lt;p&gt;As much as we love our job—software engineering—it can be extremely stressful. It's incredibly competitive and doesn't forgive standing still.&lt;/p&gt;

&lt;p&gt;Software engineers are pretty much like professional athletes: we need to work to survive and, at the same time, constantly improve our general skills outside work to make sure we're in a good position in a global perspective. &lt;/p&gt;

&lt;p&gt;Well, there are a few key differences though: if we tear our ACLs or injure our Achilles, we can still work. However professional athletes, unlike us, don't have to learn completely new things over and over again, they mostly drill what they already know and deepen their skill and understanding in that regard. Us, the software engineers? We have to do both. We need to constantly learn new things, and that includes AI.&lt;/p&gt;

&lt;p&gt;As we already mentioned, our industry is extremely competitive, not only at the individual engineer level, but also at the company level too (even more so). That's why companies are so desperate to find as good engineers as possible. Have you checked out the recent news about big tech giants literally poaching AI engineers and researchers from each other? Crazy right? I guarantee you that none of those engineers have ever complained that AI is taking their jobs and it's evil. Instead they used the situation for their benefit and it worked out pretty well for them, hasn't it?&lt;/p&gt;

&lt;h3&gt;
  
  
  Don't Be Too Cool for School
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;"So you're tellin' me that tin Lizzie of yours is better than my Quarter Horse? Ha! You've lost your senses, boy." 🤠 &lt;/p&gt;
&lt;/blockquote&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.amazonaws.com%2Fuploads%2Farticles%2F2t52qjz8my8zmsvivje8.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.amazonaws.com%2Fuploads%2Farticles%2F2t52qjz8my8zmsvivje8.png" alt="Model T and a Horse"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm 100% (a hundred percent) sure this conversation happened much more than once way back in the beginning of the 1900s when Henry Ford produced a brand new &lt;strong&gt;Model T&lt;/strong&gt; and popularized it. Look at the world now. Now horses are transported using a special trailer towed by Ford F-150s. Fair play, horses!👏&lt;/p&gt;

&lt;p&gt;The point I want to make is, don't be that person who's always trying to gain validation from society by parroting popular ideas, that's easy and cheap. Try to think about stuff yourself. Out-of-the-box thinking isn't only thinking of a business or AI startup idea that nobody even cares about, or saying something controversial that you don't even believe. &lt;/p&gt;

&lt;p&gt;Out-of-the-box thinking can be subtle, not even comprehensible for other people. As subtle as decluttering your mind from other people's perspectives and thinking about something by yourself. Tech and software engineering isn't about how things work, or how people think things work, it's all about how you make things work your way to create something special or solve a specific issue. While everyone else is just complaining about tech going backwards and AI ruining everything, the best thing you can do is sit down and brainstorm how you can use the whole AI situation to make your career even better.&lt;/p&gt;

&lt;h4&gt;
  
  
  Do Me a Favor and Once You've Read This Article Do the Following:
&lt;/h4&gt;

&lt;p&gt;Take a notebook and a pen and write down the following questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What are the most repetitive tasks that I can delegate to AI?&lt;/li&gt;
&lt;li&gt;How can I use AI tools to make my personal repositories cleaner and more efficient?&lt;/li&gt;
&lt;li&gt;What are the ways to communicate with AI to make sure my development skills aren't getting rusty?&lt;/li&gt;
&lt;li&gt;What skills am I lacking and how can I sharpen them using AI tools?&lt;/li&gt;
&lt;li&gt;How to decide when I use an AI-assisting or AI-assisted approach?&lt;/li&gt;
&lt;li&gt;Which AI tools should I use?&lt;/li&gt;
&lt;li&gt;Should I limit myself on how much I use AI during coding?&lt;/li&gt;
&lt;li&gt;In what ways can I validate that I actually understand the code AI generates for me?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You don't have to answer all these questions right away, just write them down and think about them. Let off the LinkedIn influencers and YouTube clickbaiters for some time, because more often than not, they either don't fully understand how the industry really works (which is normal because some of them aren't even technical people) or they're just throwing hot takes or popular takes into the public so they can get hundreds of likes/comments. Make your own path with your own mind.&lt;/p&gt;

&lt;h3&gt;
  
  
  "AI Makes You Dumber, AI Makes Your IQ Lower, AI This... AI That..."
&lt;/h3&gt;

&lt;p&gt;I see tons of posts, articles, and videos with a title like this. And I'm not a big fan of it. Not that I'm an AI power-user and I'm taking it personally, but because it's nothing but a "wanna be smart and cool" statement that's totally out of context and something that's easy to get many people nodding at you and liking your comment/post. &lt;/p&gt;

&lt;p&gt;In reality, it's not AI that'll make you dumber, it's you and how you use AI. It's like saying that automatic gearbox cars cause more accidents because people have more ability and freedom to use phones while driving. It's not the cars, it's the irresponsible and bad drivers who don't have the first idea how to drive a car safely.&lt;/p&gt;

&lt;p&gt;Any tool out there is there standing still waiting for your input and does stuff based on it. So if you think that AI is making you dumber and that's why being old school is the way to go, please pause for a moment and think and reflect about what's the actual reason why that happens. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maybe you're doing something wrong? &lt;/li&gt;
&lt;li&gt;Maybe you're delegating way too much to AI? &lt;/li&gt;
&lt;li&gt;Maybe you should stop vibe coding? &lt;/li&gt;
&lt;li&gt;Maybe before you ask ChatGPT to generate an email for you, you should try it? &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are so many maybes that you should think about before discouraging others from using a tool that can absolutely be used productively.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Does It Make Sense to Go Old-School?
&lt;/h2&gt;

&lt;p&gt;Even though staying up-to-date is what every developer should focus on, in some specific scenarios, it's better to stay old-school.&lt;/p&gt;

&lt;p&gt;When I think about this topic, what comes to my mind is the tweet I came across on Reddit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A friend learned COBOL and received a codebase 
where the last change was done in the 90s... 
by. his. mum.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There's an extremely good reason why that code was so old and why that person had to maintain code that was maintained by his mum. You might not even have heard of COBOL, especially if you're a gen-z software engineer. It's a programming language that is still used, even though it's over 60 years old. Not only that, plenty of unbelievably critical systems run on COBOL, like: banking systems, insurance systems, government, transportation, you name it. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;When you have a working system for several decades, THE VERY LAST THING you ever want is going modern.&lt;/strong&gt; Just stop for a moment and imagine rewriting these systems written in COBOL in modern alternatives. It's a terrible idea, right? I've actually had a discussion about this topic with a few people and some of them were even advocating that point because "it's a good investment in the long term." But in reality, it's not. It's a good investment when the update isn't that hugely significant AND you gain something out of it. Don't be just a purist who thinks only about modern technologies and the cleanest code possible—think about what you're going to bring to the table for the client. And let me tell you that if anyone touches that COBOL code written and developed for decades by the people who are retired now (at least most of them), you're not going bring nothing but bugs and tons of issues to the table. Doesn't matter how good you are, or how good your team is, you're going to cause a catastrophe. &lt;/p&gt;

&lt;p&gt;Imagine messing up the whole financial system in the USA. That will not only affect the country, but the whole rest of the world, because every other country is at least indirectly dependent on the USA's economy. And even if everything goes perfectly and there are no issues, there's still no point in doing this modernization work, because it's going to cost so much, there's literally no value whatsoever, quite the contrary.&lt;/p&gt;

&lt;p&gt;Whether you can use AI to maintain your super-legacy code, that's questionable, but if you're a COBOL developer and you're planning on using AI for maintaining your systems, please do a thorough review before you update the code.&lt;/p&gt;

&lt;p&gt;This is a perfect example when it's better to stay old-school and don't try to do crazy stuff with the system.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another example can be Real-Time and Embedded Systems.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Embedded systems are specialized computers built into devices rather than general-purpose machines. Examples include microcontrollers (Arduino, STM32, ESP32), device drivers (GPUs, sensors, storage), aerospace flight control software, and medical devices (pacemakers, insulin pumps, MRI machines). These systems often have hard real-time requirements, meaning they must respond to events within strict timing constraints, missing a timing window can cause system failure or even be life-threatening.&lt;/p&gt;

&lt;p&gt;Why Assembly / Embedded C Works:&lt;/p&gt;

&lt;p&gt;Maximum control: Direct access to hardware registers, precise memory management, and deterministic instruction execution.&lt;/p&gt;

&lt;p&gt;Predictable timing: No garbage collection or dynamic allocation, ensuring interrupts and timers fire exactly on schedule.&lt;/p&gt;

&lt;p&gt;Minimal overhead: Small, efficient machine code suitable for devices with limited RAM, flash, or slow CPUs.&lt;/p&gt;

&lt;p&gt;Hardware-specific features: Bit-level operations, DMA control, and inline assembly allow precise control impossible in high-level languages.&lt;/p&gt;

&lt;p&gt;This is another case where caution is crucial, especially when dealing with older systems dedicated to critical functions. For example:&lt;/p&gt;

&lt;p&gt;Flight control software: Airbus, Boeing... these systems cannot risk unexpected pauses.&lt;/p&gt;

&lt;p&gt;Medical devices: Pacemakers, infusion pumps—any failure can be life-threatening.&lt;/p&gt;

&lt;p&gt;With systems like these, you simply don’t take risks, because the consequences can be far more catastrophic than financial loss.&lt;/p&gt;

&lt;h3&gt;
  
  
  There's Still No Excuse
&lt;/h3&gt;

&lt;p&gt;We've identified a few examples when it's better to stick to your current tech and not upgrade it, no matter how appealing it might sound. Remember, we software engineers are here to solve problems, not to create them. Some legacy systems are legacy for a good reason—they just work and they're time-tested, quite a lot. In these cases, find something else to test your adaptability skills and learn new languages and frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary and What's Next
&lt;/h2&gt;

&lt;p&gt;Being old school is useful when it comes to critical scenarios like this and it's mainly about technology and infrastructure, but your mindset should never be only old-school, you need to also look forward and try to stay up-to-date. There's still no excuse for being old-school when it comes to your mindset. Stay hungry, stay competitive, stay awesome!&lt;/p&gt;

&lt;p&gt;The next chapter will be a complete opposite of this one, we'll talk about the pros and cons of being too obsessed with being up-to-date.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>machinelearning</category>
      <category>discuss</category>
      <category>career</category>
    </item>
    <item>
      <title>How a Simple Race Condition Bug Can Take Down Even the Biggest Systems</title>
      <dc:creator>Giorgi Kobaidze</dc:creator>
      <pubDate>Tue, 28 Oct 2025 19:34:51 +0000</pubDate>
      <link>https://forem.com/georgekobaidze/how-a-simple-race-condition-can-take-down-even-the-biggest-systems-16l0</link>
      <guid>https://forem.com/georgekobaidze/how-a-simple-race-condition-can-take-down-even-the-biggest-systems-16l0</guid>
      <description>&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What is a Race Condition?&lt;/li&gt;
&lt;li&gt;The Scenario: A DNS Management System&lt;/li&gt;
&lt;li&gt;The Race Condition: A Perfect Storm&lt;/li&gt;
&lt;li&gt;Visualizing the Race Condition&lt;/li&gt;
&lt;li&gt;The Core Bug Pattern&lt;/li&gt;
&lt;li&gt;Why This Bug is So Insidious&lt;/li&gt;
&lt;li&gt;How to Fix It: Proper Cleanup Logic&lt;/li&gt;
&lt;li&gt;Advanced Prevention: Fencing Tokens&lt;/li&gt;
&lt;li&gt;Lessons for Distributed Systems Engineers&lt;/li&gt;
&lt;li&gt;Real-World Applications&lt;/li&gt;
&lt;li&gt;The Broader Context: Why This Matters&lt;/li&gt;
&lt;li&gt;Practical Checklist for Your Systems&lt;/li&gt;
&lt;li&gt;Conclusion: The Humbling Reality of Distributed Systems&lt;/li&gt;
&lt;li&gt;Summary&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;Imagine this scenario: Your production system has been running flawlessly for years. You have redundancy, automated recovery, and multiple independent components working in harmony. Then one day, under a perfect storm of conditions, everything crashes. Not because of a hardware failure, not because of malicious actors, but because of a tiny race condition that only manifests when several unlikely events happen simultaneously.&lt;/p&gt;

&lt;p&gt;This isn't hypothetical. This exact pattern has caused major outages in global production systems, bringing down critical infrastructure and affecting millions of users. The culprit? A subtle timing bug in automation software that, under specific conditions, deletes resources that are actively being used.&lt;/p&gt;

&lt;p&gt;In this article, we'll explore one of the most insidious types of race conditions in distributed systems: the "cleanup catastrophe." We'll break down exactly how it works, why it's so hard to catch, and most importantly, how to prevent it in your own systems.&lt;/p&gt;

&lt;p&gt;Whether you're building microservices, distributed databases, or cloud infrastructure, understanding this pattern will help you avoid a category of bugs that can remain dormant for years before striking catastrophically.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Race Condition?
&lt;/h2&gt;

&lt;p&gt;Before diving into the complex scenario, let's establish the basics.&lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;race condition&lt;/strong&gt; occurs when the behavior of a system depends on the sequence or timing of uncontrollable events. In software, this typically happens when multiple processes or threads access shared resources without proper coordination.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple Example: The Bank Account Problem
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Two threads trying to update the same account
&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;

&lt;span class="c1"&gt;# Thread 1: Deposit $100
&lt;/span&gt;&lt;span class="n"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;  &lt;span class="c1"&gt;# Reads 1000
&lt;/span&gt;&lt;span class="n"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;  &lt;span class="c1"&gt;# Calculates 1100
&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp1&lt;/span&gt;  &lt;span class="c1"&gt;# Writes 1100
&lt;/span&gt;
&lt;span class="c1"&gt;# Thread 2: Withdraw $50 (happens at the same time)
&lt;/span&gt;&lt;span class="n"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;balance&lt;/span&gt;  &lt;span class="c1"&gt;# Reads 1000 (before Thread 1 writes!)
&lt;/span&gt;&lt;span class="n"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;  &lt;span class="c1"&gt;# Calculates 950
&lt;/span&gt;&lt;span class="n"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp2&lt;/span&gt;  &lt;span class="c1"&gt;# Writes 950
&lt;/span&gt;
&lt;span class="c1"&gt;# Final balance: $950
# Expected balance: $1050
# Lost: $100
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is a classic race condition. Both threads read the balance before either writes, so one update gets lost.&lt;/p&gt;

&lt;p&gt;But the race condition we're exploring today is more subtle and more dangerous.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scenario: A DNS Management System
&lt;/h2&gt;

&lt;p&gt;Let's examine a realistic distributed system that manages DNS records for a high-availability service. This pattern applies to many systems: configuration management, cache invalidation, distributed task scheduling, and more.&lt;/p&gt;

&lt;h3&gt;
  
  
  System Architecture
&lt;/h3&gt;

&lt;p&gt;Our system has three key components designed for reliability and automation:&lt;/p&gt;

&lt;h4&gt;
  
  
  1. The Planner
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Monitors infrastructure health (load balancers, servers, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function&lt;/strong&gt;: Generates configuration "plans" based on current state&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output&lt;/strong&gt;: Versioned plans (Plan 1, Plan 2, Plan 3, etc.) specifying which IP addresses should be active&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating Model&lt;/strong&gt;: Continuously running, generating new plans as infrastructure changes&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  2. The Enactors (3 instances)
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Apply configuration plans to the production DNS system&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function&lt;/strong&gt;: Execute the actual DNS record updates based on plans from the Planner&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redundancy&lt;/strong&gt;: Three separate instances running independently for fault tolerance&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Operating Model&lt;/strong&gt;: Pick up plans, validate them, apply changes to DNS&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  3. The Cleanup Process
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose&lt;/strong&gt;: Remove obsolete and "stale" plans to prevent confusion&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Function&lt;/strong&gt;: Identifies plans that are no longer needed and deletes their associated resources&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic&lt;/strong&gt;: If a plan's generation time is older than the most recently completed plan, mark it as stale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assumption&lt;/strong&gt;: Plans complete quickly, so generation time ≈ completion time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture looks solid. Redundant Enactors provide fault tolerance. Continuous planning adapts to infrastructure changes. Cleanup keeps the system tidy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But this design has a fatal flaw.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Race Condition: A Perfect Storm
&lt;/h2&gt;

&lt;p&gt;The race condition occurs when several things go wrong simultaneously, creating a timing window that the system's designers didn't anticipate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: The Slowdown (Time T1)
&lt;/h3&gt;

&lt;p&gt;Enactor #1 begins processing Plan A at time T1. Under normal circumstances, this takes a few seconds. But something unusual happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Network congestion delays communication with DNS servers&lt;/li&gt;
&lt;li&gt;Resource contention on the Enactor instance slows processing&lt;/li&gt;
&lt;li&gt;Temporary throttling from the DNS API causes retries&lt;/li&gt;
&lt;li&gt;A software bug triggers unexpected retry logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whatever the cause, Enactor #1 is stuck processing Plan A far longer than expected.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1: Enactor #1 starts applying Plan A (generated at T1)
    └─&amp;gt; Expected completion: T1 + 5 seconds
    └─&amp;gt; Actual completion: T1 + 5 minutes (unusually slow!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: The World Keeps Turning (Time T2-T3)
&lt;/h3&gt;

&lt;p&gt;While Enactor #1 struggles, the Planner doesn't know about the delay. It continues its job:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At T2: Generates Plan B based on updated infrastructure state&lt;/li&gt;
&lt;li&gt;At T3: Generates Plan C with even newer information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Planner assumes eventual consistency will work everything out. After all, that's what it was designed for.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1: Enactor #1 starts applying Plan A (still in progress...)
T2: Planner generates Plan B
T3: Planner generates Plan C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: The Speedster (Time T4-T5)
&lt;/h3&gt;

&lt;p&gt;Enactor #2, operating independently and unaware of Enactor #1's troubles, picks up the newer plans:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At T4: Quickly processes and applies Plan B (completes in 5 seconds)&lt;/li&gt;
&lt;li&gt;At T5: Quickly processes and applies Plan C (completes in 5 seconds)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enactor #2 is doing exactly what it was designed to do—applying the latest configuration as fast as possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1: Enactor #1 starts applying Plan A (still in progress...)
T2: Planner generates Plan B
T3: Planner generates Plan C
T4: Enactor #2 applies Plan B (completes quickly)
T5: Enactor #2 applies Plan C (completes quickly)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: The Cleanup Catastrophe (Time T5)
&lt;/h3&gt;

&lt;p&gt;Here's where everything falls apart. After completing Plan C, Enactor #2 (or the cleanup process) examines the system state:&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="c1"&gt;# Cleanup logic at time T5
&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;T5&lt;/span&gt;
&lt;span class="n"&gt;most_recent_completed_plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Plan_C&lt;/span&gt;  &lt;span class="c1"&gt;# Generation time: T3
&lt;/span&gt;&lt;span class="n"&gt;active_plans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Plan_A&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Plan_C&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# The fatal logic
&lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;active_plans&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;most_recent_completed_plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Plan A was generated at T1, which is &amp;lt; T3
&lt;/span&gt;        &lt;span class="c1"&gt;# Conclusion: Plan A is "stale" and "obsolete"
&lt;/span&gt;        &lt;span class="nf"&gt;delete_plan_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# This deletes ALL IP addresses associated with Plan A
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cleanup logic sees:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plan A was generated at T1 (old)&lt;/li&gt;
&lt;li&gt;Plan C was generated at T3 and completed at T5 (new)&lt;/li&gt;
&lt;li&gt;Conclusion: Plan A is stale and should be deleted&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The fatal assumption:&lt;/strong&gt; The cleanup assumes that if a plan is "old" by generation time, it isn't being actively used. But Enactor #1 is &lt;em&gt;still applying Plan A&lt;/em&gt; at T5!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1: Enactor #1 starts applying Plan A (STILL in progress at T5!)
T2: Planner generates Plan B
T3: Planner generates Plan C
T4: Enactor #2 applies Plan B (completes)
T5: Enactor #2 applies Plan C (completes)
    └─&amp;gt; Cleanup runs: "Plan A is old, delete it!"
    └─&amp;gt; Deletes Plan A's resources (IP addresses, DNS records)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: The Collision (Time T6)
&lt;/h3&gt;

&lt;p&gt;At T6, Enactor #1 finally completes its delayed processing of Plan A. But there's a catastrophic problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plan A's resources (IP addresses, DNS records) were just deleted at T5&lt;/li&gt;
&lt;li&gt;Enactor #1 tries to finalize Plan A with non-existent resources&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Result: Empty DNS record or corrupted configuration&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;T1: Enactor #1 starts applying Plan A
T5: Cleanup deletes Plan A's resources
T6: Enactor #1 finishes applying Plan A
    └─&amp;gt; ERROR: Resources don't exist!
    └─&amp;gt; Result: Empty/corrupted DNS state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: The Inconsistent State
&lt;/h3&gt;

&lt;p&gt;The system now has:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No valid IP addresses in the DNS record (or a corrupted configuration)&lt;/li&gt;
&lt;li&gt;Metadata indicating multiple plans in various states of completion&lt;/li&gt;
&lt;li&gt;An inconsistent state that prevents automated recovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Enactors can't fix this automatically because their logic assumes they can always start from a known good state. But there is no good state—the ground truth has been deleted.&lt;/p&gt;

&lt;h2&gt;
  
  
  Visualizing the Race Condition
&lt;/h2&gt;

&lt;p&gt;Here's a visual representation of the timing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Time →  T1      T2      T3      T4      T5      T6
        |       |       |       |       |       |
Plan A: [================================●]     ← Slow (Enactor #1)
                                         ↑      ↑
Plan B:         [====●]                  |      |
                                         |      |
Plan C:                 [====●]          |      |
                                         |      |
Cleanup:                        [Deletes A]     |
                                                |
Collision:                              [Enactor #1 finishes]
                                         [Resources gone!]

Legend:
[===] = Plan being applied
●     = Plan completed
↑     = Critical event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Cleanup deletes Plan A's resources at T5, while Enactor #1 is still using them, completing at T6.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Bug Pattern
&lt;/h2&gt;

&lt;p&gt;Here's the essential code pattern that causes this race condition:&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="c1"&gt;# BUGGY: The Dangerous Cleanup Logic
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cleanup_old_plans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plans&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_recent_completed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plans&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;most_recent_completed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# BUG: Doesn't check if plan is currently being applied!
&lt;/span&gt;            &lt;span class="nf"&gt;delete_plan_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="c1"&gt;# This can delete resources that are actively in use
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this is dangerous:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It assumes generation time correlates with application status&lt;/li&gt;
&lt;li&gt;It doesn't check if a plan is currently being applied&lt;/li&gt;
&lt;li&gt;It doesn't verify when the plan was last accessed&lt;/li&gt;
&lt;li&gt;It has no safety buffer or grace period&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Why This Bug is So Insidious
&lt;/h2&gt;

&lt;p&gt;This race condition is particularly dangerous because:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. It Works 99.99% of the Time
&lt;/h3&gt;

&lt;p&gt;Under normal conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Plans complete in seconds&lt;/li&gt;
&lt;li&gt;Generation time ≈ Completion time&lt;/li&gt;
&lt;li&gt;Cleanup never deletes in-use resources&lt;/li&gt;
&lt;li&gt;The system appears perfectly reliable&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. It's Invisible in Testing
&lt;/h3&gt;

&lt;p&gt;To trigger this bug, you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unusual delays in one Enactor (hard to reproduce)&lt;/li&gt;
&lt;li&gt;Continued plan generation during the delay (timing-dependent)&lt;/li&gt;
&lt;li&gt;Another Enactor completing plans quickly (normal behavior)&lt;/li&gt;
&lt;li&gt;Cleanup running at exactly the wrong moment (probabilistic)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Standard tests won't catch this. Even stress tests might miss it.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. It Fails Catastrophically
&lt;/h3&gt;

&lt;p&gt;When this bug triggers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't cause a partial failure&lt;/li&gt;
&lt;li&gt;It doesn't throw an obvious error&lt;/li&gt;
&lt;li&gt;It creates an inconsistent state that automated systems can't fix&lt;/li&gt;
&lt;li&gt;Recovery requires manual intervention&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. It Can Lie Dormant for Years
&lt;/h3&gt;

&lt;p&gt;The system could run for years without triggering this condition, then suddenly fail when the perfect storm of timing occurs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Fix It: Proper Cleanup Logic
&lt;/h2&gt;

&lt;p&gt;Here's how to implement safe cleanup that prevents this race condition:&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="c1"&gt;# SAFE: Proper Cleanup Logic with Multiple Safeguards
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cleanup_old_plans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plans&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;most_recent_completed&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;plans&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Check 1: Is the plan old by generation time?
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;most_recent_completed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;generation_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# Plan is current, skip it
&lt;/span&gt;
        &lt;span class="c1"&gt;# Check 2: Is the plan currently being applied?
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_currently_being_applied&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# Plan is in use, don't delete!
&lt;/span&gt;
        &lt;span class="c1"&gt;# Check 3: Was the plan accessed recently?
&lt;/span&gt;        &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_access_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;SAFETY_BUFFER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# Plan was accessed recently, be cautious
&lt;/span&gt;
        &lt;span class="c1"&gt;# Check 4: How many other plans reference this one?
&lt;/span&gt;        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;  &lt;span class="c1"&gt;# Other plans depend on this, keep it
&lt;/span&gt;
        &lt;span class="c1"&gt;# All checks passed, safe to delete
&lt;/span&gt;        &lt;span class="nf"&gt;delete_plan_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Key Improvements:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. State Tracking&lt;/strong&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Enum&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;CREATED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;PICKED_UP&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;IN_PROGRESS&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
    &lt;span class="n"&gt;COMPLETING&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;
    &lt;span class="n"&gt;COMPLETED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;
    &lt;span class="n"&gt;FAILED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_currently_being_applied&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PICKED_UP&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IN_PROGRESS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMPLETING&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Last Access Tracking&lt;/strong&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="c1"&gt;# Update access time whenever a plan is touched
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_access_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IN_PROGRESS&lt;/span&gt;
    &lt;span class="c1"&gt;# ... apply the plan ...
&lt;/span&gt;    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_access_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMPLETED&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Safety Buffer&lt;/strong&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="c1"&gt;# Don't delete anything accessed in the last 10 minutes
&lt;/span&gt;&lt;span class="n"&gt;SAFETY_BUFFER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Even if a plan looks old, give it a grace period
&lt;/span&gt;&lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_time&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_access_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;SAFETY_BUFFER&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Too recent, keep it for safety
&lt;/span&gt;    &lt;span class="k"&gt;continue&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Reference Counting&lt;/strong&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="c1"&gt;# Track how many Enactors are using this plan
&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;acquire&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;-=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;can_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Advanced Prevention: Fencing Tokens
&lt;/h2&gt;

&lt;p&gt;Another powerful technique is using &lt;strong&gt;fencing tokens&lt;/strong&gt; to prevent stale operations from succeeding:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConfigurationStore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Lock&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;apply_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Atomic check-and-set
&lt;/span&gt;            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;StaleOperationError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plan based on version &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                    &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;but current version is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="c1"&gt;# Apply the changes
&lt;/span&gt;            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;changes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;

            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt;

&lt;span class="c1"&gt;# Usage
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;enactor_apply_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&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="n"&gt;new_version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config_store&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;base_version&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Successfully applied plan, now at version &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;new_version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;StaleOperationError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plan is stale: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;# Don't apply this plan, it's based on old state
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that even if a slow Enactor completes, it can't apply a stale plan because the version check will fail.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons for Distributed Systems Engineers
&lt;/h2&gt;

&lt;p&gt;This race condition offers several critical lessons:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Question Your Timing Assumptions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;❌ Bad: "This operation usually takes 100ms, so timeout after 1 second"
✅ Good: "This operation usually takes 100ms, but timeout after 30 seconds and monitor p99"

❌ Bad: "If generation time is old, the plan is obsolete"
✅ Good: "If generation time is old AND it's not in use AND no one accessed it recently, it might be obsolete"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key principle:&lt;/strong&gt; Design for the exception, not the rule.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Implement Comprehensive State Tracking
&lt;/h3&gt;

&lt;p&gt;Don't just track "started" and "completed." Track:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;CREATED&lt;/code&gt;: Plan exists but not yet picked up&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;PICKED_UP&lt;/code&gt;: Enactor has claimed this plan&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;IN_PROGRESS&lt;/code&gt;: Plan is actively being applied&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COMPLETING&lt;/code&gt;: Plan is in final stages&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;COMPLETED&lt;/code&gt;: Plan finished successfully&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FAILED&lt;/code&gt;: Plan failed and is safe to clean up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This granular tracking makes it impossible to accidentally delete in-use resources.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Add Circuit Breakers to Cleanup Operations
&lt;/h3&gt;

&lt;p&gt;Before deleting critical resources, verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this resource currently locked by another process?&lt;/li&gt;
&lt;li&gt;When was this resource last accessed?&lt;/li&gt;
&lt;li&gt;How many other resources will this deletion affect?&lt;/li&gt;
&lt;li&gt;Is there a way to soft-delete first and hard-delete later?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;safe_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c1"&gt;# Soft delete: mark as deleted but keep data
&lt;/span&gt;    &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;marked_for_deletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deletion_time&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Schedule hard delete for later (24 hours)
&lt;/span&gt;    &lt;span class="nf"&gt;schedule_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;hard_delete_resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hard_delete_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Final safety check before permanent deletion
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;last_access_time&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;deletion_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# Someone accessed it after marking for deletion!
&lt;/span&gt;        &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;marked_for_deletion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c1"&gt;# Safe to permanently delete
&lt;/span&gt;    &lt;span class="nf"&gt;permanently_delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Use Optimistic Concurrency Control
&lt;/h3&gt;

&lt;p&gt;Implement version numbers that prevent stale operations:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;new_data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ConcurrencyError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Expected version &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;expected_version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;but current version is &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_data&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Design for Observable Inconsistency
&lt;/h3&gt;

&lt;p&gt;Make it easy to detect when the system is in an inconsistent state:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;verify_system_consistency&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Health check that verifies consistency&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;issues&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="c1"&gt;# Check 1: Any plans in COMPLETING state for &amp;gt; 5 minutes?
&lt;/span&gt;    &lt;span class="n"&gt;stuck_plans&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_all_plans&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;PlanState&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;COMPLETING&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;current_time&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;state_change_time&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stuck_plans&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plans stuck in COMPLETING: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;stuck_plans&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check 2: Do DNS records match the latest completed plan?
&lt;/span&gt;    &lt;span class="n"&gt;latest_plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_latest_completed_plan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;actual_dns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_current_dns_state&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;actual_dns&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;latest_plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected_dns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DNS mismatch: expected &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;latest_plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expected_dns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, got &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;actual_dns&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Check 3: Any plans marked for deletion that are still being referenced?
&lt;/span&gt;    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_plans_marked_for_deletion&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;reference_count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plan &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; marked for deletion but still referenced&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;issues&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  6. Test Timing Edge Cases
&lt;/h3&gt;

&lt;p&gt;Your test suite should include:&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_delayed_enactor_race_condition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Reproduce the race condition with artificial delays&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="c1"&gt;# Create initial plan
&lt;/span&gt;    &lt;span class="n"&gt;plan_a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;planner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_plan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Enactor 1 starts applying Plan A, but we'll delay it
&lt;/span&gt;    &lt;span class="n"&gt;enactor_1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SlowEnactor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;timedelta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;minutes&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;enactor_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply_async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# While Enactor 1 is delayed, generate newer plans
&lt;/span&gt;    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;plan_b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;planner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_plan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;plan_c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;planner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate_plan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Enactor 2 applies newer plans quickly
&lt;/span&gt;    &lt;span class="n"&gt;enactor_2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastEnactor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;enactor_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;enactor_2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# Run cleanup (this should NOT delete Plan A's resources!)
&lt;/span&gt;    &lt;span class="n"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Wait for Enactor 1 to finish
&lt;/span&gt;    &lt;span class="n"&gt;enactor_1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c1"&gt;# Verify: System should still be in consistent state
&lt;/span&gt;    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;verify_system_consistency&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="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;get_current_dns_state&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  7. Implement Gradual Rollouts for Automation
&lt;/h3&gt;

&lt;p&gt;Even if automation has been running for years, treat changes carefully:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CleanupAutomation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;  &lt;span class="c1"&gt;# Start disabled
&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_cleanup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# Not enabled for this execution
&lt;/span&gt;            &lt;span class="k"&gt;return&lt;/span&gt;

        &lt;span class="c1"&gt;# Cleanup logic here
&lt;/span&gt;        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cleanup_old_plans&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;gradual_rollout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Gradually enable cleanup automation&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;  &lt;span class="c1"&gt;# 1%
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Monitor for 24 hours
&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;  &lt;span class="c1"&gt;# 10%
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.50&lt;/span&gt;  &lt;span class="c1"&gt;# 50%
&lt;/span&gt;        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;hours&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled_percentage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;  &lt;span class="c1"&gt;# 100%
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  8. Build Manual Overrides
&lt;/h3&gt;

&lt;p&gt;No matter how reliable your automation is, have manual controls:&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="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmergencyControls&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Emergency manual overrides for production issues&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stop_all_automation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Immediately stop all automated processes&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;CleanupAutomation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;PlannerAutomation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
        &lt;span class="n"&gt;EnactorAutomation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL AUTOMATION DISABLED via emergency control&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;manual_restore_dns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Manually restore DNS state from a specific plan&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_plan_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Bypass all automation and directly set DNS
&lt;/span&gt;        &lt;span class="n"&gt;dns_service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_records&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dns_records&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DNS manually restored from plan &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;force_cleanup_plan&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Manually force deletion of a specific plan&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
        &lt;span class="n"&gt;plan&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_plan_by_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="c1"&gt;# Override all safety checks
&lt;/span&gt;        &lt;span class="nf"&gt;delete_plan_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;force&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;critical&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Plan &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;plan_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; force-deleted via manual override&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Real-World Applications
&lt;/h2&gt;

&lt;p&gt;This race condition pattern applies to many distributed systems:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Distributed Cache Invalidation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Similar bug in cache invalidation
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invalidate_cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;generation_time&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_generation_time&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;generation_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# BUG: What if another process is currently updating this key?
&lt;/span&gt;        &lt;span class="n"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Distributed Task Scheduling
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Similar bug in task cleanup
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cleanup_old_tasks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;cutoff_time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="c1"&gt;# BUG: What if this task is currently executing?
&lt;/span&gt;            &lt;span class="nf"&gt;delete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Configuration Management
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Similar bug in config rollback
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;rollback_to_previous_version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;current_version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;latest_version&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# BUG: What if current_version is being applied right now?
&lt;/span&gt;        &lt;span class="nf"&gt;delete_version_resources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_version&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Service Mesh/Load Balancer Updates
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Similar bug in endpoint updates
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_endpoints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;new_endpoints&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;old_endpoints&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_current_endpoints&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;old_endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;new_endpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="c1"&gt;# BUG: What if requests are currently routing to old_endpoints?
&lt;/span&gt;        &lt;span class="nf"&gt;remove_endpoints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;old_endpoints&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Broader Context: Why This Matters
&lt;/h2&gt;

&lt;p&gt;This race condition is more than just a specific bug. It's a window into fundamental challenges of distributed systems:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Complexity Breeds Fragility
&lt;/h3&gt;

&lt;p&gt;The system was designed to be reliable through redundancy (3 Enactors) and automation (continuous planning). But the interaction between these components created new failure modes that weren't anticipated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Insight:&lt;/strong&gt; Adding redundancy doesn't always add reliability. Sometimes it adds new ways to fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Automation Moves Faster Than Humans
&lt;/h3&gt;

&lt;p&gt;The race condition can happen in seconds. By the time humans can react, the system is in an unrecoverable state. Automation is powerful, but it needs safeguards against moving too fast.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Insight:&lt;/strong&gt; Fast automation needs slow safeguards.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The Assumption Trap
&lt;/h3&gt;

&lt;p&gt;The cleanup logic can work perfectly for years. It's only when unusual delays occur that the assumption about timing breaks down. Many systems have similar hidden assumptions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Insight:&lt;/strong&gt; Document your assumptions and test what happens when they're violated.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Timing is Everything
&lt;/h3&gt;

&lt;p&gt;In distributed systems, you can't rely on operations completing in a predictable order or time frame. Networks have delays, processes get scheduled unpredictably, and timing assumptions break down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Insight:&lt;/strong&gt; Never assume operation A will complete before operation B starts, even if A started first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Checklist for Your Systems
&lt;/h2&gt;

&lt;p&gt;Use this checklist to audit your own distributed systems for similar race conditions:&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup Logic Audit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Does cleanup check if resources are currently in use?&lt;/li&gt;
&lt;li&gt;[ ] Does cleanup use timestamps to determine staleness?&lt;/li&gt;
&lt;li&gt;[ ] Is there a safety buffer before deletion?&lt;/li&gt;
&lt;li&gt;[ ] Can you soft-delete before hard-deleting?&lt;/li&gt;
&lt;li&gt;[ ] Is there a manual override to stop cleanup?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  State Tracking Audit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Do you track in-flight operations separately from completed ones?&lt;/li&gt;
&lt;li&gt;[ ] Can you query "is resource X currently being used?"&lt;/li&gt;
&lt;li&gt;[ ] Do you log state transitions with correlation IDs?&lt;/li&gt;
&lt;li&gt;[ ] Can you reconstruct the timeline of operations?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Concurrency Control Audit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Do you use version numbers or fencing tokens?&lt;/li&gt;
&lt;li&gt;[ ] Can stale operations succeed?&lt;/li&gt;
&lt;li&gt;[ ] Is there a way to detect when operations overlap?&lt;/li&gt;
&lt;li&gt;[ ] Do you have locks or mutexes for critical sections?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Testing Audit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Do you test with artificial delays?&lt;/li&gt;
&lt;li&gt;[ ] Do you test operations completing out of order?&lt;/li&gt;
&lt;li&gt;[ ] Do you test what happens when automation runs during manual operations?&lt;/li&gt;
&lt;li&gt;[ ] Do you have chaos engineering tests?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Observability Audit
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Can you detect inconsistent state?&lt;/li&gt;
&lt;li&gt;[ ] Do you alert on unexpected state transitions?&lt;/li&gt;
&lt;li&gt;[ ] Can you trace a single operation through the entire system?&lt;/li&gt;
&lt;li&gt;[ ] Do you monitor p95/p99 latencies for timing issues?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion: The Humbling Reality of Distributed Systems
&lt;/h2&gt;

&lt;p&gt;Race conditions like this one remind us that distributed systems are inherently complex. Even with redundancy, automation, and careful design, subtle timing bugs can create catastrophic failures.&lt;/p&gt;

&lt;p&gt;But this isn't a story about inevitable failure. It's a story about learning from failure modes and designing systems that are resilient to timing edge cases.&lt;/p&gt;

&lt;p&gt;The key takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Never assume operation timing:&lt;/strong&gt; What usually takes 100ms might occasionally take 10 minutes&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Track in-flight operations:&lt;/strong&gt; Don't just know what's complete; know what's in progress&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add safety buffers to cleanup:&lt;/strong&gt; Aggressive cleanup is dangerous&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Use optimistic concurrency control:&lt;/strong&gt; Version numbers prevent stale operations&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test timing edge cases:&lt;/strong&gt; The bugs you don't test for will find you in production&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design for observability:&lt;/strong&gt; Make inconsistent states detectable&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build manual overrides:&lt;/strong&gt; Automation needs kill switches&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Document your assumptions:&lt;/strong&gt; Today's safe assumption is tomorrow's critical bug&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In distributed systems, race conditions are inevitable. But understanding them is what separates systems that fail mysteriously from systems that fail safely and recover gracefully.&lt;/p&gt;

&lt;p&gt;Every system has timing assumptions. The question is: Do you know what yours are?&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This article was written to help developers understand a subtle but devastating category of race conditions in distributed systems. The pattern described here has caused real production outages, affecting millions of users.&lt;/p&gt;

&lt;p&gt;If you found this useful, consider sharing it with your team. Review your own systems with the checklist provided. Test timing edge cases that you've been assuming "will never happen."&lt;/p&gt;

&lt;p&gt;Because in distributed systems, the timing edge case you don't test for is the one that will take down your production system at 3 AM on a holiday weekend.&lt;/p&gt;

&lt;p&gt;Let's build more reliable systems together.&lt;/p&gt;

</description>
      <category>systems</category>
      <category>cloud</category>
      <category>failure</category>
      <category>design</category>
    </item>
  </channel>
</rss>
