<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bradley Matera</title>
    <description>The latest articles on DEV Community by Bradley Matera (@bradleymatera).</description>
    <link>https://dev.to/bradleymatera</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3610693%2Ff7d715bb-f1d2-416f-94ad-ff8a4576e06a.png</url>
      <title>DEV Community: Bradley Matera</title>
      <link>https://dev.to/bradleymatera</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bradleymatera"/>
    <language>en</language>
    <item>
      <title>AI Didn't Replace Junior Developers. It Replaced Safe Places To Be One.</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Sat, 13 Jun 2026 05:59:58 +0000</pubDate>
      <link>https://dev.to/bradleymatera/ai-didnt-replace-junior-developers-it-replaced-safe-places-to-be-one-d91</link>
      <guid>https://dev.to/bradleymatera/ai-didnt-replace-junior-developers-it-replaced-safe-places-to-be-one-d91</guid>
      <description>&lt;p&gt;Every few weeks, another article lands in my inbox with a headline like "AI is Eliminating Junior Developer Roles" or "Why Entry-Level Engineers Can't Find Jobs Anymore." The narrative is consistent: AI tools are so good now that companies don't need to hire inexperienced developers. They can just have their senior engineers prompt a model and get production-ready code in minutes.&lt;/p&gt;

&lt;p&gt;I've sent over 300 job applications in the past two years. I've earned my AWS Certified Solutions Architect Associate and AI Practitioner certifications. I completed an AWS Cloud Support Associate internship. I've built projects, contributed to open source, and use AI tools daily. I'm 33 years old, a combat medic veteran from the 82nd Airborne Division, with a degree in Web Development from Full Sail University. And I'm still struggling to find a junior developer position.&lt;/p&gt;

&lt;p&gt;I don't know if entering software development was harder before. I wasn't there. What I do know is what it looks like trying to enter right now, and something about this narrative that AI is simply replacing junior developers never sat right with me.&lt;/p&gt;

&lt;p&gt;I'm not anti-AI. I use GitHub Copilot, Claude, and ChatGPT every single day. These tools have made me more productive and helped me learn faster than I ever could have otherwise. But looking at job postings and talking with other developers, it feels like AI has fundamentally changed what companies expect from entry-level hires, and I'm not sure where that leaves people like me who are still trying to break into the industry.&lt;/p&gt;

&lt;p&gt;The problem isn't that AI is replacing junior developers. The problem is that AI replaced much of the low-risk work companies historically used to train junior developers. From where I sit trying to break into the industry, this shift has created a Catch-22: you need experience to get a job, but the traditional pathways to gain that experience are disappearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Juniors (Used to) Learn Their Craft
&lt;/h2&gt;

&lt;p&gt;When I read about how junior developers learned their craft in the past, it sounds almost like a different industry. From what I can gather, entry-level developers used to spend significant time on tasks that now seem almost quaint in our AI-accelerated world:&lt;/p&gt;

&lt;p&gt;They'd spend hours fixing typos in documentation. They'd update README files when APIs changed. They'd write simple CRUD (Create, Read, Update, Delete) pages for internal tools that nobody outside the company would ever see. They'd handle straightforward bug fixes—things like correcting a misspelled variable name that was causing a form to fail validation.&lt;/p&gt;

&lt;p&gt;These tasks weren't glamorous, but they served a crucial purpose. They provided a safe environment for learning. When you made a mistake updating that documentation, the worst that happened was someone got confused about an API parameter. When you introduced a bug in that internal tool, it might inconvenience a few colleagues but wouldn't bring down customer-facing systems.&lt;/p&gt;

&lt;p&gt;Coming from the military, construction, and security work, this approach makes perfect sense to me. In the Army, you don't drop a new private into combat on day one. You start them with basic training, then gradually increase responsibility as they prove themselves. In construction, apprentices spend months learning to use tools correctly before they're trusted with more complex tasks.&lt;/p&gt;

&lt;p&gt;But looking at today's job market, it feels like the software industry has skipped this apprenticeship phase. I've seen job postings for "junior" positions that require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2-3 years of experience with specific frameworks&lt;/li&gt;
&lt;li&gt;Familiarity with cloud platforms and DevOps practices&lt;/li&gt;
&lt;li&gt;Ability to work independently with minimal supervision&lt;/li&gt;
&lt;li&gt;Experience with complex system design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a Catch-22 that I experience every day: you can't get experience without a job, but you can't get a job without experience. AI hasn't eliminated the need for human developers—it's just shifted the baseline expectations upward.&lt;/p&gt;

&lt;p&gt;I've built several projects, contributed to open source repositories, and earned AWS certifications. I use AI tools constantly in my learning process. But when I look at what companies are asking for in entry-level positions, I can't help but wonder where the modern equivalent of apprenticeship comes from.&lt;/p&gt;

&lt;p&gt;The learning that used to happen gradually and naturally on the job now seems to be expected to happen before you're even hired. This isn't just my perception—talking with other career changers, the story is remarkably consistent. We're all trying to break into an industry that seems to have eliminated many of its traditional entry points.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Companies (Used to) Hire Juniors
&lt;/h2&gt;

&lt;p&gt;Looking at job postings and talking with developers who entered the industry a few years ago, it seems like companies used to think differently about hiring juniors. From where I sit trying to break in, their reasoning makes sense:&lt;/p&gt;

&lt;p&gt;Companies invested in junior developers because they needed talent pipelines. Tech moves fast, and organizations that couldn't cultivate their own talent often found themselves unable to scale or adapt. Senior engineers don't grow on trees—you have to grow them from seedlings.&lt;/p&gt;

&lt;p&gt;There was also the matter of institutional knowledge. The person who understood why a particular workaround existed in a legacy codebase wasn't going to be a recent computer science graduate. It was going to be someone who'd been with the company for years, who'd learned the hard lessons that never made it into documentation.&lt;/p&gt;

&lt;p&gt;Succession planning mattered too. When your lead architect decided to start their own company or move to finance, you needed someone ready to step into their role. That transition was smoother when the company had invested years in developing that person's skills.&lt;/p&gt;

&lt;p&gt;Finally, there was simply the economics of supply and demand. Companies that waited for "perfect" candidates often found themselves with unfilled positions and missed opportunities. Better to hire someone promising and train them than to lose a business advantage because you couldn't find exactly the right person.&lt;/p&gt;

&lt;p&gt;But from my perspective, this model seems to be changing. I've sent applications to hundreds of companies, and the feedback I consistently receive is that I'm "overqualified" for junior positions despite having limited professional experience. When I ask for clarification, the response often comes down to needing someone who can be immediately productive.&lt;/p&gt;

&lt;p&gt;This puzzles me because I use AI tools constantly and can produce code much faster than I could without them. But it seems like companies now expect entry-level hires to be immediately productive, skipping the gradual learning curve that used to be normal. The investment in junior developers that made sense from a long-term business perspective appears to be viewed as a luxury that many companies can no longer afford.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changed Everything
&lt;/h2&gt;

&lt;p&gt;Looking at the job market from my perspective as someone trying to break in, the shift didn't happen overnight, and AI wasn't the only factor. The post-pandemic economic corrections created a new reality for many companies. Higher interest rates made expansion more expensive. Layoffs became a regular occurrence, even at profitable tech companies. Suddenly, the long-term investment in junior developers looked like a luxury few could afford.&lt;/p&gt;

&lt;p&gt;But AI productivity gains accelerated this trend in a specific way. When I talk with senior developers who use AI tools like Claude and Copilot, they tell me they can generate a basic CRUD application in minutes. From where I sit, this raises an obvious question: why spend weeks training someone to build the same thing manually when AI can do it faster?&lt;/p&gt;

&lt;p&gt;When AI can produce accurate documentation based on code changes, why pay a junior to maintain README files? The pressure to do more with fewer people became intense. Companies that had survived the pandemic by cutting costs weren't eager to add headcount, even entry-level positions. If AI could handle the work juniors once did, the math seemed simple: fewer people, same output.&lt;/p&gt;

&lt;p&gt;This created a feedback loop that I experience every day. As fewer junior positions open, competition for those roles intensifies. Companies can afford to be more selective, demanding more experience and skills from entry-level candidates. This makes it harder for true beginners like me to break in, which I can only assume reduces the pool of people who might eventually become senior developers.&lt;/p&gt;

&lt;p&gt;I've been tracking job postings for the past two years, and the change is undeniable. Positions that used to require "0-2 years of experience" now routinely ask for "2-3 years of experience with specific frameworks." Requirements that used to be nice-to-haves—like cloud certifications, DevOps experience, and full-stack capabilities—are now table stakes for entry-level roles.&lt;/p&gt;

&lt;p&gt;The economic pressures that drove these changes were real and significant. The tech sector lost hundreds of thousands of jobs in 2022 and 2023, with major companies each laying off tens of thousands of employees. In this environment, any position that could be questioned became a target for elimination or restructuring.&lt;/p&gt;

&lt;p&gt;From my vantage point, the pandemic also accelerated trends that were already underway. Remote work became the norm, which changed how companies thought about hiring. If you could hire anyone anywhere, why limit yourself to local candidates who might need training? Why not hire someone with more experience, even if it cost a bit more?&lt;/p&gt;

&lt;p&gt;Venture capital funding, which had been flowing freely into startups, dried up significantly. Startups that had been hiring aggressively suddenly needed to prove their business models and reduce burn rates. Junior positions, which often had the highest training costs and longest ramp-up times, were among the first to be eliminated.&lt;/p&gt;

&lt;p&gt;The combination of these factors created what feels like a perfect storm for entry-level developers like me. Companies that survived the immediate crisis looked around and realized they could operate with fewer people. AI tools made this reduction possible without sacrificing output. The result seems to be a fundamental shift in how the industry approaches talent development.&lt;/p&gt;

&lt;p&gt;It's worth noting that this isn't entirely irrational from a business perspective. Companies that can extract more productivity from their existing staff do have a competitive advantage. Those that can reduce their reliance on expensive senior engineers by using AI assistance can operate more efficiently.&lt;/p&gt;

&lt;p&gt;But from where I sit trying to break into the industry, the long-term consequences of this rational short-term decision are concerning. When we eliminate the pathways for people to gain experience, we're not just affecting individual careers—we're affecting the entire industry's ability to grow and adapt.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Work AI Actually Replaced
&lt;/h2&gt;

&lt;p&gt;It's important to be specific about what AI automated away, because from my perspective trying to enter the field, this represents the loss of crucial learning opportunities:&lt;/p&gt;

&lt;p&gt;Boilerplate code generation became trivial with AI assistance. Need a basic React component with state management? AI can generate that in seconds. When I first started learning React, building these components from scratch taught me fundamental concepts about state management, component lifecycle, and data flow. Now that same learning experience can be generated instantly, but I wonder if newcomers are missing out on understanding why certain patterns exist.&lt;/p&gt;

&lt;p&gt;Simple bug fixes—those misspelled variables, off-by-one errors, incorrect import statements—became almost instant with AI-powered debugging. As someone still learning to debug effectively, I can see how valuable it would have been to spend time tracking down these issues manually. Each bug taught me something about how the system worked, how errors propagated, and how to think systematically about problems.&lt;/p&gt;

&lt;p&gt;Repetitive implementation work disappeared too. Need to add a new field to a form? Connect an API endpoint to a frontend component? Implement standard authentication flows? These tasks that once provided valuable learning experiences are now routine AI-assisted work. But these weren't just busywork—they were how junior developers learned the nuts and bolts of how applications fit together.&lt;/p&gt;

&lt;p&gt;Documentation generation improved dramatically. Instead of manually writing and updating documentation, AI can generate accurate docs from code comments and examples. This reduced the need for juniors to maintain documentation as a learning exercise. But writing documentation taught developers how to explain complex technical concepts clearly—a skill that's crucial for collaboration.&lt;/p&gt;

&lt;p&gt;Simple CRUD development became almost effortless. The kind of basic data entry applications that once provided entry-level developers with experience in full-stack development, database design, and user interface principles could now be generated largely by AI. These projects were how many developers learned to think about data flow, user experience, and system architecture.&lt;/p&gt;

&lt;p&gt;From where I sit, this represents a fundamental shift in how people learn software development. The safe, low-stakes tasks that provided essential hands-on experience are increasingly being automated away, leaving fewer opportunities for newcomers to gain practical experience in a controlled environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The New Expectations Problem
&lt;/h2&gt;

&lt;p&gt;Here's where things get complicated from my perspective. As AI took over the routine work that once served as junior developer training, companies' expectations didn't adjust accordingly. Instead of recognizing that entry-level candidates would need more support and training, many organizations seem to have concluded that AI has simply made junior developers more productive.&lt;/p&gt;

&lt;p&gt;The result is what I think of as the "instant senior" phenomenon. Job postings for "junior" positions now routinely require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2-3 years of experience with specific frameworks&lt;/li&gt;
&lt;li&gt;Familiarity with cloud platforms and DevOps practices&lt;/li&gt;
&lt;li&gt;Ability to work independently with minimal supervision&lt;/li&gt;
&lt;li&gt;Experience with complex system design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a Catch-22 that I face every day. You can't get experience without a job, but you can't get a job without experience. AI hasn't eliminated the need for human developers—it's just shifted the baseline expectations upward.&lt;/p&gt;

&lt;p&gt;I've seen job postings for "junior" React developers that required more specific technical knowledge than many "senior" positions demanded just a few years ago. This isn't because the work became inherently more complex. It's because companies now expect entry-level hires to be immediately productive, skipping the gradual learning curve that used to be normal.&lt;/p&gt;

&lt;p&gt;As someone who uses AI tools constantly in my learning process, I can see both sides of this issue. AI does make me more productive and helps me learn faster. But it also means that companies can reasonably expect more from entry-level candidates. The problem is that this creates a gap between what AI can help you produce and what you actually understand deeply.&lt;/p&gt;

&lt;p&gt;I can generate a full-stack application with AI assistance, but do I truly understand how all the pieces fit together? Do I know how to debug issues when they arise? Can I make architectural decisions when requirements change? These are the kinds of skills that used to be developed gradually through hands-on experience with real systems, not through AI-assisted code generation.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Career Changer Perspective
&lt;/h2&gt;

&lt;p&gt;My path to software development wasn't typical, and I think that gives me a unique perspective on what's happening in the industry. I spent years in the Army as a combat medic with the 82nd Airborne Division, including a deployment to Afghanistan. Before that, I worked in construction, private security, warehouse jobs, and case management. I earned a B.S. in Web Development from Full Sail University while working full-time, completing the degree in 2021 after years of balancing work and study.&lt;/p&gt;

&lt;p&gt;In the military, construction, and security work, apprenticeship models are still common and respected. You start with basic tasks under close supervision, gradually taking on more responsibility as you prove yourself. You learn by doing, making mistakes in low-stakes environments, and gradually building up to more complex responsibilities.&lt;/p&gt;

&lt;p&gt;When I transitioned to tech, I expected something similar. I figured I'd start with simple tasks, learn the ropes, and work my way up. Instead, I found an industry that seems to have eliminated many of the entry points that existed for previous generations.&lt;/p&gt;

&lt;p&gt;This isn't unique to career changers like me. Even traditional computer science graduates are finding fewer opportunities to learn their craft in real-world environments. The gap between academic knowledge and practical skills has always existed, but it's widened as companies have become less willing to invest in training.&lt;/p&gt;

&lt;p&gt;In construction, you don't expect a new electrician to wire a building on day one. They spend months learning to use tools correctly, understanding electrical codes, and working under supervision before they're trusted with complex installations. In the military, junior enlisted personnel spend months in basic training and job-specific schools before taking on significant responsibilities. But in software, the expectation seems to be that you should be able to contribute meaningfully from your first day, regardless of your background.&lt;/p&gt;

&lt;p&gt;This disconnect is particularly challenging for career changers like me who are coming from fields with different learning models. I'm used to the idea that expertise takes time to develop and that mistakes are part of the learning process. But the current job market seems to expect immediate productivity without the gradual learning curve that would make that possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Learning from Other Industries
&lt;/h3&gt;

&lt;p&gt;Having worked in multiple fields before entering tech, I've observed how different industries approach training and skill development. In the Army, we had a structured progression system where competence was demonstrated through practical application, not just theoretical knowledge. You didn't become a squad leader by passing a test—you became one by successfully leading a team in training exercises and real-world missions.&lt;/p&gt;

&lt;p&gt;In construction, apprenticeship programs are formalized and regulated. An apprentice electrician works under a journeyman for years, gradually taking on more complex tasks as they prove their competence. They start with basic wiring and simple installations, progressing to complex commercial systems only after demonstrating mastery of fundamentals.&lt;/p&gt;

&lt;p&gt;In security work, new officers go through extensive training that includes both classroom instruction and supervised field work. They're never left alone with critical responsibilities until they've proven they can handle them safely and effectively.&lt;/p&gt;

&lt;p&gt;These industries recognize that expertise requires time, practice, and mentorship. They've developed systems that protect both the novice learner and the organization they're serving. The software industry seems to be moving away from this approach, and I'm not sure that's sustainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Military Comparison
&lt;/h3&gt;

&lt;p&gt;My military experience gives me a particular perspective on this issue. In the Army, we understood that investing in junior personnel was essential for mission success. A platoon sergeant who took time to develop junior soldiers was seen as valuable, not inefficient. The long-term benefits of having capable subordinates outweighed the short-term costs of training them.&lt;/p&gt;

&lt;p&gt;We also had systems in place to ensure continuity of knowledge. When experienced soldiers rotated out, they didn't take all their institutional knowledge with them. We documented procedures, mentored newcomers, and created redundancy in critical skills.&lt;/p&gt;

&lt;p&gt;In contrast, the software industry seems to be moving toward a model where knowledge is concentrated in fewer individuals. When experienced developers leave, they often take significant institutional knowledge with them, leaving gaps that are difficult to fill.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Construction Parallel
&lt;/h3&gt;

&lt;p&gt;In construction, there's a clear progression from apprentice to journeyman to master. Each level has specific requirements and expectations. An apprentice knows they're learning and expects to make mistakes under supervision. A journeyman can work independently but still consults with masters on complex problems. A master has the experience to make judgment calls and train others.&lt;/p&gt;

&lt;p&gt;This progression makes sense because construction is inherently risky. A mistake in structural engineering can kill people. The industry has developed systems that minimize risk while maximizing learning opportunities.&lt;/p&gt;

&lt;p&gt;Software development also has life-or-death stakes in some applications—medical devices, aviation systems, financial infrastructure. But the industry's approach to training doesn't always reflect this reality. Instead of creating safe learning environments, we seem to be pushing more responsibility onto less experienced developers while simultaneously reducing the support systems that would help them succeed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters Long Term
&lt;/h2&gt;

&lt;p&gt;The implications extend far beyond individual career trajectories like mine. If fewer people can enter the field, where do future senior engineers come from? Who will design the next generation of systems? Who will lead teams and make architectural decisions?&lt;/p&gt;

&lt;p&gt;The software industry has always been built on a pipeline model. Universities and coding bootcamps produce graduates. Companies hire and train them. Some become excellent engineers. Some become leaders. Some start their own companies. The cycle continues.&lt;/p&gt;

&lt;p&gt;But what happens when that pipeline narrows? When the work that once provided essential training disappears? When the expectations for entry-level positions become so high that fewer people can meet them?&lt;/p&gt;

&lt;p&gt;From where I sit trying to break into the industry, we're already seeing some effects. Salaries for experienced developers continue to rise, even as entry-level opportunities shrink. The gap between junior and senior compensation has widened. Companies are investing more in tools and processes to extract maximum productivity from their existing staff rather than growing their teams.&lt;/p&gt;

&lt;p&gt;This creates a brittle system. When experienced developers leave—as they inevitably do—there may be fewer qualified people to replace them. The institutional knowledge that once accumulated over years of gradual learning might be concentrated in fewer and fewer individuals.&lt;/p&gt;

&lt;p&gt;As someone who's been through multiple career transitions, this pattern looks familiar. I've seen what happens when industries become too focused on short-term efficiency and lose sight of long-term sustainability. The question is whether the software industry will recognize this pattern before it becomes a crisis.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Experience Gap
&lt;/h3&gt;

&lt;p&gt;One of the most concerning trends I've observed is the growing experience gap in the industry. When I talk to senior developers at conferences or in online communities, many express frustration with the lack of mid-level engineers. They're hiring either very junior developers who need extensive training or very senior developers who command high salaries.&lt;/p&gt;

&lt;p&gt;This gap didn't appear overnight. It's the result of several years of reduced investment in junior developer training, combined with increased demands on those who do make it through the initial hurdles. The developers who would have spent the last few years developing into mid-level roles are missing, creating a gap between entry-level and senior positions.&lt;/p&gt;

&lt;p&gt;I've experienced this gap firsthand in job interviews. I'm often told I'm "too experienced" for junior positions but "not experienced enough" for mid-level roles. This isn't just my perception—it's feedback I've received from dozens of interviews and conversations with hiring managers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Innovation Problem
&lt;/h3&gt;

&lt;p&gt;There's another long-term concern that keeps me up at night: the potential impact on innovation. Historically, some of the most innovative solutions in software development have come from junior developers who didn't know what was "supposed to be impossible." They approached problems with fresh perspectives, unencumbered by assumptions about how things were "supposed to work."&lt;/p&gt;

&lt;p&gt;When we eliminate the pathways for people to gain experience, we're not just affecting individual careers—we're potentially limiting the industry's ability to innovate. The next breakthrough in software development might come from someone who's just entering the field, but if we make it impossible for newcomers to gain the experience they need, we might miss that breakthrough entirely.&lt;/p&gt;

&lt;p&gt;I've seen this principle in action in my previous careers. Some of the best security solutions I've encountered came from new officers who questioned established procedures. Some of the most efficient construction techniques I've learned came from apprentices who suggested improvements to traditional methods.&lt;/p&gt;

&lt;p&gt;The software industry has benefited from this kind of fresh thinking throughout its history. From the early days of personal computing to the rise of the web to the mobile revolution, many breakthroughs came from people who were relatively new to the field. If we make it harder for newcomers to gain experience, we might be limiting our own future potential.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Diversity Concern
&lt;/h3&gt;

&lt;p&gt;This shift also has implications for diversity in the industry. Career changers like me, people from non-traditional backgrounds, and those who didn't follow the conventional path through computer science education are already underrepresented in tech. When we eliminate many of the traditional entry points, we're likely to reduce diversity even further.&lt;/p&gt;

&lt;p&gt;I've noticed this in my own job search. Many of the positions I've applied for seem to assume a particular career trajectory: computer science degree, internship at a tech company, progression through increasingly senior roles. This path excludes many talented people who might contribute significantly to the industry but didn't start their careers in tech.&lt;/p&gt;

&lt;p&gt;The lack of diverse perspectives in software development has real consequences. Products are built by people with similar backgrounds, leading to blind spots and missed opportunities. When we make it harder for people from different backgrounds to enter the field, we're not just limiting their opportunities—we're limiting the industry's potential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addressing Counterarguments
&lt;/h2&gt;

&lt;p&gt;It's important to acknowledge that this analysis isn't universally accepted, and I've encountered compelling counterarguments in my discussions with other developers and hiring managers.&lt;/p&gt;

&lt;p&gt;Some argue that AI creates new opportunities rather than just eliminating old ones. Perhaps we're seeing a shift toward more creative, strategic, and complex work. Instead of spending time on routine implementation, developers can focus on architecture, user experience, and business logic.&lt;/p&gt;

&lt;p&gt;There's truth to this. AI tools do enable developers to tackle more interesting problems earlier in their careers. A junior developer today might work on machine learning integrations or complex data pipelines that would have been senior-only work just a few years ago. I've seen this in my own learning—AI has helped me explore advanced topics that would have been out of reach without assistance.&lt;/p&gt;

&lt;p&gt;Others point out that juniors have more tools than ever before. Documentation is better, learning resources are abundant, and AI assistance can help bridge knowledge gaps quickly. Why shouldn't companies expect more from entry-level candidates when they have so many resources available?&lt;/p&gt;

&lt;p&gt;This is also valid. The barrier to acquiring technical knowledge has never been lower. A motivated beginner can learn more in their first year than previous generations could learn in several years of formal education. I've certainly benefited from this—my AWS certifications and project work were made possible by the wealth of resources available today.&lt;/p&gt;

&lt;p&gt;Finally, some argue that previous generations faced different barriers. The dot-com bust, the 2008 financial crisis, and other economic disruptions all affected entry-level opportunities. What makes the current situation unique?&lt;/p&gt;

&lt;p&gt;The difference, from where I sit, may be in the nature of the change. Previous disruptions were cyclical—bad times followed by recovery periods where traditional hiring practices returned. The AI-driven shift might be structural, fundamentally altering how the industry develops talent. This isn't just a temporary market correction—it's a fundamental change in what companies expect from new hires and how they're willing to invest in their development.&lt;/p&gt;

&lt;p&gt;I've also noticed something else in my conversations with developers who entered the industry before the AI boom. They often talk about learning on the job in ways that seem increasingly rare. The safe, low-stakes tasks that provided essential hands-on experience are disappearing, and I'm not sure what's replacing them as effective learning mechanisms.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Just Learn Faster" Argument
&lt;/h3&gt;

&lt;p&gt;One argument I hear frequently is that the solution is simply to learn faster. With all the resources available today, the thinking goes, there's no excuse for not being able to acquire the skills needed for a junior position in a matter of months rather than years.&lt;/p&gt;

&lt;p&gt;This argument misses a crucial point about how expertise actually develops. Yes, I can use AI tools to generate code for a web application in hours rather than weeks. But understanding why that code works, how to debug it when it fails, and how to modify it for different requirements still takes time and experience.&lt;/p&gt;

&lt;p&gt;I've experienced this firsthand. I can generate a React component with AI assistance, but when it doesn't behave as expected, I still need to understand the underlying principles to debug it effectively. I can create a database schema with AI help, but designing for performance, scalability, and security requires experience that can't be shortcut.&lt;/p&gt;

&lt;p&gt;The "just learn faster" argument also assumes that all learning happens in isolation. In reality, much of what makes someone effective as a developer comes from working with others, understanding organizational dynamics, and developing soft skills that are difficult to acquire through self-study.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Everyone Started Somewhere" Perspective
&lt;/h3&gt;

&lt;p&gt;Another counterargument I encounter is that everyone started somewhere, and previous generations of developers faced similar challenges. This is true to some extent, but there are important differences in the current landscape.&lt;/p&gt;

&lt;p&gt;When I talk to senior developers who entered the field 10-15 years ago, they describe a different environment. Yes, they faced challenges, but there were more entry-level positions available, and companies were more willing to invest in training. The path from beginner to experienced developer was more clearly defined and supported.&lt;/p&gt;

&lt;p&gt;The current situation is different because the nature of entry-level work itself has changed. It's not just that there are fewer positions—it's that the positions that do exist require more experience and skills than before. This creates a fundamentally different challenge for newcomers.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Bootcamp Graduates Are Fine" Observation
&lt;/h3&gt;

&lt;p&gt;Some argue that coding bootcamp graduates are still finding jobs, so the problem isn't as severe as I'm suggesting. While it's true that some bootcamp graduates are successful, my observations suggest the picture is more complex.&lt;/p&gt;

&lt;p&gt;Many of the bootcamp graduates I know who have found jobs had significant advantages: previous technical experience, strong networks, or the ability to dedicate full time to job searching. For career changers like me who are also supporting families, the path is much more challenging.&lt;/p&gt;

&lt;p&gt;Additionally, the jobs that bootcamp graduates are finding often come with their own challenges. Some are in roles that are being automated, others require extensive unpaid overtime to meet unrealistic expectations, and many don't provide the mentorship and growth opportunities that would help develop long-term careers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding a Path Forward
&lt;/h2&gt;

&lt;p&gt;So where does this leave someone like me who's trying to break into the industry? If I'm right that AI primarily eliminated the safe learning environments that once existed for junior developers, what can be done about it?&lt;/p&gt;

&lt;p&gt;First, we need to recognize that the traditional apprenticeship model hasn't disappeared—it's just moved. Instead of learning on the job at established companies, many new developers are building skills through open source contributions, personal projects, and community involvement.&lt;/p&gt;

&lt;p&gt;This isn't necessarily worse than the old model, but it is different. It requires more self-direction and may not provide the same breadth of experience. A developer who builds impressive projects in isolation might struggle with the collaborative, process-heavy environment of many companies. I've experienced this myself—my projects demonstrate technical ability, but they don't show how I'd work within an existing team or navigate complex organizational dynamics.&lt;/p&gt;

&lt;p&gt;Second, companies need to reconsider their hiring practices. If AI has eliminated much of the routine work that once provided training, perhaps they need to be more intentional about creating learning opportunities. This might mean dedicated mentorship programs, rotational assignments, or explicit investment in junior developer growth.&lt;/p&gt;

&lt;p&gt;I've been fortunate to find some companies that still recognize the value of investing in junior talent. My AWS Cloud Support Associate internship was structured around this principle, and it made a huge difference in my development. But these programs seem to be becoming rarer, which concerns me for the future of the industry.&lt;/p&gt;

&lt;p&gt;Third, the industry needs to acknowledge that the skills required for effective AI collaboration are different from those required for traditional development. Prompt engineering, result verification, and understanding AI limitations are now essential skills. Companies that recognize and train for these skills may find they can be more effective with smaller teams.&lt;/p&gt;

&lt;p&gt;From my perspective, this creates an opportunity. While many experienced developers are still learning how to work effectively with AI, newcomers like me are growing up with these tools. The question is whether companies will recognize this as a strength rather than a weakness.&lt;/p&gt;

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

&lt;p&gt;The narrative that AI is eliminating junior developer roles misses an important nuance, at least from where I sit trying to break into the industry. AI didn't eliminate the need for human developers. It eliminated many of the safe, low-stakes opportunities that helped people learn to become effective developers.&lt;/p&gt;

&lt;p&gt;This creates real challenges for career changers like me and newcomers to the field. It also creates long-term risks for the industry as a whole. If fewer people can enter the profession, the pipeline of future senior engineers, architects, and technical leaders will eventually shrink.&lt;/p&gt;

&lt;p&gt;The solution isn't to resist AI or pretend it hasn't changed the landscape. As someone who uses AI tools constantly, I can attest to their value in learning and development. But we need to recognize how AI has changed things and adapt accordingly. This means creating new pathways for learning and growth, adjusting expectations to match reality, and investing in the human skills that AI can't replace.&lt;/p&gt;

&lt;p&gt;The industry still needs new developers. The challenge is figuring out how people gain experience when many of the traditional entry-level tasks are increasingly automated. Those who solve this challenge—whether individuals, companies, or communities—will likely find themselves with significant advantages in the evolving tech landscape.&lt;/p&gt;

&lt;p&gt;As I continue applying for positions and building my skills, I'm trying to focus on what makes me valuable beyond what AI can produce. I bring problem-solving skills honed in high-stress environments, the ability to learn quickly and adapt, and a perspective shaped by multiple career transitions. I use AI tools effectively, but I also understand their limitations.&lt;/p&gt;

&lt;p&gt;AI didn't replace junior developers. It replaced safe places to be one. The question now is how we create new safe places in an AI-assisted world—places where people like me can learn, grow, and eventually contribute meaningfully to the industry's future.&lt;/p&gt;

&lt;p&gt;I don't know if entering software development was harder before. I wasn't there. But I do know that the path forward requires creativity, adaptability, and a willingness to forge new pathways where traditional ones have disappeared. For people like me trying to break into the industry, that's both a challenge and an opportunity.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Reality of AI-Enhanced Productivity
&lt;/h2&gt;

&lt;p&gt;As someone who uses AI tools daily in my learning and development process, I can attest to their incredible productivity benefits. But I've also observed how these tools are changing expectations in ways that may not be sustainable.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Productivity Paradox
&lt;/h3&gt;

&lt;p&gt;When I first started learning to code, building a simple web application might take me days or even weeks. I'd spend hours debugging simple syntax errors, researching API documentation, and figuring out how to connect different components. It was frustrating, but it was also how I learned.&lt;/p&gt;

&lt;p&gt;Now, with AI assistance, I can build the same application in hours. GitHub Copilot suggests code as I type. Claude helps me debug complex issues. ChatGPT explains concepts I don't understand. These tools have made me significantly more productive than I would have been without them.&lt;/p&gt;

&lt;p&gt;But this creates a paradox. Companies can see what AI-assisted developers can produce, so they adjust their expectations accordingly. They assume that entry-level candidates should be able to produce at the same rate, even though they haven't had years to learn how to use these tools effectively.&lt;/p&gt;

&lt;p&gt;This is where my perspective as someone still learning differs from that of experienced developers. I use AI tools, but I'm still learning when and how to trust their output. I'm still developing the judgment to know when AI suggestions are appropriate and when they're misleading. I'm still building the foundational knowledge that would allow me to use these tools effectively even when they fail.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Verification Challenge
&lt;/h3&gt;

&lt;p&gt;One of the most important skills I've had to develop is verification. AI tools can generate code quickly, but that code isn't always correct. I've spent countless hours debugging AI-generated code that looked right but contained subtle errors.&lt;/p&gt;

&lt;p&gt;This is where the experience gap becomes apparent. Experienced developers have spent years building intuition about what code should look like, how systems should behave, and what kinds of errors to expect. They can quickly spot when AI output is wrong because it violates principles they've learned through experience.&lt;/p&gt;

&lt;p&gt;As a newcomer, I'm still building that intuition. I can verify that code runs without errors, but I might miss subtle issues with security, performance, or maintainability. This is why I believe the traditional apprenticeship model was valuable—it gave junior developers time to build that intuition gradually, with guidance from more experienced colleagues.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Prompt Engineering Skill
&lt;/h3&gt;

&lt;p&gt;Another skill I've had to develop is prompt engineering. Getting good output from AI tools requires understanding how to frame questions, provide context, and iterate on results. This isn't something that's typically taught in computer science programs or coding bootcamps.&lt;/p&gt;

&lt;p&gt;I've learned prompt engineering through trial and error, experimentation, and observation of how more experienced developers work with these tools. But this learning process would have been much easier with mentorship and guidance from experienced colleagues.&lt;/p&gt;

&lt;p&gt;The problem is that companies now expect entry-level developers to have these skills without providing the learning opportunities that would help them develop them. It's like expecting someone to become a master electrician without ever working under a journeyman.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Pathways and Their Limitations
&lt;/h2&gt;

&lt;p&gt;While traditional entry-level positions have become scarcer, several alternative pathways have emerged. However, each comes with its own limitations and challenges.&lt;/p&gt;

&lt;h3&gt;
  
  
  Open Source Contributions
&lt;/h3&gt;

&lt;p&gt;Many developers suggest contributing to open source projects as a way to gain experience and build a portfolio. I've tried this approach, and while it has value, it's not a complete solution to the apprenticeship problem.&lt;/p&gt;

&lt;p&gt;Open source contributions can demonstrate technical ability and collaboration skills, but they don't replicate the full experience of working in a professional development environment. There's no product manager to clarify requirements, no deadlines that affect business outcomes, and no complex organizational dynamics to navigate.&lt;/p&gt;

&lt;p&gt;Additionally, contributing to popular open source projects is extremely competitive. Many projects receive hundreds of contributions for each accepted pull request. For someone still learning, getting meaningful contributions accepted can be incredibly challenging.&lt;/p&gt;

&lt;p&gt;I've had some success with smaller projects, but these often lack the complexity and scale of real-world applications. The skills I've developed through open source work are valuable, but they don't fully prepare me for the challenges of professional software development.&lt;/p&gt;

&lt;h3&gt;
  
  
  Personal Projects and Portfolio Building
&lt;/h3&gt;

&lt;p&gt;Building personal projects is another commonly suggested approach. I've built several projects, including a task management application, a weather dashboard, and a simple e-commerce site. These projects have helped me develop technical skills and demonstrate my abilities to potential employers.&lt;/p&gt;

&lt;p&gt;However, personal projects have limitations as learning tools. They don't involve working with legacy code, navigating complex requirements, or dealing with the constraints of existing systems. They also don't provide experience with code review processes, deployment pipelines, or collaboration with team members.&lt;/p&gt;

&lt;p&gt;Most importantly, personal projects don't replicate the pressure of real business requirements. When a project is just for learning, it's easy to take shortcuts or abandon it when things get difficult. In a professional environment, these challenges must be faced and overcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding Bootcamps and Online Courses
&lt;/h3&gt;

&lt;p&gt;I've considered enrolling in additional coding bootcamps or online courses, but my experience suggests these have limitations as pathways to employment. Many bootcamps make promises about job placement that don't match reality. The job market they describe often doesn't exist for graduates.&lt;/p&gt;

&lt;p&gt;Online courses can provide valuable knowledge, but they don't replace hands-on experience with real systems and real problems. They also don't provide the mentorship and guidance that comes from working with experienced developers.&lt;/p&gt;

&lt;p&gt;The time and financial investment required for additional education is also significant, especially for someone like me who is already supporting a family while trying to transition careers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Freelancing and Contract Work
&lt;/h3&gt;

&lt;p&gt;Some suggest starting with freelancing or contract work as a way to gain experience. While this approach can work, it comes with significant risks and challenges for newcomers.&lt;/p&gt;

&lt;p&gt;Freelancing requires not just technical skills but also business skills: finding clients, negotiating contracts, managing finances, and handling legal issues. For someone still learning technical skills, adding these business challenges can be overwhelming.&lt;/p&gt;

&lt;p&gt;Contract work often involves working on existing projects with tight deadlines and high expectations. Without the safety net of mentorship and gradual learning, mistakes can be costly both financially and reputationally.&lt;/p&gt;

&lt;p&gt;Additionally, the freelance and contract market is highly competitive, with many experienced developers also seeking these opportunities. As a newcomer, competing on price alone often leads to a race to the bottom that doesn't provide sustainable income or meaningful learning opportunities.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Companies Can Do Differently
&lt;/h2&gt;

&lt;p&gt;While individuals like me face significant challenges, companies also have opportunities to adapt their approaches to talent development in ways that benefit both the organization and new developers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Structured Learning Environments
&lt;/h3&gt;

&lt;p&gt;Companies that invest in structured learning environments for junior developers often see significant returns. These programs don't have to replicate the traditional apprenticeship model exactly, but they should provide the same core benefits: safe spaces to make mistakes, gradual increases in responsibility, and mentorship from experienced colleagues.&lt;/p&gt;

&lt;p&gt;Some companies have started creating "resident" programs where new developers spend their first year rotating through different teams and projects, gaining broad exposure to the organization's systems and processes. Others have established formal mentorship programs that pair junior developers with senior mentors for regular check-ins and guidance.&lt;/p&gt;

&lt;p&gt;These programs require investment, but they also create more capable, loyal employees. Developers who feel supported in their learning are more likely to stay with a company long-term and become valuable contributors.&lt;/p&gt;

&lt;h3&gt;
  
  
  Redefining Entry-Level Roles
&lt;/h3&gt;

&lt;p&gt;Companies could also reconsider what entry-level roles should look like in an AI-assisted world. Instead of expecting junior developers to be immediately productive on complex projects, they could create roles focused on learning and growth.&lt;/p&gt;

&lt;p&gt;These roles might involve working closely with AI tools to understand their capabilities and limitations, documenting best practices for AI collaboration, or developing internal training materials. They could provide value to the organization while also giving new developers the time and support they need to develop expertise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Better Feedback Loops
&lt;/h3&gt;

&lt;p&gt;One of the challenges I've observed is that many junior developers work in environments with poor feedback loops. They might spend weeks on a project only to have it rejected in code review with minimal explanation. This is frustrating and doesn't provide the learning opportunities that make feedback valuable.&lt;/p&gt;

&lt;p&gt;Companies that invest in better feedback processes—regular one-on-one meetings, detailed code reviews, and clear expectations—tend to develop more capable junior developers. These processes take time and effort, but they're more effective than simply throwing new developers into complex projects and hoping for the best.&lt;/p&gt;

&lt;h3&gt;
  
  
  Recognizing Different Types of Experience
&lt;/h3&gt;

&lt;p&gt;Finally, companies could benefit from recognizing that experience comes in many forms. My background as a combat medic, construction worker, and security officer has given me skills that are valuable in software development: problem-solving under pressure, attention to detail, and the ability to work effectively in teams.&lt;/p&gt;

&lt;p&gt;Too often, job postings focus exclusively on traditional software development experience, missing out on candidates who might bring valuable perspectives and skills from other fields. Companies that broaden their definition of relevant experience may find they have access to a larger, more diverse pool of talented candidates.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Path Forward for Individuals
&lt;/h2&gt;

&lt;p&gt;For people like me who are trying to break into the industry, there are still strategies that can improve our chances of success, even in this challenging environment.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a Learning Mindset
&lt;/h3&gt;

&lt;p&gt;One of the most important shifts I've made is embracing a learning mindset rather than focusing solely on immediate job placement. Instead of viewing every rejection as a failure, I try to extract lessons that will help me grow as a developer.&lt;/p&gt;

&lt;p&gt;This means seeking feedback whenever possible, even when it's not offered. It means viewing every project—whether personal, open source, or professional—as an opportunity to learn something new. It means staying curious about technologies and approaches that might not be immediately relevant to my job search.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developing a Broad Skill Set
&lt;/h3&gt;

&lt;p&gt;I've also focused on developing a broad skill set rather than deep expertise in a single area. While specialization has its benefits, having a diverse set of skills makes me more adaptable to different roles and companies.&lt;/p&gt;

&lt;p&gt;This includes not just technical skills—programming languages, frameworks, tools—but also soft skills like communication, project management, and problem-solving. It also means understanding the business context in which software is developed, not just the technical implementation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating Value Wherever Possible
&lt;/h3&gt;

&lt;p&gt;Another strategy I've adopted is looking for ways to create value wherever I can, even when those opportunities don't immediately lead to employment. This might mean contributing to open source projects, writing technical blog posts, or helping other developers in online communities.&lt;/p&gt;

&lt;p&gt;These activities help me build skills, establish a reputation in the community, and sometimes lead to job opportunities. More importantly, they help me develop the mindset of someone who creates value rather than just someone who wants a job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Genuine Relationships
&lt;/h3&gt;

&lt;p&gt;Networking is often cited as important for career development, but I've found that building genuine relationships is more valuable than collecting contacts. This means engaging with other developers because I'm genuinely interested in their work and perspectives, not just because I hope they'll give me a job.&lt;/p&gt;

&lt;p&gt;These relationships have led to mentorship opportunities, collaboration on projects, and insights into different companies and roles. They've also made the journey more enjoyable and less isolating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintaining Long-Term Perspective
&lt;/h3&gt;

&lt;p&gt;Finally, I've tried to maintain a long-term perspective on my career development. Breaking into the software industry is challenging, but it's not impossible. Success often requires persistence, patience, and the ability to learn from setbacks.&lt;/p&gt;

&lt;p&gt;I've had to remind myself that the goal isn't just to get any job, but to build a sustainable, fulfilling career. This might mean being selective about opportunities, even when they're scarce. It might mean investing time in learning and growth rather than rushing into the first available position.&lt;/p&gt;

&lt;p&gt;The path forward isn't easy, but it's not impossible either. For people like me who are committed to the journey, there are still opportunities to build meaningful careers in software development, even in this changing landscape.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>productivity</category>
      <category>programming</category>
    </item>
    <item>
      <title>The AI Review Trap: Why Verification Matters More Than Prompting</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Sat, 13 Jun 2026 05:37:40 +0000</pubDate>
      <link>https://dev.to/bradleymatera/the-ai-review-trap-why-verification-matters-more-than-prompting-3lak</link>
      <guid>https://dev.to/bradleymatera/the-ai-review-trap-why-verification-matters-more-than-prompting-3lak</guid>
      <description>&lt;h2&gt;
  
  
  Most AI development content focuses on prompting.
&lt;/h2&gt;

&lt;p&gt;Browse any AI coding discussion and the questions are consistent:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which model should I use?&lt;/li&gt;
&lt;li&gt;What prompt gets the best output?&lt;/li&gt;
&lt;li&gt;How do I make agents more autonomous?&lt;/li&gt;
&lt;li&gt;Should I use Claude or GPT-4?&lt;/li&gt;
&lt;li&gt;How do I improve my prompt engineering?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These questions assume the bottleneck is generation quality.&lt;/p&gt;

&lt;p&gt;That assumption is wrong.&lt;/p&gt;

&lt;p&gt;The real bottleneck is verification.&lt;/p&gt;

&lt;p&gt;AI systems are exceptionally good at producing answers that appear correct. They format code cleanly. They write confident explanations. They sound authoritative. They produce documentation-quality output.&lt;/p&gt;

&lt;p&gt;But confidence is not correctness.&lt;/p&gt;

&lt;p&gt;The trap works like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You ask an AI system a question.&lt;/li&gt;
&lt;li&gt;The system returns a confident, well-formatted answer.&lt;/li&gt;
&lt;li&gt;You assume confidence means correctness.&lt;/li&gt;
&lt;li&gt;You build on top of that answer.&lt;/li&gt;
&lt;li&gt;The mistake compounds.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is the AI Review Trap.&lt;/p&gt;

&lt;p&gt;The most dangerous part is not the initial mistake. AI will make mistakes. The dangerous part is building layers of work on top of an unverified assumption.&lt;/p&gt;

&lt;p&gt;For junior developers, self-taught developers, and career changers using AI as a learning tool, this trap is especially costly. When you do not yet have the pattern recognition to spot mistakes quickly, every unverified answer becomes a potential production issue, a confusing debugging session, or hours of wasted work.&lt;/p&gt;

&lt;p&gt;This guide argues that the most important skill in AI-assisted development is not prompting.&lt;/p&gt;

&lt;p&gt;It is verification.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Confidence Problem
&lt;/h2&gt;

&lt;p&gt;AI does not know when it is wrong.&lt;/p&gt;

&lt;p&gt;This is not a flaw in any specific model. This is how these systems work. They predict tokens. They do not verify truth. They do not check documentation. They do not run code. They produce output that matches patterns in their training data.&lt;/p&gt;

&lt;p&gt;When an AI system generates code, it does so with the same confident tone regardless of whether the code is correct.&lt;/p&gt;

&lt;p&gt;Consider these examples:&lt;/p&gt;

&lt;h3&gt;
  
  
  Non-Existent APIs
&lt;/h3&gt;

&lt;p&gt;An AI generates a method call that sounds reasonable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_by_email&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user@example.com&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;p&gt;The method does not exist. The actual Stripe API requires listing customers with an email filter. But the AI's answer looks correct. The syntax is valid. The method name is plausible. A junior developer might spend twenty minutes debugging before realizing the API call itself is wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deprecated Methods
&lt;/h3&gt;

&lt;p&gt;AI training data often includes older framework versions. The generated code might use a method that worked in React 16 but was removed in React 18. The code looks fine. The explanation is confident. The compiler might even accept parts of it. But the runtime behavior is broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrong Package Names
&lt;/h3&gt;

&lt;p&gt;AI suggests installing &lt;code&gt;stripe-node&lt;/code&gt; instead of &lt;code&gt;stripe&lt;/code&gt;. Or &lt;code&gt;aws-sdk-v3&lt;/code&gt; instead of &lt;code&gt;@aws-sdk/client-s3&lt;/code&gt;. The package name looks reasonable. The installation fails or installs the wrong library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incorrect Framework Patterns
&lt;/h3&gt;

&lt;p&gt;AI generates a Next.js API route using an outdated pattern that worked in Next.js 12 but breaks in Next.js 14. Or it produces a Vue 2 component structure when the project uses Vue 3. The code is syntactically valid but architecturally wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invalid Configuration
&lt;/h3&gt;

&lt;p&gt;AI recommends an IAM policy that grants permissions using a deprecated action name. Or it suggests a Docker Compose configuration that uses syntax from an older specification version. The file looks correct but fails at runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Issues
&lt;/h3&gt;

&lt;p&gt;AI generates code that works but exposes secrets in environment variables accessible to the client. Or it creates an API endpoint without authentication. Or it builds a form without input validation. The functionality works. The security posture is broken.&lt;/p&gt;

&lt;h3&gt;
  
  
  Outdated Documentation References
&lt;/h3&gt;

&lt;p&gt;AI cites a configuration option that was removed in the latest version of the tool. Or it references a CLI flag that no longer exists. The explanation sounds authoritative but the actual command fails.&lt;/p&gt;

&lt;h3&gt;
  
  
  Broken Business Logic
&lt;/h3&gt;

&lt;p&gt;AI generates code that passes type checks and compiles successfully but implements the wrong business rule. A discount calculation rounds the wrong way. A date comparison uses the wrong timezone. A filter excludes valid records.&lt;/p&gt;

&lt;p&gt;The problem is not that these mistakes exist. Humans make similar mistakes.&lt;/p&gt;

&lt;p&gt;The problem is that AI presents every answer with the same polished confidence.&lt;/p&gt;

&lt;p&gt;Correct code and incorrect code look identical until you verify them.&lt;/p&gt;




&lt;h2&gt;
  
  
  Generation vs Verification
&lt;/h2&gt;

&lt;p&gt;AI accelerates generation.&lt;/p&gt;

&lt;p&gt;Generation includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Writing code&lt;/li&gt;
&lt;li&gt;Writing explanations&lt;/li&gt;
&lt;li&gt;Writing documentation&lt;/li&gt;
&lt;li&gt;Proposing solutions&lt;/li&gt;
&lt;li&gt;Suggesting architectures&lt;/li&gt;
&lt;li&gt;Producing boilerplate&lt;/li&gt;
&lt;li&gt;Drafting tests&lt;/li&gt;
&lt;li&gt;Creating configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generation is cheap. AI can produce thousands of lines of code in seconds.&lt;/p&gt;

&lt;p&gt;Verification is what creates value.&lt;/p&gt;

&lt;p&gt;Verification includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running code&lt;/li&gt;
&lt;li&gt;Testing code&lt;/li&gt;
&lt;li&gt;Reading logs&lt;/li&gt;
&lt;li&gt;Checking outputs&lt;/li&gt;
&lt;li&gt;Reviewing assumptions&lt;/li&gt;
&lt;li&gt;Comparing against documentation&lt;/li&gt;
&lt;li&gt;Testing edge cases&lt;/li&gt;
&lt;li&gt;Validating security&lt;/li&gt;
&lt;li&gt;Confirming business logic&lt;/li&gt;
&lt;li&gt;Checking error states&lt;/li&gt;
&lt;li&gt;Testing user flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Verification is expensive. It requires time, attention, and understanding.&lt;/p&gt;

&lt;p&gt;Most developers using AI optimize for generation speed. They want faster output. Better prompts. More autonomous agents.&lt;/p&gt;

&lt;p&gt;The developers who succeed with AI optimize for verification speed. They want faster feedback loops. Better testing. More reliable validation.&lt;/p&gt;

&lt;p&gt;Here is the distinction:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Generation&lt;/th&gt;
&lt;th&gt;Verification&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;AI writes 100 lines of code&lt;/td&gt;
&lt;td&gt;You run the code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI explains an API&lt;/td&gt;
&lt;td&gt;You read the official docs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI suggests a configuration&lt;/td&gt;
&lt;td&gt;You test the configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI proposes a solution&lt;/td&gt;
&lt;td&gt;You validate the solution works&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI generates a component&lt;/td&gt;
&lt;td&gt;You test the component in the browser&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI creates a migration&lt;/td&gt;
&lt;td&gt;You review the migration in a staging environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI writes a test&lt;/td&gt;
&lt;td&gt;You verify the test actually fails when it should&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Generation is the starting point.&lt;/p&gt;

&lt;p&gt;Verification is the work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Senior Developers Catch More AI Mistakes
&lt;/h2&gt;

&lt;p&gt;Experience often looks like intelligence.&lt;/p&gt;

&lt;p&gt;A senior developer reviews AI-generated code and immediately spots problems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"This will break in production because the timeout is too short."&lt;/li&gt;
&lt;li&gt;"This configuration will cause memory issues under load."&lt;/li&gt;
&lt;li&gt;"This migration will lock the table."&lt;/li&gt;
&lt;li&gt;"This API call will fail when the user is not authenticated."&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not magic. It is pattern recognition.&lt;/p&gt;

&lt;p&gt;Senior developers have seen these failures before:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication systems that failed during deployment.&lt;/li&gt;
&lt;li&gt;Database migrations that caused downtime.&lt;/li&gt;
&lt;li&gt;Configuration mistakes that broke monitoring.&lt;/li&gt;
&lt;li&gt;API integrations that worked in development but failed in production.&lt;/li&gt;
&lt;li&gt;Security issues that were caught in code review or, worse, discovered in production.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because they have debugged these problems, they instinctively verify assumptions AI makes.&lt;/p&gt;

&lt;p&gt;When AI suggests a configuration, they check the documentation.&lt;/p&gt;

&lt;p&gt;When AI generates a query, they think about performance.&lt;/p&gt;

&lt;p&gt;When AI writes an API route, they consider authentication.&lt;/p&gt;

&lt;p&gt;When AI proposes a deployment step, they think about rollback.&lt;/p&gt;

&lt;p&gt;Junior developers can build this skill intentionally.&lt;/p&gt;

&lt;p&gt;The method is simple: verify everything until verification becomes instinct.&lt;/p&gt;

&lt;p&gt;Over time, you will start recognizing patterns. You will see AI suggest something and think, "I have debugged this exact mistake before."&lt;/p&gt;

&lt;p&gt;That instinct is not a replacement for verification. It is a signal that tells you where to verify first.&lt;/p&gt;




&lt;h2&gt;
  
  
  Real-World AI Failure Scenarios
&lt;/h2&gt;

&lt;p&gt;These are not hypothetical. These are patterns that happen repeatedly in AI-assisted development.&lt;/p&gt;

&lt;h3&gt;
  
  
  API Hallucination
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You ask AI how to retrieve a user from Stripe by email.&lt;/p&gt;

&lt;p&gt;AI responds:&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;user&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;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;getByEmail&lt;/code&gt; method does not exist in the Stripe API.&lt;/p&gt;

&lt;p&gt;The actual pattern is:&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;customers&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;stripe&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user@example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;limit&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;customers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&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;/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;p&gt;The hallucinated method looks correct. It follows JavaScript conventions. It matches the mental model of "get a customer by email." A developer might copy it, assume it works, and only discover the problem when the code runs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verification Step:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Check the Stripe API documentation before using the method.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cloud Configuration Error
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You ask AI how to configure an S3 bucket for static site hosting.&lt;/p&gt;

&lt;p&gt;AI generates a bucket policy that looks reasonable. The policy grants public read access. The syntax is valid. The explanation is confident.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The policy grants more access than necessary. It allows listing all objects in the bucket, not just reading specific objects. This is a security risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Is Dangerous:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The configuration works. The site loads. But the bucket is now exposing more information than intended. A security audit or a penetration test would flag this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verification Step:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Review the AWS documentation for least-privilege access patterns. Test the policy with the AWS Policy Simulator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Oversight
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You ask AI to build a simple authentication API.&lt;/p&gt;

&lt;p&gt;AI generates code that stores passwords and returns user objects.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code stores passwords in plaintext. The API returns password hashes to the client. There is no rate limiting on the login endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Is Dangerous:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The code works. Users can log in. But the security posture is broken. Passwords are compromised if the database is accessed. Password hashes are exposed to clients. The endpoint is vulnerable to brute-force attacks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verification Step:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Review authentication best practices. Use a library like bcrypt for password hashing. Do not return sensitive fields to the client. Add rate limiting.&lt;/p&gt;

&lt;h3&gt;
  
  
  Frontend Success, User Failure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You ask AI to build a form component.&lt;/p&gt;

&lt;p&gt;AI generates a React form with controlled inputs. The code compiles. The tests pass.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The form does not validate input before submission. The error messages do not display correctly. The form does not show a loading state during submission. The form is not keyboard-accessible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why This Is Dangerous:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The component technically works. But the user experience is broken. Users submit invalid data. Users do not see errors. Users do not know if their submission is processing. Users who rely on keyboard navigation cannot use the form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Verification Step:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Test the form in the browser. Try invalid inputs. Submit the form. Navigate with the keyboard. Check accessibility with browser dev tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Verification Workflow
&lt;/h2&gt;

&lt;p&gt;Verification should be a repeatable process.&lt;/p&gt;

&lt;p&gt;This is a practical workflow you can use immediately:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Read Everything
&lt;/h3&gt;

&lt;p&gt;Before running AI-generated code, read it.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method names you do not recognize&lt;/li&gt;
&lt;li&gt;Configuration values that seem unusual&lt;/li&gt;
&lt;li&gt;Comments that contradict the code&lt;/li&gt;
&lt;li&gt;Hardcoded values that should be configurable&lt;/li&gt;
&lt;li&gt;Missing error handling&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Verify Documentation
&lt;/h3&gt;

&lt;p&gt;If AI references an API, package, framework method, or configuration option, check the official documentation.&lt;/p&gt;

&lt;p&gt;Do not assume the AI is current.&lt;/p&gt;

&lt;p&gt;Compare:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Method signatures&lt;/li&gt;
&lt;li&gt;Parameter names&lt;/li&gt;
&lt;li&gt;Return types&lt;/li&gt;
&lt;li&gt;Deprecation notices&lt;/li&gt;
&lt;li&gt;Version compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Run Tests
&lt;/h3&gt;

&lt;p&gt;If the codebase has tests, run them.&lt;/p&gt;

&lt;p&gt;If AI generated new code, write tests for it.&lt;/p&gt;

&lt;p&gt;If AI claims code is correct, verify that tests actually fail when they should.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Check Logs
&lt;/h3&gt;

&lt;p&gt;Run the code and read the logs.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Warnings&lt;/li&gt;
&lt;li&gt;Deprecation notices&lt;/li&gt;
&lt;li&gt;Error messages&lt;/li&gt;
&lt;li&gt;Unexpected output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logs are more honest than explanations.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Validate Outputs
&lt;/h3&gt;

&lt;p&gt;Check that the code produces the expected result.&lt;/p&gt;

&lt;p&gt;Do not just check that it runs without errors. Check that the output is correct.&lt;/p&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Happy path&lt;/li&gt;
&lt;li&gt;Edge cases&lt;/li&gt;
&lt;li&gt;Error cases&lt;/li&gt;
&lt;li&gt;Null values&lt;/li&gt;
&lt;li&gt;Empty inputs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  6. Review Assumptions
&lt;/h3&gt;

&lt;p&gt;AI makes assumptions.&lt;/p&gt;

&lt;p&gt;Common assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The database is always available&lt;/li&gt;
&lt;li&gt;The API always responds in under one second&lt;/li&gt;
&lt;li&gt;The user is always authenticated&lt;/li&gt;
&lt;li&gt;The input is always valid&lt;/li&gt;
&lt;li&gt;The network is always reliable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;List the assumptions. Verify each one.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Browser Test User-Facing Changes
&lt;/h3&gt;

&lt;p&gt;If the change affects a UI, open it in a browser.&lt;/p&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigation&lt;/li&gt;
&lt;li&gt;Forms&lt;/li&gt;
&lt;li&gt;Buttons&lt;/li&gt;
&lt;li&gt;Error states&lt;/li&gt;
&lt;li&gt;Loading states&lt;/li&gt;
&lt;li&gt;Mobile viewport&lt;/li&gt;
&lt;li&gt;Keyboard navigation&lt;/li&gt;
&lt;li&gt;Screen reader compatibility&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  8. Ship Only After Verification
&lt;/h3&gt;

&lt;p&gt;Do not deploy code you have not verified.&lt;/p&gt;

&lt;p&gt;The deployment pipeline should include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automated tests&lt;/li&gt;
&lt;li&gt;Code review&lt;/li&gt;
&lt;li&gt;Staging environment validation&lt;/li&gt;
&lt;li&gt;Smoke tests in production&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Documentation Is The Source Of Truth
&lt;/h2&gt;

&lt;p&gt;Official documentation outranks AI.&lt;/p&gt;

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

&lt;p&gt;When AI suggests an API method, check the docs.&lt;/p&gt;

&lt;p&gt;When AI recommends a configuration, check the docs.&lt;/p&gt;

&lt;p&gt;When AI explains framework behavior, check the docs.&lt;/p&gt;

&lt;p&gt;AI training data has a cutoff date. Frameworks change. APIs evolve. Best practices shift.&lt;/p&gt;

&lt;p&gt;A method that worked in version 2.0 might not exist in version 3.0.&lt;/p&gt;

&lt;p&gt;A configuration option that was standard in 2023 might be deprecated in 2024.&lt;/p&gt;

&lt;p&gt;AI does not know this. The training data is static.&lt;/p&gt;

&lt;p&gt;Here is the verification pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI suggests a solution.&lt;/li&gt;
&lt;li&gt;You identify the specific method, package, or configuration involved.&lt;/li&gt;
&lt;li&gt;You search the official documentation for that method, package, or configuration.&lt;/li&gt;
&lt;li&gt;You compare the AI's version with the documented version.&lt;/li&gt;
&lt;li&gt;You use the documented version.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This takes time.&lt;/p&gt;

&lt;p&gt;It is worth it.&lt;/p&gt;

&lt;p&gt;One hour spent verifying documentation prevents days spent debugging production issues caused by outdated code.&lt;/p&gt;




&lt;h2&gt;
  
  
  Logs Are More Honest Than AI
&lt;/h2&gt;

&lt;p&gt;AI generates explanations.&lt;/p&gt;

&lt;p&gt;Logs report facts.&lt;/p&gt;

&lt;p&gt;When something breaks, trust the logs more than the explanation.&lt;/p&gt;

&lt;p&gt;This is a lesson from cloud operations, support workflows, and troubleshooting production systems.&lt;/p&gt;

&lt;p&gt;Logs tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What actually happened&lt;/li&gt;
&lt;li&gt;When it happened&lt;/li&gt;
&lt;li&gt;What error code was returned&lt;/li&gt;
&lt;li&gt;What parameters were passed&lt;/li&gt;
&lt;li&gt;What the system state was at the time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI tells you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What might have happened&lt;/li&gt;
&lt;li&gt;What could cause similar issues&lt;/li&gt;
&lt;li&gt;What the error message might mean&lt;/li&gt;
&lt;li&gt;What debugging steps might help&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logs are evidence. Explanations are guesses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Debugging an API Failure
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The Scenario:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An API call fails in production. You ask AI to explain the error message.&lt;/p&gt;

&lt;p&gt;AI responds with a confident explanation. It suggests three possible causes. It recommends debugging steps. The explanation is detailed and well-formatted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Better Approach:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Read the logs.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The exact error message&lt;/li&gt;
&lt;li&gt;The HTTP status code&lt;/li&gt;
&lt;li&gt;The request payload&lt;/li&gt;
&lt;li&gt;The response payload&lt;/li&gt;
&lt;li&gt;The timestamp&lt;/li&gt;
&lt;li&gt;The request ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once you have the facts, you can verify AI's explanation against the actual evidence.&lt;/p&gt;

&lt;p&gt;Often, the logs reveal the problem immediately. The API key was wrong. The request was malformed. The rate limit was exceeded. The timeout was too short.&lt;/p&gt;

&lt;p&gt;These are facts. They do not require interpretation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example: Monitoring Dashboard
&lt;/h3&gt;

&lt;p&gt;If your application has monitoring (CloudWatch, Datadog, New Relic, etc.), check the metrics before accepting AI's explanation.&lt;/p&gt;

&lt;p&gt;Metrics tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Latency&lt;/li&gt;
&lt;li&gt;Error rate&lt;/li&gt;
&lt;li&gt;Request count&lt;/li&gt;
&lt;li&gt;Resource usage&lt;/li&gt;
&lt;li&gt;Dependency health&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If AI suggests a performance issue is caused by a database query, check the database metrics first. If the query time is 10ms, the database is not the bottleneck.&lt;/p&gt;

&lt;p&gt;This is not anti-AI. This is pro-verification.&lt;/p&gt;

&lt;p&gt;AI is extremely useful for generating hypotheses. It can suggest possible causes, debugging steps, and solutions.&lt;/p&gt;

&lt;p&gt;But logs and metrics confirm which hypothesis is correct.&lt;/p&gt;




&lt;h2&gt;
  
  
  Browser Verification
&lt;/h2&gt;

&lt;p&gt;Successful compilation does not mean a successful application.&lt;/p&gt;

&lt;p&gt;This is especially true for frontend work.&lt;/p&gt;

&lt;p&gt;The TypeScript compiler might accept your code. The tests might pass. The build might succeed.&lt;/p&gt;

&lt;p&gt;But the user experience might be broken.&lt;/p&gt;

&lt;p&gt;Browser verification is non-negotiable for frontend changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  What To Check
&lt;/h3&gt;

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

&lt;ul&gt;
&lt;li&gt;Do all links work?&lt;/li&gt;
&lt;li&gt;Do navigation menus open and close correctly?&lt;/li&gt;
&lt;li&gt;Does the back button work as expected?&lt;/li&gt;
&lt;li&gt;Do route changes update the URL?&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;Do inputs accept the expected data types?&lt;/li&gt;
&lt;li&gt;Do validations trigger at the right time?&lt;/li&gt;
&lt;li&gt;Do error messages display correctly?&lt;/li&gt;
&lt;li&gt;Does the form submit successfully?&lt;/li&gt;
&lt;li&gt;Does the form show a loading state during submission?&lt;/li&gt;
&lt;li&gt;Does the form handle submission errors?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Mobile Responsiveness:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the layout work on small screens?&lt;/li&gt;
&lt;li&gt;Are buttons large enough to tap?&lt;/li&gt;
&lt;li&gt;Is text readable without zooming?&lt;/li&gt;
&lt;li&gt;Do modals and dropdowns work on mobile?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Error States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What happens if an API call fails?&lt;/li&gt;
&lt;li&gt;Does the UI show a meaningful error message?&lt;/li&gt;
&lt;li&gt;Can the user retry the action?&lt;/li&gt;
&lt;li&gt;Is the error reported to monitoring?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Loading States:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the UI show a loading indicator during async operations?&lt;/li&gt;
&lt;li&gt;Are loading states visually clear?&lt;/li&gt;
&lt;li&gt;Does the UI remain interactive during loading?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Accessibility Basics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can you navigate the UI with only a keyboard?&lt;/li&gt;
&lt;li&gt;Do form inputs have labels?&lt;/li&gt;
&lt;li&gt;Do images have alt text?&lt;/li&gt;
&lt;li&gt;Is color contrast sufficient?&lt;/li&gt;
&lt;li&gt;Do error messages work with screen readers?&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Browser Console
&lt;/h3&gt;

&lt;p&gt;Open the browser dev tools. Check the console.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript errors&lt;/li&gt;
&lt;li&gt;Warning messages&lt;/li&gt;
&lt;li&gt;Failed network requests&lt;/li&gt;
&lt;li&gt;Deprecation notices&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are facts. They tell you what is actually broken.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verification Checklist
&lt;/h2&gt;

&lt;p&gt;Use this checklist before deploying AI-generated code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Basic Validation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I read the entire AI-generated code&lt;/li&gt;
&lt;li&gt;[ ] I understand what the code does&lt;/li&gt;
&lt;li&gt;[ ] I ran the code locally&lt;/li&gt;
&lt;li&gt;[ ] The code runs without errors&lt;/li&gt;
&lt;li&gt;[ ] The code produces the expected output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Documentation Verification:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I checked the official documentation for APIs used&lt;/li&gt;
&lt;li&gt;[ ] I verified method names are correct&lt;/li&gt;
&lt;li&gt;[ ] I verified package names are correct&lt;/li&gt;
&lt;li&gt;[ ] I verified configuration options are correct&lt;/li&gt;
&lt;li&gt;[ ] I checked for deprecation notices&lt;/li&gt;
&lt;/ul&gt;

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

&lt;ul&gt;
&lt;li&gt;[ ] I wrote tests for the new code&lt;/li&gt;
&lt;li&gt;[ ] I ran existing tests&lt;/li&gt;
&lt;li&gt;[ ] All tests pass&lt;/li&gt;
&lt;li&gt;[ ] I tested edge cases&lt;/li&gt;
&lt;li&gt;[ ] I tested error cases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Logs and Monitoring:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I checked the logs after running the code&lt;/li&gt;
&lt;li&gt;[ ] I looked for warnings or deprecation notices&lt;/li&gt;
&lt;li&gt;[ ] I verified no unexpected errors appear in logs&lt;/li&gt;
&lt;li&gt;[ ] I confirmed monitoring dashboards show expected behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Review:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I reviewed the code for hardcoded secrets&lt;/li&gt;
&lt;li&gt;[ ] I verified authentication is required where needed&lt;/li&gt;
&lt;li&gt;[ ] I confirmed user input is validated&lt;/li&gt;
&lt;li&gt;[ ] I checked for overly permissive configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Frontend Verification (if applicable):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I tested the UI in a browser&lt;/li&gt;
&lt;li&gt;[ ] I tested on mobile viewport&lt;/li&gt;
&lt;li&gt;[ ] I tested form validation&lt;/li&gt;
&lt;li&gt;[ ] I tested error states&lt;/li&gt;
&lt;li&gt;[ ] I tested loading states&lt;/li&gt;
&lt;li&gt;[ ] I tested keyboard navigation&lt;/li&gt;
&lt;li&gt;[ ] I checked the browser console for errors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Deployment Readiness:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] I reviewed the code in a pull request&lt;/li&gt;
&lt;li&gt;[ ] I tested the code in a staging environment&lt;/li&gt;
&lt;li&gt;[ ] I verified rollback procedures exist&lt;/li&gt;
&lt;li&gt;[ ] I confirmed monitoring is in place&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This checklist should feel repetitive.&lt;/p&gt;

&lt;p&gt;That is the point.&lt;/p&gt;

&lt;p&gt;Verification is repetitive.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Cost Of False Confidence
&lt;/h2&gt;

&lt;p&gt;Verification feels slower.&lt;/p&gt;

&lt;p&gt;Reading documentation takes time. Writing tests takes time. Checking logs takes time. Testing in the browser takes time.&lt;/p&gt;

&lt;p&gt;It is tempting to skip these steps.&lt;/p&gt;

&lt;p&gt;AI gave you code. The code looks correct. Ship it.&lt;/p&gt;

&lt;p&gt;This is the trap.&lt;/p&gt;

&lt;p&gt;Skipping verification does not save time. It defers the cost.&lt;/p&gt;

&lt;p&gt;The real cost is paid later:&lt;/p&gt;

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

&lt;p&gt;The code breaks in production. You spend hours debugging. You trace the issue back to an incorrect API method AI suggested. You could have caught this with five minutes of documentation review.&lt;/p&gt;

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

&lt;p&gt;The feature works but does not meet requirements. The business logic is wrong. You rewrite the entire feature. You could have caught this with user acceptance testing before deployment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Production Issues:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application breaks for users. Support tickets increase. Engineers are pulled into incident response. Customers are impacted. You could have caught this with browser testing before release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Lost Trust:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your team starts questioning AI-generated code. Code review becomes adversarial. Deployments slow down. You could have avoided this by demonstrating that verification catches issues before they reach production.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Security Incidents:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A security researcher reports that your API exposes user data without authentication. You scramble to patch the issue. The vulnerability existed for weeks. You could have caught this with a basic security review.&lt;/p&gt;

&lt;p&gt;Verification is an investment.&lt;/p&gt;

&lt;p&gt;The return is fewer incidents, faster debugging, and higher confidence in deployments.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;AI is one of the most useful tools available to developers today.&lt;/p&gt;

&lt;p&gt;It accelerates generation. It explains complex concepts. It suggests solutions. It helps you learn new frameworks, languages, and tools.&lt;/p&gt;

&lt;p&gt;This guide is not anti-AI.&lt;/p&gt;

&lt;p&gt;This guide is pro-verification.&lt;/p&gt;

&lt;p&gt;The skill that separates productive AI-assisted development from expensive mistakes is not prompting.&lt;/p&gt;

&lt;p&gt;It is verification.&lt;/p&gt;

&lt;p&gt;Prompting gets you answers.&lt;/p&gt;

&lt;p&gt;Verification proves the answers are correct.&lt;/p&gt;

&lt;p&gt;Confidence is not correctness.&lt;/p&gt;

&lt;p&gt;A well-formatted, confidently written answer is still wrong if it references a deprecated API, uses an outdated pattern, or contains a security flaw.&lt;/p&gt;

&lt;p&gt;The most valuable skill in AI-assisted development is not writing better prompts.&lt;/p&gt;

&lt;p&gt;It is learning how to prove that the answer is correct.&lt;/p&gt;

&lt;p&gt;Verify the documentation. Run the code. Read the logs. Test the UI. Check the assumptions. Write the tests.&lt;/p&gt;

&lt;p&gt;Do the work.&lt;/p&gt;

&lt;p&gt;AI will help you move faster, but only if you verify what it produces.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Verification Workflow Summary:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read everything&lt;/li&gt;
&lt;li&gt;Verify documentation&lt;/li&gt;
&lt;li&gt;Run tests&lt;/li&gt;
&lt;li&gt;Check logs&lt;/li&gt;
&lt;li&gt;Validate outputs&lt;/li&gt;
&lt;li&gt;Review assumptions&lt;/li&gt;
&lt;li&gt;Browser test user-facing changes&lt;/li&gt;
&lt;li&gt;Ship only after verification&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The developers who succeed with AI are not the ones with the best prompts.&lt;/p&gt;

&lt;p&gt;They are the ones who verify everything.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>beginners</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>What 364 Applications, 187 Rejections, and Two Years Actually Looks Like</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Sat, 06 Jun 2026 03:46:43 +0000</pubDate>
      <link>https://dev.to/bradleymatera/what-364-applications-187-rejections-and-two-years-actually-looks-like-2554</link>
      <guid>https://dev.to/bradleymatera/what-364-applications-187-rejections-and-two-years-actually-looks-like-2554</guid>
      <description>&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%2Fk8svn6rditydpc2t260l.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%2Fk8svn6rditydpc2t260l.jpg" alt="Banner" width="800" height="450"&gt;&lt;/a&gt;&lt;br&gt;
The advice for breaking into tech is consistent.&lt;/p&gt;

&lt;p&gt;Get a degree or take a bootcamp. Build projects. Earn certifications. Get an internship. Make a portfolio. Use GitHub. Network. Apply broadly. Try support roles, not just developer positions. Write tailored resumes. Write cover letters. Follow up. Keep learning.&lt;/p&gt;

&lt;p&gt;I followed that checklist.&lt;/p&gt;

&lt;p&gt;Full Sail Web Development degree with a 3.8 GPA. AWS Cloud Support Associate internship. AWS Solutions Architect Associate and AWS AI Practitioner certifications. Portfolio site with public GitHub projects and a technical blog. LinkedIn network of about 206 connections, mostly developers, engineers, and recruiters. Tailored resumes and cover letters. Applications across software development, cloud engineering, DevOps, infrastructure, QA, technical support, Oracle/ERP analyst work, AI automation, and local IT fallback roles. Direct outreach to local employers. Recruiter contacts. Freelance attempts.&lt;/p&gt;

&lt;p&gt;What mattered to me at the time was this: I had the degree. I had the AWS internship. I had the certs. I had the portfolio, GitHub, technical blog, LinkedIn network, tailored resumes, cover letters, direct outreach, recruiter contacts, freelance attempts, and applications across multiple lanes.&lt;/p&gt;

&lt;p&gt;The outcome was not stable employment.&lt;/p&gt;

&lt;p&gt;This is not a post about companies being unfair or the tech industry being impossible to enter. What I want to talk about is the gap between the advice given to career changers and the reality of the current entry-level market—at least the one I encountered from mid-2024 through mid-2026.&lt;/p&gt;

&lt;p&gt;I kept thinking maybe the next resume version would be the one. Maybe the next project would make the difference. Maybe support roles would be more realistic. Maybe local companies would be different. After enough cycles of that, I started tracking it because I needed to know if I was imagining the pattern.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Standard Advice I Kept Hearing
&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%2Fxpq6xkx3jtm06iljl4fc.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%2Fxpq6xkx3jtm06iljl4fc.png" alt="Image15" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
"Have you tried applying to more jobs?"&lt;/p&gt;

&lt;p&gt;"Are you networking?"&lt;/p&gt;

&lt;p&gt;"Maybe your resume needs work."&lt;/p&gt;

&lt;p&gt;"Did you build projects?"&lt;/p&gt;

&lt;p&gt;"Have you considered support roles instead of just developer positions?"&lt;/p&gt;

&lt;p&gt;"Try local companies, not just remote roles."&lt;/p&gt;

&lt;p&gt;"Get certifications."&lt;/p&gt;

&lt;p&gt;"Do an internship if you can."&lt;/p&gt;

&lt;p&gt;None of this advice was wrong. It just assumed that following it would eventually work if I kept adjusting and applying.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Actually Did
&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%2Fm5tftoy9d8pc8i48y6f3.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%2Fm5tftoy9d8pc8i48y6f3.png" alt="Image1" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
I am not claiming I did everything perfectly. I am claiming I did the work.&lt;/p&gt;

&lt;p&gt;Graduated from Full Sail University's Web Development program in October 2025 with a 3.8 GPA. Completed an AWS Cloud Support Associate internship. Earned AWS Solutions Architect Associate and AWS AI Practitioner certifications. Built a portfolio site, maintained public GitHub repositories, and kept a technical blog. Networked through LinkedIn, stayed connected with my AWS internship cohort, and participated in a regular Friday night tech discussion group with Full Sail peers that often ran around six hours talking through projects, job searching, and software engineering.&lt;/p&gt;

&lt;p&gt;Eventually, I started tracking it. Not because I wanted a spreadsheet for its own sake, but because I needed to know whether I was imagining the pattern. My Gmail searches show 364 application confirmations, 320 sent job-search emails, and 187 rejections over roughly two years. LinkedIn shows 87 tracked applications. Epic Systems alone shows 16 applications from July 2024 through June 2026. I applied across software development, cloud engineering, DevOps, infrastructure, QA, technical support, Oracle and ERP analyst work, AI automation, data roles, and local IT fallback positions. I reached out directly to local employers, contacted recruiters and staffing agencies, and attempted freelance work and paid writing collaborations.&lt;/p&gt;

&lt;p&gt;I had followed the checklist as honestly as I knew how. The outcome was not stable employment.&lt;/p&gt;

&lt;h2&gt;
  
  
  I Was Building While Applying
&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%2Fcmmie180you2n8jc95rt.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%2Fcmmie180you2n8jc95rt.png" alt="Image2" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
"Build projects" is one of the main pieces of advice given to juniors. I did build projects, and I tried to document them in the way people say hiring teams want: problem, solution, role, stack, repo, live demo, and lessons learned.&lt;/p&gt;

&lt;p&gt;My portfolio was not a one-page resume site. It became a working public hub for my job search and technical proof. The portfolio itself became one of the projects. It had a frontend, backend functionality, GitHub-backed iteration, deployment workflow, role pages, project case studies, a blog, contributions, and store/Stripe-related work. I kept thinking maybe this would be the proof that made the difference—that the site itself showed I could build, deploy, maintain, and iterate on a public web presence while applying.&lt;/p&gt;

&lt;p&gt;The blog acted as field notes and project retrospectives—35 articles covering web development, career, DevOps, AWS, AI, Docker, APIs, testing, and debugging. The Projects page organized entries by problem, solution, role, tech stack, and proof. Car-Match showed full-stack work with React, Express, MongoDB, and JWT. The Interactive Pokédex demonstrated Next.js static generation with PokéAPI integration. Convo-AI was a local voice assistant built with Python, FastAPI, Whisper, and Ollama. CheeseMath showed testing patterns with Jest. CIRIS AI contributions showed open-source documentation and Docker Compose work. EthicsFrontEndDemo was a secrets-management tutorial.&lt;/p&gt;

&lt;p&gt;The Roles page was intentionally transparent. I labeled the pages as aspirational student case studies and said directly that I had not been paid in those roles yet, that I used AI and tutor support, and that I still needed mentorship in areas like algorithms and large-scale operations. The Contributions page documented unpaid student-level work: README updates, contributor forms, volunteer runbooks, and Tech Talk Club involvement at Full Sail.&lt;/p&gt;

&lt;p&gt;What mattered was this: I was not only applying. I was building, documenting, learning publicly, and trying to make the work verifiable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Noticed in the Tracker
&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%2F81ob9lomkutlddpos7zt.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%2F81ob9lomkutlddpos7zt.png" alt="Image3" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
Once I stopped looking at each rejection as a separate event, the pattern became harder to ignore.&lt;/p&gt;

&lt;p&gt;At first, I thought each rejection was just one rejection. After enough of them, I started looking at the pattern instead of the individual emails.&lt;/p&gt;

&lt;p&gt;The tracker does not just show volume. It shows a pattern: applying, getting rejected, retargeting, following up, trying local options, and widening the search.&lt;/p&gt;

&lt;p&gt;The rejections included phrasing like "not moving forward," "other candidates," or "position filled." Allstate rejected me for an entry-level full-stack role. DailyPay declined a junior web developer application. FORM moved forward with other candidates for a software support analyst position. I was not locked into one job title—I was trying developer roles, junior roles, and support-adjacent roles.&lt;/p&gt;

&lt;p&gt;It was not only job boards either. Slitherine, Rockford IT, Shady Oak Dental, DoIT Illinois, and TreeTop Staffing show direct outreach beyond portals. They also show I tried developer roles, local IT, state IT, staffing channels, and non-tech fallback work. "Apply directly" and "try local companies" were part of the standard advice, and I was doing it.&lt;/p&gt;

&lt;p&gt;The tracker spanned software engineering, cloud, DevOps, support, QA, AI, data, and customer success roles across multiple platforms. What frustrated me was not one rejection. It was that "just apply more" does not explain what happened. I was already applying, adjusting, following up, and widening the search.&lt;/p&gt;

&lt;h2&gt;
  
  
  Epic Systems: A Case Study
&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%2F5ew3zxcmo42k9t07ha2o.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%2F5ew3zxcmo42k9t07ha2o.png" alt="Image4" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
Epic is the strongest single-company example because it shows repeated, targeted effort over time. My Epic portal shows 16 applications submitted between July 2024 and June 2026 across infrastructure, systems administration, software development, technical support, UX design, and Windows engineering. Four separate applications went to Infrastructure Engineer roles. Five went to Technical Solutions Engineer. Two targeted Junior Systems Administrator positions. Two aimed at Software Developer roles. The rest spread across Infrastructure as Code Engineer, User Experience Designer, and Windows Engineer.&lt;/p&gt;

&lt;p&gt;All Verona, Wisconsin. All onsite or hybrid. My Epic profile showed multiple uploaded resume versions tailored to cloud, infrastructure, software, and technical support paths. This was not one application and one rejection. This was sustained retargeting with one employer who was actively hiring in my region.&lt;/p&gt;

&lt;p&gt;This is not me saying Epic did anything wrong. I am using Epic as the clearest example because their portal made the pattern visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Career Lanes I Tried
&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%2F26g17cmwtrjjujzrt55m.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%2F26g17cmwtrjjujzrt55m.png" alt="Image5" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
People always say "don't just apply to one type of job." I did not. I tried seven lanes: software development, cloud and infrastructure, support engineering, QA and testing, analyst and ERP work, AI and data roles, and local fallback positions. Each lane had actual applications or tailored materials behind it.&lt;/p&gt;

&lt;p&gt;Backend roles at WTS Paradigm. Full-stack roles at Yahara Software. Developer tooling at Netflix. Cloud engineering using my AWS internship experience with applications to Epic Infrastructure Engineer and Canonical Cloud Support Engineer. Support roles because the advice said support is a good entry point. QA roles at Collins Aerospace. Oracle and ERP analyst positions as a potential entry point. AI roles because I had experience with local AI hosting and LLM workflows. Local employers where I emphasized onsite availability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Networking and Direct Outreach
&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%2F6bj9mg2qgevy9z9bdxoc.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%2F6bj9mg2qgevy9z9bdxoc.png" alt="Image6" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
People always say "network more" and "don't just rely on job boards." I was doing both. My LinkedIn network included approximately 206 connections, mostly developers, engineers, recruiters, and tech workers. I stayed in contact with people from my AWS internship cohort. Since around August 2024, I participated in a regular Friday night tech discussion group with Full Sail peers that often lasted around six hours talking through projects, job searching, and software engineering topics.&lt;/p&gt;

&lt;p&gt;Those nights were not formal networking events. They were usually a few of us talking for hours about projects, job searching, software engineering, tools, and whatever we were stuck on that week.&lt;/p&gt;

&lt;p&gt;Beyond that, I reached out directly to local employers. I emailed Rockford IT for entry-level IT work, followed up with Shady Oak Dental for a non-tech fallback role, contacted DoIT Illinois after a virtual job fair, sent materials to Slitherine for junior developer opportunities, and reached out to TreeTop Staffing. I attempted freelance work on Upwork and explored paid technical writing collaborations. Looking back, I was not just applying cold through portals. I was networking, reaching out directly, and trying multiple income paths.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Think This Does and Does Not Prove
&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%2F80eelqvkh0jwbu5yj9t2.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%2F80eelqvkh0jwbu5yj9t2.png" alt="Image7" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
This is not a benchmark. This is one person's experience over roughly two years of active job searching while completing a degree, internship, certifications, and projects. I cannot claim this represents everyone's experience, that the job market was uniquely hostile to me, that I did everything perfectly, or that every rejected application was flawless.&lt;/p&gt;

&lt;p&gt;What I can claim is this: I followed the advice as best as I could, tracked what happened, and the result made me question whether the path was ever as reliable as people made it sound. The tracker shows repeated applications, rejections, retargeting, role-specific materials, public proof of work, education, certifications, networking, and continued effort after rejection.&lt;/p&gt;

&lt;p&gt;Around that point, I started wondering: was the self-directed education and portfolio path enough for the entry-level market I was actually applying into? Maybe I am wrong, but after two years of sustained effort, I do not think lack of effort explains what happened.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Would Tell Someone Starting This Path Now
&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%2Fjacc52lyovwg94n609qa.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%2Fjacc52lyovwg94n609qa.png" alt="Image9" width="512" height="256"&gt;&lt;/a&gt;&lt;br&gt;
I would not tell someone to give up. I would tell them to be more careful than I was at the beginning.&lt;/p&gt;

&lt;p&gt;Verify the local job market for entry-level roles before starting. Identify realistic entry points beyond "junior developer." Plan for the possibility that a hundred applications may not be enough. Consider whether you can sustain this effort financially for one to three years. Build relationships with people already employed in the roles you want. Ask whether formal programs with employer pipelines are available. Test your materials and approach with people who have hired successfully. Prepare for the psychological cost of sustained rejection.&lt;/p&gt;

&lt;p&gt;The portfolio matters. The projects matter. The certifications matter. The education matters. The networking matters. They were not sufficient by themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Takeaway
&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%2Fa13prehwadlnkgauxf74.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%2Fa13prehwadlnkgauxf74.png" alt="Image10" width="512" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;This post documents my job search from mid-2024 through mid-2026. Evidence includes Gmail application confirmations, rejection emails, sent outreach messages, LinkedIn application tracker screenshots, ZipRecruiter application history, Epic Systems portal screenshots, Google Drive cover letter documents, uploaded resume versions, and project repositories. Numbers are based on search queries and visible records. I am not claiming these numbers are perfect. I am claiming they are real.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;I proved I could learn. I proved I could build. I proved I could document. I proved I could troubleshoot. I did not prove I could turn that into stable employment.&lt;/p&gt;

&lt;p&gt;That is the actual result.&lt;/p&gt;

&lt;p&gt;I did not start tracking this because I wanted to prove everyone wrong. I started tracking it because I was starting to wonder if I was the problem, and I needed something more real than feelings to look at. After two years of applications, projects, certifications, an internship, networking, direct outreach, and retargeting, I do not think the honest answer is "just try harder." I did try harder.&lt;/p&gt;

&lt;p&gt;Maybe the better question is whether career changers and juniors need more than the standard checklist. Maybe they need employer pipelines, realistic labor-market guidance, mentorship, and a clearer route to companies that actually hire from self-directed portfolios.&lt;/p&gt;

&lt;p&gt;I am not completely comfortable saying the path was the whole problem, but after looking at the tracker, I do not think "try harder" explains it either.&lt;/p&gt;

</description>
      <category>career</category>
      <category>hiring</category>
      <category>whoishiring</category>
      <category>discuss</category>
    </item>
    <item>
      <title>The Developer Pay Paradox: Are Junior Devs, Staff Engineers and Most Developers Over- or Under-paid?</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Sun, 10 May 2026 00:11:39 +0000</pubDate>
      <link>https://dev.to/bradleymatera/the-developer-pay-paradox-are-junior-devs-staff-engineers-and-most-developers-over-or-under-paid-oid</link>
      <guid>https://dev.to/bradleymatera/the-developer-pay-paradox-are-junior-devs-staff-engineers-and-most-developers-over-or-under-paid-oid</guid>
      <description>&lt;p&gt;The software salary debate usually turns into two groups yelling past each other. One side sees a junior developer making $90k or $100k and says tech is overpaid, while the other side sees a staff engineer keeping a giant system alive and says developers are underpaid compared to the money they help companies make. Both sides can be right depending on what kind of developer they are talking about, but the conversation usually falls apart because people use one job title to describe a bunch of completely different jobs.&lt;/p&gt;

&lt;p&gt;A junior dev building admin screens, a mid-level dev fixing production bugs, a staff engineer designing systems across teams, and an AI engineer working near model infrastructure are all technically “developers,” but they are not living in the same labor market. Some of that work is closer to skilled trade work with a keyboard, some of it is business automation work, some of it is infrastructure work, and some of it is high-scale technical decision-making where one bad call can cost a company a lot of money.&lt;/p&gt;

&lt;p&gt;I also do not like when developers act like software is the only hard work that exists. I have been a roofer, I was a medic in the Army, I worked private security, and I have done warehouse-style work loading roofing materials onto job sites, so it is hard for me to listen to someone act like fixing a React bug is automatically harder than climbing a roof, treating people under pressure, standing a post all night, or throwing heavy material around in bad weather for less than $20 an hour.&lt;/p&gt;

&lt;p&gt;At the same time, I do not like fake arguments that pretend software work is easy just because it is not physically brutal. A job can be easier on the body and still be valuable to a company, because the company is not paying based on how much your back hurts. The company is paying based on leverage, replacement cost, scalability, risk, and how close the work sits to money.&lt;/p&gt;

&lt;p&gt;That is the uncomfortable part. A junior developer can do work that looks simple, like fixing a form or wiring an API call, and still get paid more than someone doing harder physical work. That does not mean the junior developer is tougher or more useful to society. It means software sits inside a business model where one small piece of work can be reused, deployed, copied, and sold again and again.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;The Real Question&lt;/li&gt;
&lt;li&gt;Why I’m Comparing These Jobs At All&lt;/li&gt;
&lt;li&gt;The Pay Numbers That Start The Argument&lt;/li&gt;
&lt;li&gt;Salary Comparison Graphic&lt;/li&gt;
&lt;li&gt;Why A Junior Dev Can Make More Than People Doing Harder Work&lt;/li&gt;
&lt;li&gt;Roofing Compared To Software Development&lt;/li&gt;
&lt;li&gt;Army Medic Work Compared To Software Development&lt;/li&gt;
&lt;li&gt;Private Security Compared To Software Development&lt;/li&gt;
&lt;li&gt;Warehouse And Manual Labor Compared To Software Development&lt;/li&gt;
&lt;li&gt;Teaching Compared To Software Development&lt;/li&gt;
&lt;li&gt;Do Most Developers Even Do DSA?&lt;/li&gt;
&lt;li&gt;Is Web Development Skilled Trade Work With A Keyboard?&lt;/li&gt;
&lt;li&gt;Are Junior Developers Overpaid?&lt;/li&gt;
&lt;li&gt;Are Mid-Level Developers Fairly Paid?&lt;/li&gt;
&lt;li&gt;Are Staff Engineers Overpaid?&lt;/li&gt;
&lt;li&gt;Where AI Changes The Pay Conversation&lt;/li&gt;
&lt;li&gt;The Three Different Developer Economies&lt;/li&gt;
&lt;li&gt;The Honest Answer&lt;/li&gt;
&lt;li&gt;Sources&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Real Question &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The real question is not “are developers overpaid?” because that question is too broad to be useful. A better question is, “overpaid compared to what, for what type of work, at what company, and under what business model?” Without those details, the argument turns into people comparing a junior web developer at a small company to a staff engineer at Google like those are the same thing.&lt;/p&gt;

&lt;p&gt;If we compare developers to the national median worker, developers are paid a lot. If we compare developers to roofers, EMTs, paramedics, security guards, warehouse workers, construction laborers, or teachers, software pay can look insane, especially when the software job is remote and the other job is physically dangerous, emotionally heavy, or socially necessary.&lt;/p&gt;

&lt;p&gt;If we compare developers to the money their work can generate, the answer changes. A developer working on a SaaS product, payment system, cloud platform, AI tool, ad system, internal dashboard, or automation flow can touch systems that scale to thousands, millions, or even billions of interactions. That kind of scale is why the salary conversation gets weird fast.&lt;/p&gt;

&lt;p&gt;That is the part people miss when they only compare effort. The labor market does not pay only based on pain, danger, stress, intelligence, or how noble the job is. It mostly pays based on leverage, scarcity, replacement cost, company margins, and how close the work is to revenue.&lt;/p&gt;

&lt;p&gt;This is why the argument feels morally wrong but economically explainable. A medic can do more socially important work than a junior web developer and still make less, because medical labor is often trapped inside public budgets, insurance structures, military pay tables, local contracts, or staffing models. Software work, especially inside product companies, can sit closer to high-margin revenue.&lt;/p&gt;

&lt;p&gt;That does not mean the market is fair. It means the market is not built around fairness. It is built around money, risk, supply, demand, and who has the power to negotiate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why I’m Comparing These Jobs At All &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;I am not comparing software to roofing, Army medic work, private security, warehouse-style labor, and case management because I think they are all the same job. I am comparing them because I have lived enough of those worlds to know that “hard work” and “high pay” are not the same thing, and pretending they are is one of the reasons the developer pay debate gets so fake.&lt;/p&gt;

&lt;p&gt;My own work history did not start in tech. I served as a Healthcare Specialist in the Army from 2011 to 2014, including training environments and combat-zone medical support, where the work involved triage, emergency response, medical readiness, supplies, physical exams, medication administration, and staying calm when things were unpredictable. After that, I worked roofing and roofing supply roles from 2017 to 2020, including general contracting, tear-off, shingle work, site prep, cleanup, and roof loading heavy materials onto job sites in bad weather and under tight schedules. I also worked private security, and later worked in case management with Veterans Court, Drug Court, and Mental Health Court, where documentation, communication, crisis intervention, and keeping people on track mattered every day.&lt;/p&gt;

&lt;p&gt;I also worked at Mason County Kitten Rescue from 2020 to 2022, which was not high-paying tech work, but it taught organization, intake, care routines, training volunteers, watching for signs of distress, and doing important daily work that does not become more profitable just because it matters. Then I started moving seriously into software, contributing as a Junior Frontend Developer with CIRIS Ethical AI in 2024 by running the project locally, improving onboarding and setup documentation, adding small code changes, improving token-verification logging, fixing lint issues, improving error messages, and opening GitHub Issues to keep larger ideas tracked. In 2025, I completed an on-site AWS Cloud Support Engineer internship in Seattle, where the work included guided support rotations in training environments with no customer data, guided Juniper and Junos troubleshooting labs in Jupyter Notebooks, and a capstone serverless metadata extraction workflow using Lambda, DynamoDB, S3, and an accessible frontend deployed on AWS Amplify.&lt;/p&gt;

&lt;p&gt;The reason that timeline matters is because none of the earlier physical or service-heavy jobs paid me over $20 an hour at the time, but they still demanded discipline, pressure management, communication, safety, documentation, and the ability to keep moving when things were not comfortable. Then tech came along and suddenly the pay ceiling was completely different, not because the work became morally superior, but because the business model changed. Software is not automatically harder than those jobs, but it can be attached to systems where the output scales in a way those jobs usually cannot.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Pay Numbers That Start The Argument &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The U.S. Bureau of Labor Statistics listed the median annual wage for software developers at &lt;strong&gt;$133,080&lt;/strong&gt; in May 2024. The same BLS page says the lowest 10 percent earned less than &lt;strong&gt;$79,850&lt;/strong&gt;, while the highest 10 percent earned more than &lt;strong&gt;$211,450&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That number is already high compared to normal American wages. BLS listed the median annual wage for all workers at &lt;strong&gt;$49,500&lt;/strong&gt; in May 2024, which means the median software developer made about 2.7 times the median worker.&lt;/p&gt;

&lt;p&gt;The comparison gets uncomfortable when software is placed next to jobs that are clearly hard, risky, or socially important. BLS listed roofers at &lt;strong&gt;$50,970&lt;/strong&gt;, EMTs at &lt;strong&gt;$41,340&lt;/strong&gt;, paramedics at &lt;strong&gt;$58,410&lt;/strong&gt;, security guards at &lt;strong&gt;$38,370&lt;/strong&gt;, construction laborers and helpers at &lt;strong&gt;$46,050&lt;/strong&gt;, hand laborers and material movers at &lt;strong&gt;$37,680&lt;/strong&gt;, and high school teachers at &lt;strong&gt;$64,580&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Those numbers explain why people outside tech get annoyed when developers complain about pay. A junior developer can make more than a roofer, medic, security guard, teacher, construction laborer, or warehouse worker before that junior developer is even fully useful to the team.&lt;/p&gt;

&lt;p&gt;Levels.fyi shows even larger numbers because it tracks total compensation, not just base salary. In May 2026, Levels.fyi listed U.S. software engineer median total compensation around &lt;strong&gt;$191,000&lt;/strong&gt;, with the 25th percentile around &lt;strong&gt;$135,000&lt;/strong&gt;, the 75th percentile around &lt;strong&gt;$276,100&lt;/strong&gt;, and the 90th percentile around &lt;strong&gt;$380,000&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;BuiltIn shows a lower junior number than Levels.fyi, which makes sense because BuiltIn pulls from a broader mix of companies. BuiltIn lists U.S. junior software engineer average base salary around &lt;strong&gt;$89,847&lt;/strong&gt;, average additional cash compensation around &lt;strong&gt;$10,590&lt;/strong&gt;, and average total compensation around &lt;strong&gt;$100,437&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Role Or Group&lt;/th&gt;
&lt;th&gt;Recent Pay Data&lt;/th&gt;
&lt;th&gt;Why It Matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;All U.S. workers&lt;/td&gt;
&lt;td&gt;$49,500 median wage&lt;/td&gt;
&lt;td&gt;This is the broad baseline for the whole labor market.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Roofers&lt;/td&gt;
&lt;td&gt;$50,970 median wage&lt;/td&gt;
&lt;td&gt;This is skilled, physical, dangerous work, but the pay is close to the national median.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;EMTs&lt;/td&gt;
&lt;td&gt;$41,340 median wage&lt;/td&gt;
&lt;td&gt;This is life-safety work, but the labor market pays it far below software.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paramedics&lt;/td&gt;
&lt;td&gt;$58,410 median wage&lt;/td&gt;
&lt;td&gt;This pays more than EMT work, but still far below the median developer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security guards&lt;/td&gt;
&lt;td&gt;$38,370 median wage&lt;/td&gt;
&lt;td&gt;This is common risk-bearing work, but it pays far below software.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Construction laborers and helpers&lt;/td&gt;
&lt;td&gt;$46,050 median wage&lt;/td&gt;
&lt;td&gt;This is hard physical work that often pays less than many junior tech jobs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hand laborers and material movers&lt;/td&gt;
&lt;td&gt;$37,680 median wage&lt;/td&gt;
&lt;td&gt;This covers a lot of warehouse-style physical labor and shows how low that work often pays.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High school teachers&lt;/td&gt;
&lt;td&gt;$64,580 median wage&lt;/td&gt;
&lt;td&gt;This requires education, responsibility, and social value, but it is still below junior software pay in many cases.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Software developers&lt;/td&gt;
&lt;td&gt;$133,080 median wage&lt;/td&gt;
&lt;td&gt;This is where the comparison starts looking unfair to people outside tech.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;U.S. software engineers on Levels.fyi&lt;/td&gt;
&lt;td&gt;$191,000 median total comp&lt;/td&gt;
&lt;td&gt;This includes bonus and equity, so it shows the higher end of tech more clearly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Junior software engineers on BuiltIn&lt;/td&gt;
&lt;td&gt;$100,437 average total comp&lt;/td&gt;
&lt;td&gt;This is one reason people ask whether junior developers are overpaid.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The table is not saying developers have easy lives or that every developer is rich. It is showing why the discussion gets tense, because the pay gap is real and the explanation is not as simple as “developers are smarter” or “developers work harder.”&lt;/p&gt;

&lt;p&gt;The market is not judging pay by soreness, danger, or public good. It is judging pay by how much money the company has, how scalable the output is, how hard the role is to fill, and how expensive it is when the work is done badly.&lt;/p&gt;




&lt;h2&gt;
  
  
  Salary Comparison Graphic &lt;a&gt;&lt;/a&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%2Fq2c5nt9jndbfdinm30ys.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%2Fq2c5nt9jndbfdinm30ys.jpg" alt="Salary comparison chart showing median annual pay for security guards, warehouse-style material movers, EMTs, construction laborers, all U.S. workers, roofers, paramedics, teachers, junior software engineers, software developers, and Levels.fyi software engineers" width="800" height="368"&gt;&lt;/a&gt;&lt;/p&gt;

A salary comparison using recent BLS wage data, BuiltIn junior software engineer compensation, and Levels.fyi software engineer total compensation. The point is not that software is always harder. The point is that software sits closer to scalable business leverage, which changes how companies pay for the work.







&lt;h2&gt;
  
  
  Why A Junior Dev Can Make More Than People Doing Harder Work &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;This is the question people are really asking. Why is a junior developer who barely knows the codebase getting paid more than somebody climbing roofs, treating casualties, standing security posts, moving freight, or managing a classroom?&lt;/p&gt;

&lt;p&gt;The answer is not that junior devs are tougher than roofers, medics, teachers, or security guards. A junior dev sitting at a desk with a laptop is not taking the same physical beating as a roofer, and they are not carrying the same kind of immediate life-and-death pressure as a medic.&lt;/p&gt;

&lt;p&gt;The answer is also not that every junior developer is doing genius-level computer science all day. Most junior developers are not writing compilers, designing databases, or inventing new algorithms. Most are fixing bugs, building components, writing API calls, updating forms, handling validation, reading existing code, asking questions, and trying not to break the build.&lt;/p&gt;

&lt;p&gt;The reason junior developers can still get paid more is leverage. A junior dev working on the right product can ship a small feature that thousands of customers touch, while a roofer can only roof the house, building, or section physically in front of them.&lt;/p&gt;

&lt;p&gt;That does not make the roofer less skilled, and it does not make the medic less important. It means software output can be copied, deployed, reused, sold, and scaled in a way physical labor usually cannot.&lt;/p&gt;

&lt;p&gt;A roofer finishes a roof and that roof exists in one place. A developer finishes a login flow, billing screen, internal automation, or API endpoint, and that work might run all day for every user the company has.&lt;/p&gt;

&lt;p&gt;A medic treats the patient in front of them, and that work matters in a direct human way. A developer builds a system that might remove manual steps for a whole department, process thousands of payments, or prevent support tickets before they exist.&lt;/p&gt;

&lt;p&gt;A security guard protects a site, handles access, watches patterns, and responds to incidents in one location. A developer who builds access controls, audit logs, or monitoring systems might affect every user and every employee at the company.&lt;/p&gt;

&lt;p&gt;That is why software salaries feel disconnected from effort. The pay is not really for typing code. The pay is for building and maintaining systems that can scale past one person’s physical output.&lt;/p&gt;




&lt;h2&gt;
  
  
  Roofing Compared To Software Development &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Roofing is one of the easiest jobs for people to underestimate because the final product looks simple. A roof keeps water out, but anyone who has actually done the work knows that a roof is only simple when you ignore everything that makes it fail.&lt;/p&gt;

&lt;p&gt;When I think about roofing, there are about 10 things you have to actually learn before you are useful and safe. You need to understand tear-off, decking, underlayment, flashing, shingles, fasteners, ventilation, valleys, measurements, and job-site safety.&lt;/p&gt;

&lt;p&gt;Tear-off is not just ripping old material off the roof. It is removing layers without destroying the deck, managing debris, watching for rot, keeping the site clean enough to work, and not creating a bigger problem before the new material even goes on.&lt;/p&gt;

&lt;p&gt;Decking matters because the roof is only as good as what it is attached to. In software, this is like discovering the data model, old architecture, or legacy service is rotten underneath the feature request.&lt;/p&gt;

&lt;p&gt;Underlayment, ice barrier, and water protection are the hidden layers most homeowners never think about. In software, those are like validation, auth checks, error handling, logging, and safe defaults, because nobody praises them when they work but everybody notices when they fail.&lt;/p&gt;

&lt;p&gt;Flashing is where a lot of bad roofs lose. In software, the equivalent is integrations, permission boundaries, third-party APIs, weird browser behavior, and all the places where one clean system meets another messy system.&lt;/p&gt;

&lt;p&gt;Shingles look easy from the ground, but alignment, overlap, nailing pattern, starter strips, and sequence all matter. In software, that is the repeatable pattern work, because a component, endpoint, or service should fit the system instead of being random every time.&lt;/p&gt;

&lt;p&gt;Fasteners matter because using the wrong nail, wrong placement, or wrong pressure creates future failure. In code, that is like using the wrong dependency, weak typing, fragile state management, a bad query, or a shortcut that only works until the system changes.&lt;/p&gt;

&lt;p&gt;Ventilation is one of those things that makes a roof fail slowly. In software, performance, caching, queues, background jobs, and infrastructure limits are the same kind of hidden system health work.&lt;/p&gt;

&lt;p&gt;Valleys, edges, vents, chimneys, and walls are where the easy middle stops being easy. In software, the happy path is usually simple, but the edge cases, weird inputs, expired sessions, duplicate requests, broken permissions, and production-only bugs are where the real work shows up.&lt;/p&gt;

&lt;p&gt;Measurement and material planning matter because waste costs money and bad estimates kill jobs. In software, bad estimates create missed deadlines, half-built features, rushed testing, and pressure that usually lands on the people doing the work.&lt;/p&gt;

&lt;p&gt;Safety matters because roofing can hurt or kill you fast. Software usually will not do that to your body, but it can hurt customers, leak data, break billing, stop operations, or create business damage if the system is important enough.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Roofing Work&lt;/th&gt;
&lt;th&gt;Software Equivalent&lt;/th&gt;
&lt;th&gt;Why The Comparison Makes Sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tear off the old roof without damaging the deck&lt;/td&gt;
&lt;td&gt;Refactor old code without breaking production&lt;/td&gt;
&lt;td&gt;Both jobs start by removing bad or outdated layers carefully.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Inspect problem areas before quoting the job&lt;/td&gt;
&lt;td&gt;Read requirements, logs, errors, and existing code before coding&lt;/td&gt;
&lt;td&gt;Both jobs punish people who start swinging before understanding the problem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Measure the roof and calculate material&lt;/td&gt;
&lt;td&gt;Scope the feature, data model, and implementation work&lt;/td&gt;
&lt;td&gt;Both jobs need estimating, waste control, and planning before execution.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replace rotten plywood or damaged joists&lt;/td&gt;
&lt;td&gt;Fix bad architecture, bad data, or broken dependencies&lt;/td&gt;
&lt;td&gt;Both jobs reveal hidden problems once the surface layer comes off.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install underlayment and water protection&lt;/td&gt;
&lt;td&gt;Add validation, auth, error handling, and security checks&lt;/td&gt;
&lt;td&gt;Both jobs need invisible protection that the customer may never notice until it fails.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Flash chimneys, walls, valleys, and vents&lt;/td&gt;
&lt;td&gt;Handle edge cases around integrations, permissions, and weird states&lt;/td&gt;
&lt;td&gt;Both jobs usually fail at the edges, not in the big flat middle.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Lay shingles with proper overlap and alignment&lt;/td&gt;
&lt;td&gt;Build UI and API flows with consistent patterns&lt;/td&gt;
&lt;td&gt;Both jobs need repeatable patterns, not random improvisation every few feet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cut materials around vents, walls, and valleys&lt;/td&gt;
&lt;td&gt;Adapt code around browser quirks, API limits, and product exceptions&lt;/td&gt;
&lt;td&gt;Both jobs require custom fitting while still following a system.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Install ventilation correctly&lt;/td&gt;
&lt;td&gt;Design performance, caching, and operational flow&lt;/td&gt;
&lt;td&gt;Both jobs can look fine at first and fail later if system flow is wrong.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work safely on ladders, slopes, heat, wind, and job sites&lt;/td&gt;
&lt;td&gt;Work safely around production data, secrets, deployments, and user impact&lt;/td&gt;
&lt;td&gt;Both jobs have risk, but the kind of risk is different.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is why I do not buy the argument that software work is always intellectually superior to trade work. A lot of software development is applied craft, pattern recognition, troubleshooting, repetition, and learning how to avoid known failures.&lt;/p&gt;

&lt;p&gt;The difference is that software companies can sell the same work again and again. A roofing company cannot install the same roof on 100,000 houses with one deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Army Medic Work Compared To Software Development &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Medic work is another comparison that makes software pay feel strange. As a medic, especially in the Army, the job is not just knowing medical facts. It is applying training under stress, around chain of command, with imperfect information, limited time, and real consequences.&lt;/p&gt;

&lt;p&gt;The Army describes the 68W Combat Medic Specialist role as assessing injuries, stabilizing patients, making critical medical decisions under extreme conditions, training other soldiers in first aid, and providing emergency medical treatment. That is a lot of responsibility for a role that often does not pay anywhere near what a developer makes.&lt;/p&gt;

&lt;p&gt;Civilian pay shows the gap clearly too. BLS lists EMTs at a median annual wage of &lt;strong&gt;$41,340&lt;/strong&gt; and paramedics at &lt;strong&gt;$58,410&lt;/strong&gt;, which means a junior software developer can easily make more than someone doing emergency medicine work.&lt;/p&gt;

&lt;p&gt;This is not because the junior developer has more immediate responsibility than a medic. A junior dev might break a page or slow down a sprint, while a medic can be involved in decisions where minutes matter.&lt;/p&gt;

&lt;p&gt;The software comparison is not about physical danger or emotional pressure. It is about decision-making inside a system, because medics and developers both work with incomplete information and need to decide what matters first.&lt;/p&gt;

&lt;p&gt;A medic has to assess the patient, control bleeding, protect the airway, manage shock, communicate with the team, prepare evacuation, document care, and keep working under pressure. A developer has to assess the bug, isolate the failure, protect production, communicate with the team, prepare a fix, document the change, and keep working under pressure.&lt;/p&gt;

&lt;p&gt;Those are not equal jobs. The human stakes are not the same. But the pattern is similar because both involve triage, prioritization, systems thinking, and knowing when the wrong action is worse than taking a moment to understand the problem.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Medic Work&lt;/th&gt;
&lt;th&gt;Software Equivalent&lt;/th&gt;
&lt;th&gt;Why The Comparison Makes Sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Triage multiple problems under pressure&lt;/td&gt;
&lt;td&gt;Prioritize incidents, bugs, and outages&lt;/td&gt;
&lt;td&gt;Both jobs require deciding what matters first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stop bleeding before treating smaller injuries&lt;/td&gt;
&lt;td&gt;Fix the production-breaking issue before cosmetic bugs&lt;/td&gt;
&lt;td&gt;Both jobs need damage control before polish.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maintain airway, breathing, and circulation&lt;/td&gt;
&lt;td&gt;Protect uptime, data flow, and core system health&lt;/td&gt;
&lt;td&gt;Both jobs depend on keeping the main system alive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work with limited information&lt;/td&gt;
&lt;td&gt;Debug with incomplete logs or unclear reports&lt;/td&gt;
&lt;td&gt;Both jobs rarely start with perfect information.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Communicate with chain of command or evacuation teams&lt;/td&gt;
&lt;td&gt;Communicate with managers, product, support, and engineers&lt;/td&gt;
&lt;td&gt;Both jobs fail when communication fails.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track treatment and patient status&lt;/td&gt;
&lt;td&gt;Document incident notes, fixes, and follow-up work&lt;/td&gt;
&lt;td&gt;Both jobs need records so the next person is not blind.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Train others in basic first aid&lt;/td&gt;
&lt;td&gt;Mentor juniors and write operational docs&lt;/td&gt;
&lt;td&gt;Both jobs scale knowledge through training.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stay calm when people panic&lt;/td&gt;
&lt;td&gt;Stay calm during production issues&lt;/td&gt;
&lt;td&gt;Both jobs punish panic and reward process.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is why I do not like when developers exaggerate how hard coding is compared to everything else. Medic work can be more stressful, more direct, more personal, and more consequential in the moment.&lt;/p&gt;

&lt;p&gt;The reason software pays more is not because society values medics correctly. Software pays more because companies can turn working software into repeatable revenue, while emergency medical work is often limited by public budgets, contracts, insurance systems, military pay structures, and staffing models that do not reward the worker based on the actual human value of the work.&lt;/p&gt;




&lt;h2&gt;
  
  
  Private Security Compared To Software Development &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Private security is another job people underestimate because they picture someone just standing around. Sometimes that is what it looks like from the outside, but the actual job is staying alert when nothing is happening, noticing when something changes, handling people without escalating the situation, and being the first person blamed when something goes wrong.&lt;/p&gt;

&lt;p&gt;BLS lists security guards at a median annual wage of &lt;strong&gt;$38,370&lt;/strong&gt; in May 2024. That is about &lt;strong&gt;$18.45/hour&lt;/strong&gt;, and it is still far below what many junior developers make.&lt;/p&gt;

&lt;p&gt;When I worked private security, the job was not technically complex the same way software is complex, but it required discipline, awareness, patience, and judgment. You had to watch access points, control entry, write incident reports, handle tense people, stay awake, stay professional, and understand when to call for help.&lt;/p&gt;

&lt;p&gt;Software has a security version of that same thinking. A lot of development work is boring monitoring, access control, logging, reviewing permissions, checking systems, and making sure the wrong person does not get into the wrong place.&lt;/p&gt;

&lt;p&gt;The pay difference is not because the private security worker has no value. The pay difference is because private security is often treated as a cost center, while software is often treated as a product engine or revenue multiplier.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Private Security Work&lt;/th&gt;
&lt;th&gt;Software Equivalent&lt;/th&gt;
&lt;th&gt;Why The Comparison Makes Sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Control access to a site&lt;/td&gt;
&lt;td&gt;Build authentication and authorization&lt;/td&gt;
&lt;td&gt;Both jobs decide who gets in and what they can touch.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Watch cameras, doors, lots, and patterns&lt;/td&gt;
&lt;td&gt;Monitor logs, dashboards, errors, and metrics&lt;/td&gt;
&lt;td&gt;Both jobs require noticing abnormal behavior.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Write incident reports&lt;/td&gt;
&lt;td&gt;Write bug reports, incident notes, and postmortems&lt;/td&gt;
&lt;td&gt;Both jobs need clear records after something happens.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;De-escalate tense people&lt;/td&gt;
&lt;td&gt;Handle support escalations and production pressure calmly&lt;/td&gt;
&lt;td&gt;Both jobs need communication under stress.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Follow post orders&lt;/td&gt;
&lt;td&gt;Follow runbooks, deployment process, and security policy&lt;/td&gt;
&lt;td&gt;Both jobs depend on process because memory is not enough.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Patrol and inspect areas&lt;/td&gt;
&lt;td&gt;Review systems, endpoints, configs, and permissions&lt;/td&gt;
&lt;td&gt;Both jobs look for problems before they become incidents.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Respond when something changes&lt;/td&gt;
&lt;td&gt;Respond to alerts, outages, and suspicious activity&lt;/td&gt;
&lt;td&gt;Both jobs can be quiet for hours and then serious fast.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The unfair part is that security workers are paid like replaceable labor even though bad security can cost a company a lot. Software developers are paid better because their work is closer to scalable revenue and because companies believe replacing a developer is harder than replacing a guard.&lt;/p&gt;

&lt;p&gt;That does not mean the market is morally correct. It means the market rewards leverage more than responsibility.&lt;/p&gt;




&lt;h2&gt;
  
  
  Warehouse And Manual Labor Compared To Software Development &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Warehouse work is another comparison that matters because a lot of people in tech have never had to do repetitive physical work for a paycheck. BLS lists hand laborers and material movers at a median annual wage of &lt;strong&gt;$37,680&lt;/strong&gt;, which shows how low that work often pays compared to software.&lt;/p&gt;

&lt;p&gt;Warehouse work can look simple if you only describe it as “moving boxes.” Software can also look simple if you only describe it as “typing code,” which is why bad descriptions are useless.&lt;/p&gt;

&lt;p&gt;Warehouse work requires speed, accuracy, memory, scanning, staging, loading, safety, endurance, and not making mistakes that slow down everyone behind you. A bad pick, bad label, bad count, bad pallet, or bad load can create real downstream problems.&lt;/p&gt;

&lt;p&gt;Software has the same kind of flow problem, just in a different form. A bad data migration, wrong config, bad deploy, missed environment variable, or broken API contract can hold up the whole team or create customer issues.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Warehouse Work&lt;/th&gt;
&lt;th&gt;Software Equivalent&lt;/th&gt;
&lt;th&gt;Why The Comparison Makes Sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Pick the right item&lt;/td&gt;
&lt;td&gt;Pull the right data or dependency&lt;/td&gt;
&lt;td&gt;Both jobs fail when the wrong thing moves through the system.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Label and scan correctly&lt;/td&gt;
&lt;td&gt;Name, type, and log data correctly&lt;/td&gt;
&lt;td&gt;Both jobs need traceability.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Stage items in the right place&lt;/td&gt;
&lt;td&gt;Prepare code, branches, builds, and environments correctly&lt;/td&gt;
&lt;td&gt;Both jobs depend on sequence and organization.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Load without damaging product&lt;/td&gt;
&lt;td&gt;Deploy without damaging production&lt;/td&gt;
&lt;td&gt;Both jobs involve moving work safely from one state to another.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Keep pace without losing accuracy&lt;/td&gt;
&lt;td&gt;Ship quickly without breaking quality&lt;/td&gt;
&lt;td&gt;Both jobs punish sloppy speed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Follow safety and workflow rules&lt;/td&gt;
&lt;td&gt;Follow code review, testing, and deployment rules&lt;/td&gt;
&lt;td&gt;Both jobs use process to reduce mistakes.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The difference is not that software is always harder. The difference is that software work can automate the warehouse workflow itself, reduce headcount, improve routing, change inventory systems, or improve company-wide efficiency.&lt;/p&gt;

&lt;p&gt;That is why a developer who has never done warehouse work might make more than the warehouse worker. It is not because the developer is automatically tougher, it is because the developer may be building the system that changes how 500 warehouse workers operate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Teaching Compared To Software Development &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Teaching is one of the clearest examples of how pay does not equal social value. BLS lists high school teachers at a median annual wage of &lt;strong&gt;$64,580&lt;/strong&gt;, which is above the national median but still far below software developer pay and below many junior tech offers.&lt;/p&gt;

&lt;p&gt;A good teacher has to understand the subject, manage a room, communicate clearly, adjust to different students, track progress, deal with parents and administrators, follow standards, grade work, and keep showing up even when the system is not built to make the job easy.&lt;/p&gt;

&lt;p&gt;That sounds a lot like developer mentorship in some ways. A senior developer who cannot explain anything clearly is less useful than a senior developer who can teach patterns, review code well, write docs, and help juniors become productive.&lt;/p&gt;

&lt;p&gt;The difference is that teaching usually sits inside public budgets, district funding, local taxes, political fights, and credential systems. Software sits inside companies that can sell products repeatedly and use technical work to increase margins.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Teaching Work&lt;/th&gt;
&lt;th&gt;Software Equivalent&lt;/th&gt;
&lt;th&gt;Why The Comparison Makes Sense&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Break down hard concepts&lt;/td&gt;
&lt;td&gt;Explain systems, code, and architecture&lt;/td&gt;
&lt;td&gt;Both jobs require turning complexity into something another person can use.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Manage different skill levels&lt;/td&gt;
&lt;td&gt;Mentor juniors and collaborate across teams&lt;/td&gt;
&lt;td&gt;Both jobs involve uneven experience levels.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grade and give feedback&lt;/td&gt;
&lt;td&gt;Review code and give actionable comments&lt;/td&gt;
&lt;td&gt;Both jobs need feedback that improves the person, not just the output.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Follow curriculum and standards&lt;/td&gt;
&lt;td&gt;Follow product requirements, security standards, and engineering process&lt;/td&gt;
&lt;td&gt;Both jobs work inside constraints.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Track progress over time&lt;/td&gt;
&lt;td&gt;Track technical debt, sprint work, and developer growth&lt;/td&gt;
&lt;td&gt;Both jobs require long-term attention.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handle classroom pressure&lt;/td&gt;
&lt;td&gt;Handle meetings, incidents, and team pressure&lt;/td&gt;
&lt;td&gt;Both jobs require communication when things get messy.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is why the “developers are paid because they are smarter” argument falls apart. Teachers need skill, judgment, patience, communication, and subject knowledge, but their labor does not scale the same way software does.&lt;/p&gt;

&lt;p&gt;A teacher teaches the students in front of them. A developer builds a feature once and the company can put it in front of every customer.&lt;/p&gt;




&lt;h2&gt;
  
  
  Do Most Developers Even Do DSA? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Most developers do not spend their normal workday implementing red-black trees, writing graph algorithms from scratch, or solving LeetCode-style dynamic programming problems. Most business software work is much more ordinary than the interview process makes it look.&lt;/p&gt;

&lt;p&gt;That does not mean data structures and algorithms are useless. It means there is a difference between the theory that helps you think and the daily work most developers are paid to do.&lt;/p&gt;

&lt;p&gt;Most web developers spend more time reading existing code, changing components, writing endpoints, shaping data, handling errors, fixing tests, wiring third-party services, working with databases, and pushing changes through a deployment process. That work still uses data structures, but usually in the form of arrays, objects, maps, JSON, query results, collections, queues, and state.&lt;/p&gt;

&lt;p&gt;A roofer does not calculate structural engineering formulas all day either. That does not mean roofing has no skill. It means the job is mostly applied field knowledge, judgment, tool use, sequence, safety, and knowing what failure looks like before it happens.&lt;/p&gt;

&lt;p&gt;A medic does not write a medical textbook during every patient interaction either. They apply training, assess the current situation, follow protocol, make decisions, communicate, and act before the situation gets worse.&lt;/p&gt;

&lt;p&gt;A security guard is not doing legal theory all night either. They follow post orders, watch patterns, control access, de-escalate, document, and call the right people when something crosses the line.&lt;/p&gt;

&lt;p&gt;Software is similar for most developers. The job is less “solve a puzzle from scratch” and more “change a living system without making it worse.”&lt;/p&gt;

&lt;p&gt;The reason DSA still matters is that some jobs really do need it. Search, ranking, distributed systems, graphics, compilers, databases, high-frequency trading, AI infrastructure, embedded systems, and large-scale platform work can absolutely require deeper computer science.&lt;/p&gt;

&lt;p&gt;The problem is that the hiring process often treats every web developer like they are applying to build a search engine. That creates a fake picture of the job, because plenty of developers make solid money doing CRUD, integrations, infrastructure, UI, testing, debugging, and maintenance.&lt;/p&gt;

&lt;p&gt;This is part of why salary conversations get weird. A person outside tech hears that developers make six figures and assumes they must be doing advanced math all day. A person inside tech knows plenty of developers are mostly moving data from one place to another, validating it, displaying it, storing it, and making sure it does not break.&lt;/p&gt;

&lt;p&gt;That work still matters, but it is not always the mythical version of software engineering people imagine. Most companies pay for working systems, not for how many algorithm problems someone can solve on a whiteboard.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is Web Development Skilled Trade Work With A Keyboard? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A lot of normal software work is closer to skilled trade work than developers want to admit. Most business developers are not doing advanced algorithm research, because they are building, fixing, connecting, deploying, documenting, and maintaining systems.&lt;/p&gt;

&lt;p&gt;That does not make the job fake or easy. Roofing is also “just putting materials on a roof” if someone wants to describe it badly, but anyone who has done it knows that a bad roof can look fine for a little while before the leak exposes every shortcut.&lt;/p&gt;

&lt;p&gt;Software is the same way. Bad code can look fine in the demo, pass the happy path, and still fail when users hit weird inputs, network errors, bad permissions, slow queries, expired sessions, broken environment variables, or real production load.&lt;/p&gt;

&lt;p&gt;This is where the trade comparison gets useful. A lot of web development is not elite math, but it is still skilled production work where experience matters because the edge cases are what punish you.&lt;/p&gt;

&lt;p&gt;The same pattern shows up across roofing, medic work, security, warehouse work, teaching, and software. The public sees the visible output, but the worker knows the job is mostly about preventing the failure that nobody notices if you did it right.&lt;/p&gt;

&lt;p&gt;In roofing, a customer might only see shingles. In software, a product manager might only see a button. The worker sees the layers under it, the ways it can fail, the shortcuts that were taken before, and the cleanup nobody budgeted time for.&lt;/p&gt;

&lt;p&gt;That is why I think “easy job” is the wrong phrase. Some development work is physically easy, and some tickets are technically simple, but the job becomes valuable because the work lives inside a larger system with users, data, revenue, and future maintenance attached to it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Are Junior Developers Overpaid? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Compared to roofers, EMTs, teachers, security guards, warehouse workers, construction laborers, and the national median worker, junior developers are usually overpaid in the plain social comparison sense. A junior developer making $90k to $120k while still learning the job is making more than many people who carry more physical risk, more public responsibility, or more immediate consequences.&lt;/p&gt;

&lt;p&gt;Compared to the business model they work inside, juniors are not always overpaid. A junior who can ship small production improvements, automate annoying internal work, fix customer-facing bugs, improve documentation, and grow into a mid-level developer is not just being paid for today’s output.&lt;/p&gt;

&lt;p&gt;The company is paying for the pipeline. Hiring a junior is partly a bet that the person will become useful enough to retain, promote, or use as a cheaper alternative to hiring only seniors.&lt;/p&gt;

&lt;p&gt;This is also why junior hiring gets ugly when the market tightens. If companies stop wanting to invest in training, juniors suddenly look expensive because they need mentorship before they become reliably productive.&lt;/p&gt;

&lt;p&gt;That is where the “easy job” complaint has some truth but not the whole truth. A lot of junior tickets are easy compared to roofing, medic work, or private security, but the junior is still learning how to work inside a system where small changes can create bigger problems.&lt;/p&gt;

&lt;p&gt;So yes, juniors can be overpaid if the company expects them to be productive immediately and they are mostly being carried. But juniors can be underpaid if they are doing real production work, learning fast, getting little support, and still being treated like replaceable cheap labor.&lt;/p&gt;

&lt;p&gt;The more honest answer is that junior pay is not about whether the current ticket is easy. It is about whether the company believes the person can become valuable before the cost of training them becomes a loss.&lt;/p&gt;




&lt;h2&gt;
  
  
  Are Mid-Level Developers Fairly Paid? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Mid-level developers are probably the closest thing to fairly paid in normal software work. They usually know enough to ship, debug, communicate, review code, understand production basics, and ask for help before they create a disaster.&lt;/p&gt;

&lt;p&gt;They are not usually responsible for company-wide technical direction. They also are not usually helpless, which makes them valuable without making them as expensive as staff or principal engineers.&lt;/p&gt;

&lt;p&gt;This level is where software starts looking most like skilled trade work. A solid mid-level developer knows the tools, knows the common failure points, knows how to estimate better than a junior, and knows when a “small change” is not actually small.&lt;/p&gt;

&lt;p&gt;A solid roofer with a few years in the field is the same kind of person. They may not own the company or design the whole job, but they can look at a roof, understand the next steps, avoid obvious mistakes, and keep the job moving.&lt;/p&gt;

&lt;p&gt;A solid medic is also that kind of person. They may not be the doctor, but they know how to assess the situation, act within scope, document, communicate, and keep the patient moving through the system.&lt;/p&gt;

&lt;p&gt;A reliable security worker fits the same pattern too. They may not be writing policy, but they know the post, notice what is off, document what happened, and understand when a situation needs to move up the chain.&lt;/p&gt;

&lt;p&gt;That is why mid-level dev compensation makes the most sense to me. They are expensive, but they are usually expensive in the same way any reliable skilled worker is expensive, with the added difference that software output can scale.&lt;/p&gt;




&lt;h2&gt;
  
  
  Are Staff Engineers Overpaid? &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Staff engineers are where the conversation becomes almost impossible because the numbers get absurd. A Google L6 staff engineer around $580k, a Meta E6 staff engineer around $775k, and Netflix senior staff compensation near or above $1M sounds fake if you compare it to normal jobs.&lt;/p&gt;

&lt;p&gt;But staff engineers at companies like that are not being paid to close Jira tickets. They are paid to reduce risk, set technical direction, unblock teams, review architecture, avoid expensive mistakes, and make decisions that affect systems with huge numbers of users.&lt;/p&gt;

&lt;p&gt;That is why revenue per employee matters. NVIDIA reportedly generated around $4.4 million in revenue per employee, and Netflix was reported around $4.15 million per employee, which changes how a $700k engineer looks on a spreadsheet.&lt;/p&gt;

&lt;p&gt;That does not mean every staff engineer deserves $700k. Some people have inflated titles, some companies hand out titles loosely, and some senior people become expensive bottlenecks instead of force multipliers.&lt;/p&gt;

&lt;p&gt;But a real staff engineer at scale is not just a better coder. They are closer to a technical foreman, architect, incident preventer, reviewer, teacher, and risk manager combined.&lt;/p&gt;

&lt;p&gt;That kind of work can be underpaid if it prevents huge losses. It can also be overpaid if the person mostly attends meetings, writes vague docs, and creates no real technical leverage.&lt;/p&gt;

&lt;p&gt;The title alone does not answer the question. The value depends on the actual scope, the systems involved, and whether the person makes many other engineers and systems better.&lt;/p&gt;

&lt;p&gt;This is the part that normal salary comparisons miss. A staff engineer at a small company and a staff engineer at a global platform can have the same title, but one might be improving internal tooling for 80 employees while the other is making architecture decisions that affect millions of users.&lt;/p&gt;

&lt;p&gt;That is why staff pay looks fake from the outside. Sometimes it is inflated, sometimes it is justified, and sometimes it is still cheaper than the damage the wrong technical decision would cause.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where AI Changes The Pay Conversation &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;AI makes this debate even harder because it lowers the floor and raises the ceiling at the same time. A junior with AI tools can ship more than a junior could a few years ago, but a weak junior can also create a bigger mess faster than before.&lt;/p&gt;

&lt;p&gt;The boring tasks are becoming cheaper. Boilerplate, simple components, basic scripts, basic CRUD, documentation drafts, test scaffolds, and quick debugging help are all easier with tools like ChatGPT, Claude, Cursor, and Copilot.&lt;/p&gt;

&lt;p&gt;That means companies may eventually pay less for people who only know how to produce basic code. The value is moving toward people who can understand the system, verify AI output, debug bad suggestions, protect production, think through risk, and connect technical work to business goals.&lt;/p&gt;

&lt;p&gt;This is where staff engineers and strong mid-level developers may become even more valuable. If a company has ten juniors using AI and nobody experienced reviewing the architecture, the company did not get faster, it just created problems at higher speed.&lt;/p&gt;

&lt;p&gt;AI does not remove the need for judgment. It makes judgment more important because the cost of producing code went down, but the cost of understanding whether that code is correct did not disappear.&lt;/p&gt;

&lt;p&gt;This is also why junior dev pay is going to be a rough topic for a while. If a junior can use AI to ship useful work and they can explain what they are doing, their value goes up. If they use AI to produce code they cannot understand, their risk goes up.&lt;/p&gt;

&lt;p&gt;The same thing happened in other work when tools improved. Better nail guns did not remove the need for someone who understands roofing. Better medical equipment did not remove the need for someone who can assess the patient. Better cameras did not remove the need for security judgment.&lt;/p&gt;

&lt;p&gt;Better coding tools will not remove the need for developers who understand systems. They will probably remove some tolerance for people who only copy output and hope it works.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Three Different Developer Economies &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The software industry is not one labor market anymore. It is at least three different economies pretending to be one because all the job titles use the word developer or engineer.&lt;/p&gt;

&lt;p&gt;The first economy is normal software work. These are the developers at small companies, local businesses, agencies, internal IT teams, healthcare companies, manufacturing companies, insurance companies, and non-tech companies where software supports the business instead of being the whole business.&lt;/p&gt;

&lt;p&gt;The second economy is high-scale tech. These are developers at Big Tech, AI labs, high-frequency trading firms, cloud infrastructure companies, fintech platforms, and product companies where one technical decision can affect millions of users or billions of dollars in market value.&lt;/p&gt;

&lt;p&gt;The third economy is underpaid software work. These are developers maintaining legacy systems, handling frontend, backend, support, infrastructure, deployments, and documentation while making $60k, $80k, or maybe $100k with little mentorship and no real path upward.&lt;/p&gt;

&lt;p&gt;This is why the argument goes nowhere. Someone talking about a junior web developer at a small local company and someone talking about an L6 engineer at Google are not talking about the same job.&lt;/p&gt;

&lt;p&gt;Both people can be telling the truth. They are just describing different worlds.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Developer Economy&lt;/th&gt;
&lt;th&gt;Typical Work&lt;/th&gt;
&lt;th&gt;Typical Pay Reality&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Normal software work&lt;/td&gt;
&lt;td&gt;CRUD, internal tools, websites, APIs, integrations, support, maintenance&lt;/td&gt;
&lt;td&gt;Often $70k to $180k depending on region and company.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;High-scale tech&lt;/td&gt;
&lt;td&gt;Infrastructure, platforms, AI, distributed systems, revenue-critical products&lt;/td&gt;
&lt;td&gt;Can reach $300k to $1M+ because the leverage is massive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Underpaid software work&lt;/td&gt;
&lt;td&gt;Legacy maintenance, too many hats, little support, low-budget companies&lt;/td&gt;
&lt;td&gt;Can pay closer to $50k to $100k while still demanding broad responsibility.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This split explains why developers argue past each other. One person is talking about people making $500k and another person is talking about someone doing full-stack work for $70k at a non-tech company.&lt;/p&gt;

&lt;p&gt;The title alone does not tell you enough. You need to know the company, the market, the revenue model, the level, the scope, the risk, and whether the person is actually creating leverage or just carrying a fancy title.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest Answer &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Developers are overpaid if the comparison is physical danger, social value, or visible effort. A junior developer working from home can make more than a roofer, medic, teacher, security guard, warehouse worker, or construction laborer, and I do not think developers should pretend that feels normal.&lt;/p&gt;

&lt;p&gt;Developers are not always overpaid if the comparison is business leverage. A developer who ships a feature used by thousands of customers, prevents outages, improves performance, secures customer data, or automates expensive work can easily create more value than their salary.&lt;/p&gt;

&lt;p&gt;Most normal developers are not doing elite computer science all day. They are doing applied software trade work, which means building, fixing, connecting, testing, deploying, documenting, and maintaining systems that break in weird ways.&lt;/p&gt;

&lt;p&gt;That work is not magic. It is not always harder than roofing, medic work, construction, warehouse work, teaching, or security work, but it exists inside a business model where output can scale.&lt;/p&gt;

&lt;p&gt;The cleanest answer is this: junior devs can be socially overpaid and economically reasonable at the same time, mid-level devs are often the most fairly paid group, and real staff engineers at scale can look wildly overpaid while still being underpaid compared to the money and risk they manage.&lt;/p&gt;

&lt;p&gt;The thing I do not buy anymore is the idea that pay equals difficulty. Pay equals leverage, scarcity, company margins, negotiation power, and how close your work is to money.&lt;/p&gt;

&lt;p&gt;That is why the junior dev making a React form can out-earn a roofer, medic, guard, teacher, or warehouse worker. It is not because the junior dev is tougher, and it is not because the other jobs are easy. It is because the software company can scale the result in a way most physical or public-service work cannot.&lt;/p&gt;

&lt;p&gt;That does not make the market morally correct. It just explains why the numbers look broken.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources &lt;a&gt;&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/computer-and-information-technology/software-developers.htm" rel="noopener noreferrer"&gt;BLS, Software Developers, Quality Assurance Analysts, and Testers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/construction-and-extraction/roofers.htm" rel="noopener noreferrer"&gt;BLS, Roofers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/healthcare/emts-and-paramedics.htm" rel="noopener noreferrer"&gt;BLS, EMTs and Paramedics&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/protective-service/security-guards.htm" rel="noopener noreferrer"&gt;BLS, Security Guards and Gambling Surveillance Officers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/education-training-and-library/high-school-teachers.htm" rel="noopener noreferrer"&gt;BLS, High School Teachers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/construction-and-extraction/construction-laborers-and-helpers.htm" rel="noopener noreferrer"&gt;BLS, Construction Laborers and Helpers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/ooh/transportation-and-material-moving/hand-laborers-and-material-movers.htm" rel="noopener noreferrer"&gt;BLS, Hand Laborers and Material Movers&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.bls.gov/charts/census-of-fatal-occupational-injuries/rate-and-number-of-fatal-work-injuries-in-selected-occupations.htm" rel="noopener noreferrer"&gt;BLS, Fatal Work Injury Rates, 2024&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.goarmy.com/careers-and-jobs/science-medicine/intensive-care/68w-combat-medic-specialist" rel="noopener noreferrer"&gt;U.S. Army, 68W Combat Medic Specialist&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.cool.osd.mil/army/moc/index.html?moc=68w" rel="noopener noreferrer"&gt;Army COOL, 68W Combat Medic Specialist MOS Overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.dfas.mil/MilitaryMembers/payentitlements/Pay-Tables/" rel="noopener noreferrer"&gt;DFAS, Military Pay Tables&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.levels.fyi/t/software-engineer" rel="noopener noreferrer"&gt;Levels.fyi, Software Engineer Salary&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://builtin.com/salaries/us/junior-software-engineer" rel="noopener noreferrer"&gt;BuiltIn, Junior Software Engineer Salary in US&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.adpresearch.com/research/the-rise-and-fall-of-the-software-developer" rel="noopener noreferrer"&gt;ADP Research, The Rise and Fall of the Software Developer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.library.hbs.edu/working-knowledge/remote-work-or-more-pay-what-tech-workers-value-in-one-chart" rel="noopener noreferrer"&gt;Harvard Business School, Remote Work or More Pay&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.ondeck.com/resources/revenue-per-employee" rel="noopener noreferrer"&gt;OnDeck, Revenue Per Employee Rankings&lt;/a&gt;&lt;/p&gt;

</description>
      <category>career</category>
      <category>careerdevelopment</category>
      <category>ai</category>
      <category>development</category>
    </item>
    <item>
      <title>AI Policy Is Becoming the New Entry-Level Gatekeeping</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:37:55 +0000</pubDate>
      <link>https://dev.to/bradleymatera/ai-policy-is-becoming-the-new-entry-level-gatekeeping-1d4o</link>
      <guid>https://dev.to/bradleymatera/ai-policy-is-becoming-the-new-entry-level-gatekeeping-1d4o</guid>
      <description>&lt;p&gt;AI policy is becoming a new entry-level gate.&lt;/p&gt;

&lt;p&gt;Not because companies have mature rules. Because many do not.&lt;/p&gt;

&lt;p&gt;They want juniors who are AI-literate, fast, current, and able to use modern tools.&lt;/p&gt;

&lt;p&gt;They also distrust AI-assisted work, punish unclear disclosure, and often fail to explain which tools are allowed.&lt;/p&gt;

&lt;p&gt;That contradiction creates the trap:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use AI and risk looking dependent. Avoid AI and risk looking behind.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is not a junior developer problem. It is a leadership problem.&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://giphy.com/gifs/afinitiai-ai-intelligence-artificial-Fs4Fh8g3KxM3PEoGIB" 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%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExZXh4enU4NjUybnl4ODFtcG03YnBmNDN6anN3dnM3dDg3dnduMnQxcCZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FFs4Fh8g3KxM3PEoGIB%2Fgiphy.webp" height="270" class="m-0" width="480"&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://giphy.com/gifs/afinitiai-ai-intelligence-artificial-Fs4Fh8g3KxM3PEoGIB" rel="noopener noreferrer" class="c-link"&gt;
            Winning Artificial Intelligence GIF by Afiniti - Find &amp;amp; Share on GIPHY
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Discover &amp;amp; share this Winning Artificial Intelligence GIF by Afiniti with everyone you know. GIPHY is how you search, share, discover, and create GIFs.
          &lt;/p&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%2Fgiphy.com%2Fstatic%2Fimg%2Ffavicon.png" width="16" height="16"&gt;
          giphy.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The market already moved
&lt;/h2&gt;

&lt;p&gt;AI is not a fringe developer tool anymore.&lt;/p&gt;

&lt;p&gt;Stack Overflow's 2025 Developer Survey says 84% of respondents are using or planning to use AI tools in their development process. It also says 44% used AI-enabled tools to learn coding techniques or a new language. [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;GitHub's Octoverse 2025 report says nearly 80% of new developers on GitHub used Copilot within their first week. [&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Microsoft's 2025 Work Trend Index describes AI agents and AI-assisted work as part of the emerging workplace model. [&lt;a href="https://news.microsoft.com/annual-work-trend-index-2025/" rel="noopener noreferrer"&gt;Microsoft Work Trend Index 2025&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;OpenAI's 2025 enterprise AI report also frames coding workflows as one of the areas where frontier models are accelerating software development. [&lt;a href="https://openai.com/business/guides-and-resources/the-state-of-enterprise-ai-2025-report/" rel="noopener noreferrer"&gt;OpenAI enterprise AI report&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-47b0b04c-0435-4418-ae83-724f82e4eafa" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-47b0b04c-0435-4418-ae83-724f82e4eafa" alt="Chart: AI is already present across developer use, new GitHub developer onboarding, entry-level hiring expectations, and coding education" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt;, &lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;, and &lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake Class of 2026 AI economy research&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The message is obvious: AI is already in the workflow. The rules are lagging behind the tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  The entry-level contradiction
&lt;/h2&gt;

&lt;p&gt;Handshake's research on the Class of 2026 in the AI economy found that 70% of hiring leaders say AI will change entry-level role requirements. [&lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" alt="Chart: 70% of hiring leaders say AI will change entry-level role requirements" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake Class of 2026 AI economy research&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That means companies expect entry-level candidates to understand AI's role in work.&lt;/p&gt;

&lt;p&gt;But many job descriptions still do not say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;whether AI tools are allowed&lt;/li&gt;
&lt;li&gt;which tools are approved&lt;/li&gt;
&lt;li&gt;whether generated code is allowed&lt;/li&gt;
&lt;li&gt;whether AI use must be disclosed&lt;/li&gt;
&lt;li&gt;whether candidates may use AI in take-home assignments&lt;/li&gt;
&lt;li&gt;whether company code can be pasted into tools&lt;/li&gt;
&lt;li&gt;whether AI is allowed for learning but not implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That ambiguity matters because juniors are the least powerful people in the hiring process.&lt;/p&gt;

&lt;p&gt;Ambiguous rules usually punish the least powerful person first.&lt;/p&gt;

&lt;h2&gt;
  
  
  "Use AI, but not like that" is not a policy
&lt;/h2&gt;

&lt;p&gt;A lot of companies have a vibe instead of a policy.&lt;/p&gt;

&lt;p&gt;The vibe sounds like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We want people who use modern tools.&lt;/li&gt;
&lt;li&gt;We value productivity.&lt;/li&gt;
&lt;li&gt;We are exploring AI.&lt;/li&gt;
&lt;li&gt;Do not submit AI slop.&lt;/li&gt;
&lt;li&gt;Use common sense.&lt;/li&gt;
&lt;li&gt;We can tell when something is generated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not governance. That is a collection of future arguments.&lt;/p&gt;

&lt;p&gt;A real policy answers operational questions:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Policy area&lt;/th&gt;
&lt;th&gt;Clear answer needed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Approved tools&lt;/td&gt;
&lt;td&gt;Which tools can employees use?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data privacy&lt;/td&gt;
&lt;td&gt;What code, logs, tickets, or customer data may be pasted?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generated code&lt;/td&gt;
&lt;td&gt;Is generated implementation allowed?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Learning use&lt;/td&gt;
&lt;td&gt;Can AI explain code, docs, errors, and concepts?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disclosure&lt;/td&gt;
&lt;td&gt;When must AI assistance be mentioned in a PR?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Review&lt;/td&gt;
&lt;td&gt;What extra review is required for risky code?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Interviews&lt;/td&gt;
&lt;td&gt;Can candidates use AI during take-homes or live screens?&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Enforcement&lt;/td&gt;
&lt;td&gt;What happens when rules are unclear or violated?&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Without that, companies are not evaluating judgment. They are evaluating whether candidates guessed the hidden rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not trust the output blindly
&lt;/h2&gt;

&lt;p&gt;AI output should not be trusted blindly.&lt;/p&gt;

&lt;p&gt;Stack Overflow's 2025 survey says more developers distrust AI output accuracy than trust it: 46% versus 33%. The most common frustration is that AI solutions are "almost right, but not quite." [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-0cb70d32-659d-4b1d-8407-981bc3a9d1ee" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-0cb70d32-659d-4b1d-8407-981bc3a9d1ee" alt="Chart: Stack Overflow 2025 shows 46% distrust AI output accuracy, 33% trust it, and 66% cite almost-right answers as a frustration" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That warning matters. It does not justify lazy anti-AI rules.&lt;/p&gt;

&lt;p&gt;It supports a verification standard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can the developer explain the code?&lt;/li&gt;
&lt;li&gt;Did they test the risky behavior?&lt;/li&gt;
&lt;li&gt;Did they compare output against docs?&lt;/li&gt;
&lt;li&gt;Did they reject bad suggestions?&lt;/li&gt;
&lt;li&gt;Did they disclose meaningful assistance?&lt;/li&gt;
&lt;li&gt;Did they protect private data?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is better than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"No AI."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is also better than:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use AI to move faster, but we will punish you if we dislike the result."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Hiring managers often do not know what they want
&lt;/h2&gt;

&lt;p&gt;Many hiring managers are trying to hire for a role they have not defined.&lt;/p&gt;

&lt;p&gt;They want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AI-literate but not AI-dependent&lt;/li&gt;
&lt;li&gt;junior but production-ready&lt;/li&gt;
&lt;li&gt;independent but coachable&lt;/li&gt;
&lt;li&gt;full-stack but cheap&lt;/li&gt;
&lt;li&gt;fast but careful&lt;/li&gt;
&lt;li&gt;transparent but not risky&lt;/li&gt;
&lt;li&gt;modern but compliant with unstated policy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not a candidate profile. It is unresolved leadership tension.&lt;/p&gt;

&lt;p&gt;The job description turns into a contradiction because the team has not decided what kind of developer it actually needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Evaluate AI use directly
&lt;/h2&gt;

&lt;p&gt;Companies should stop pretending candidates are not using AI. Evaluate how they use it.&lt;/p&gt;

&lt;p&gt;A good interview prompt could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Here is a small function with a bug.
You may use AI as you normally would.
When you submit the fix, include:
- what you asked
- what the tool got wrong
- what you verified
- what tests you added
- what you would want reviewed before production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tests judgment, not theater. It also reflects how real work is increasingly done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bad AI use versus professional AI use
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Lazy AI use&lt;/th&gt;
&lt;th&gt;Professional AI use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Paste generated output&lt;/td&gt;
&lt;td&gt;Own the final code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust confident answers&lt;/td&gt;
&lt;td&gt;Verify against docs and tests&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hide tool use&lt;/td&gt;
&lt;td&gt;Disclose when required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ignore security and privacy&lt;/td&gt;
&lt;td&gt;Use approved tools and data rules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skip fundamentals&lt;/td&gt;
&lt;td&gt;Use AI to strengthen fundamentals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Treat AI as authority&lt;/td&gt;
&lt;td&gt;Treat AI as a fallible assistant&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This is the distinction hiring should measure: not whether the candidate touched AI, but whether the candidate can use it without outsourcing judgment.&lt;/p&gt;

&lt;h2&gt;
  
  
  The learning-resource problem is real
&lt;/h2&gt;

&lt;p&gt;AI is becoming the default learning layer partly because older learning paths are fragmented.&lt;/p&gt;

&lt;p&gt;The modern junior is trying to stitch together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;official docs&lt;/li&gt;
&lt;li&gt;old Stack Overflow answers&lt;/li&gt;
&lt;li&gt;framework changelogs&lt;/li&gt;
&lt;li&gt;YouTube tutorials&lt;/li&gt;
&lt;li&gt;Discord threads&lt;/li&gt;
&lt;li&gt;GitHub issues&lt;/li&gt;
&lt;li&gt;blog posts&lt;/li&gt;
&lt;li&gt;paid courses&lt;/li&gt;
&lt;li&gt;outdated examples&lt;/li&gt;
&lt;li&gt;internal docs if they are lucky&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI sits on top of that mess and gives a conversational way to ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What changed between versions?&lt;/li&gt;
&lt;li&gt;Why does this error happen?&lt;/li&gt;
&lt;li&gt;What should I search next?&lt;/li&gt;
&lt;li&gt;Can you explain this code like I am new to the repo?&lt;/li&gt;
&lt;li&gt;What test cases should I consider?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not a replacement for learning. It is a learning interface.&lt;/p&gt;

&lt;p&gt;Companies that do not understand that will keep misreading AI use as laziness.&lt;/p&gt;

&lt;h2&gt;
  
  
  The research points back to training
&lt;/h2&gt;

&lt;p&gt;The paper &lt;em&gt;The Widening Gap&lt;/em&gt; found that generative AI can help novice programmers, but weaker learners may accept incorrect suggestions more easily. [&lt;a href="https://arxiv.org/abs/2405.17739" rel="noopener noreferrer"&gt;The Widening Gap&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;A 2025 systematic literature review on junior developers adopting LLMs found both positive and negative perceptions in most of the studies reviewed. [&lt;a href="https://arxiv.org/abs/2503.07556" rel="noopener noreferrer"&gt;Junior developers and LLMs SLR&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;That points back to training: AI literacy has to be taught, not assumed and not banned by reflex.&lt;/p&gt;

&lt;h2&gt;
  
  
  A policy that actually says something
&lt;/h2&gt;

&lt;p&gt;A serious AI policy for junior developers could say:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Approved tools only&lt;/td&gt;
&lt;td&gt;Prevents data leakage and tool sprawl.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No private code in unapproved tools&lt;/td&gt;
&lt;td&gt;Protects IP and customer data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Disclosure for material assistance&lt;/td&gt;
&lt;td&gt;Keeps review honest.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tests required for generated logic&lt;/td&gt;
&lt;td&gt;Verifies behavior.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Human review for risky domains&lt;/td&gt;
&lt;td&gt;Auth, payments, permissions, infrastructure, data access.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI allowed for learning&lt;/td&gt;
&lt;td&gt;Explanation, docs, debugging, practice tasks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Developer owns final output&lt;/td&gt;
&lt;td&gt;No hiding behind the model.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is not anti-AI. That is professional.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;AI policy is now part of junior hiring. Companies can either define it clearly or keep using it as hidden gatekeeping.&lt;/p&gt;

&lt;p&gt;The serious path is obvious:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;allow learning&lt;/li&gt;
&lt;li&gt;protect private data&lt;/li&gt;
&lt;li&gt;require verification&lt;/li&gt;
&lt;li&gt;inspect the work&lt;/li&gt;
&lt;li&gt;teach the judgment&lt;/li&gt;
&lt;li&gt;stop pretending AI is not part of the modern developer stack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Juniors do not need permission to be reckless. They need clear rules for being responsible.&lt;/p&gt;

&lt;p&gt;If companies cannot provide those rules, they should stop calling the confusion a candidate-quality problem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tags/ai" class="crayons-btn crayons-btn--primary"&gt;Interested in AI tooling, junior developers, and hiring? Explore #ai on DEV.&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>career</category>
      <category>careerdevelopment</category>
      <category>hiring</category>
      <category>leadership</category>
    </item>
    <item>
      <title>Senior Engineers Complaining About Juniors Are Missing the Point</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:34:40 +0000</pubDate>
      <link>https://dev.to/bradleymatera/senior-engineers-complaining-about-juniors-are-missing-the-point-2ch6</link>
      <guid>https://dev.to/bradleymatera/senior-engineers-complaining-about-juniors-are-missing-the-point-2ch6</guid>
      <description>&lt;p&gt;Senior engineers love complaining about juniors.&lt;/p&gt;

&lt;p&gt;They complain juniors do not understand fundamentals.&lt;/p&gt;

&lt;p&gt;They complain juniors use AI too much.&lt;/p&gt;

&lt;p&gt;They complain juniors ask basic questions.&lt;/p&gt;

&lt;p&gt;They complain juniors cannot debug production systems.&lt;/p&gt;

&lt;p&gt;Some of those complaints are true. They are also incomplete.&lt;/p&gt;

&lt;p&gt;Because the same industry that complains about junior quality spent years weakening the systems that used to create it.&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://giphy.com/gifs/dubsado-teamwork-WOTtToQqAArtvgBggf" 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%2Fmedia0.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExbTA0bTU2Y2xoM25oMXFrODF0ZTJuNDZvOGMwM3VsbmNlcnI0c3l0aSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FWOTtToQqAArtvgBggf%2Fgiphy.webp" height="270" class="m-0" width="480"&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://giphy.com/gifs/dubsado-teamwork-WOTtToQqAArtvgBggf" rel="noopener noreferrer" class="c-link"&gt;
            Teamwork GIF by Dubsado - Find &amp;amp; Share on GIPHY
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Discover &amp;amp; share this Teamwork GIF by Dubsado with everyone you know. GIPHY is how you search, share, discover, and create GIFs.
          &lt;/p&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%2Fgiphy.com%2Fstatic%2Fimg%2Ffavicon.png" width="16" height="16"&gt;
          giphy.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Juniors are not supposed to arrive finished
&lt;/h2&gt;

&lt;p&gt;A junior developer is not a discounted senior.&lt;/p&gt;

&lt;p&gt;A junior is a developer with potential, fundamentals in progress, limited production context, and a real need for feedback.&lt;/p&gt;

&lt;p&gt;That should not be controversial. Many companies still act like it is.&lt;/p&gt;

&lt;p&gt;They hire a junior and expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;independent delivery&lt;/li&gt;
&lt;li&gt;production debugging&lt;/li&gt;
&lt;li&gt;architectural judgment&lt;/li&gt;
&lt;li&gt;stakeholder communication&lt;/li&gt;
&lt;li&gt;cloud deployment&lt;/li&gt;
&lt;li&gt;test strategy&lt;/li&gt;
&lt;li&gt;security intuition&lt;/li&gt;
&lt;li&gt;codebase navigation&lt;/li&gt;
&lt;li&gt;product sense&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are learned abilities, not personality traits.&lt;/p&gt;

&lt;p&gt;If the company does not teach them, the company should not be shocked when the junior learns from AI, YouTube, old docs, Stack Overflow, Discord, Reddit, and trial-and-error.&lt;/p&gt;

&lt;h2&gt;
  
  
  The mentorship gap is not mysterious
&lt;/h2&gt;

&lt;p&gt;Good junior development requires slack in the system. Somebody has to have time to teach.&lt;/p&gt;

&lt;p&gt;Someone has to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explain the codebase&lt;/li&gt;
&lt;li&gt;review PRs with reasoning&lt;/li&gt;
&lt;li&gt;answer questions without making the junior feel stupid&lt;/li&gt;
&lt;li&gt;give scoped tasks&lt;/li&gt;
&lt;li&gt;connect bugs to system concepts&lt;/li&gt;
&lt;li&gt;show how production incidents are handled&lt;/li&gt;
&lt;li&gt;explain trade-offs&lt;/li&gt;
&lt;li&gt;model debugging&lt;/li&gt;
&lt;li&gt;call out risk before it becomes blame&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That takes time. Companies cut that time first.&lt;/p&gt;

&lt;p&gt;Then they complain the pipeline is weak.&lt;/p&gt;

&lt;p&gt;That is not a junior problem. It is a resource allocation problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Psychological safety is not office decor
&lt;/h2&gt;

&lt;p&gt;The research on team learning has been clear for a long time.&lt;/p&gt;

&lt;p&gt;Amy Edmondson's 1999 paper, &lt;a href="https://journals.sagepub.com/doi/pdf/10.2307/2666999" rel="noopener noreferrer"&gt;Psychological Safety and Learning Behavior in Work Teams&lt;/a&gt;, studied 51 work teams and found psychological safety was associated with learning behavior.&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-19b4fbd4-91f8-4612-8233-585c2bda17f8" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-19b4fbd4-91f8-4612-8233-585c2bda17f8" alt="Chart: Edmondson's psychological safety study examined 51 work teams" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://journals.sagepub.com/doi/pdf/10.2307/2666999" rel="noopener noreferrer"&gt;Psychological Safety and Learning Behavior in Work Teams&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That matters in engineering because juniors learn by taking small interpersonal risks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"I do not understand this code."&lt;/li&gt;
&lt;li&gt;"I think this bug is deeper than the UI."&lt;/li&gt;
&lt;li&gt;"I used AI to understand the error, but I want to verify it."&lt;/li&gt;
&lt;li&gt;"I do not know whether this is safe."&lt;/li&gt;
&lt;li&gt;"Can you explain why this pattern is preferred?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If asking those questions gets punished, juniors stop asking.&lt;/p&gt;

&lt;p&gt;Then seniors say juniors are quiet, passive, or not curious.&lt;/p&gt;

&lt;p&gt;That is the predictable result of a team that punishes learning out loud.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI fills the space mentorship left open
&lt;/h2&gt;

&lt;p&gt;Stack Overflow's 2025 Developer Survey says 44% of developers used AI-enabled tools to learn coding techniques or a new language. [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;GitHub's Octoverse 2025 report says nearly 80% of new developers on GitHub used Copilot within their first week. [&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" alt="Chart: Developer AI adoption and learning signals, including Stack Overflow AI learning use and GitHub Copilot first-week usage for new developers" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt; and &lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This is the part senior engineers need to take seriously: AI is not only being used to generate code.&lt;/p&gt;

&lt;p&gt;It is being used because juniors need explanations and often cannot get them from people.&lt;/p&gt;

&lt;p&gt;AI answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is this error?&lt;/li&gt;
&lt;li&gt;What does this SQL join do?&lt;/li&gt;
&lt;li&gt;Why is this React state stale?&lt;/li&gt;
&lt;li&gt;What is a race condition?&lt;/li&gt;
&lt;li&gt;How do I write a test for this?&lt;/li&gt;
&lt;li&gt;What should I ask in code review?&lt;/li&gt;
&lt;li&gt;What edge cases might I be missing?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That does not make AI a mentor. It makes AI the thing juniors reach for when the actual mentor is unavailable.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old learning culture had shortcuts too
&lt;/h2&gt;

&lt;p&gt;It is dishonest to act like older developers learned only through deep first-principles study.&lt;/p&gt;

&lt;p&gt;Previous generations used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stack Overflow answers&lt;/li&gt;
&lt;li&gt;snippets from blogs&lt;/li&gt;
&lt;li&gt;copied config files&lt;/li&gt;
&lt;li&gt;starter templates&lt;/li&gt;
&lt;li&gt;WordPress themes&lt;/li&gt;
&lt;li&gt;Bootstrap examples&lt;/li&gt;
&lt;li&gt;jQuery plugins&lt;/li&gt;
&lt;li&gt;internal code copied from older services&lt;/li&gt;
&lt;li&gt;tutorials that skipped production concerns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some developers learned deeply through those shortcuts. Some cargo-culted them.&lt;/p&gt;

&lt;p&gt;That same distinction matters with AI.&lt;/p&gt;

&lt;p&gt;The question is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the junior use outside help?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Did the junior build understanding?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Review the thinking, not just the diff
&lt;/h2&gt;

&lt;p&gt;A senior who wants better juniors should stop reviewing only the final diff. Review the thinking.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Review question&lt;/th&gt;
&lt;th&gt;What it teaches&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What problem is this solving?&lt;/td&gt;
&lt;td&gt;Product framing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What did you try first?&lt;/td&gt;
&lt;td&gt;Debugging process.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What did AI suggest that you rejected?&lt;/td&gt;
&lt;td&gt;Judgment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What edge case worries you?&lt;/td&gt;
&lt;td&gt;Risk awareness.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What test proves this behavior?&lt;/td&gt;
&lt;td&gt;Verification.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What part of this system do you still not understand?&lt;/td&gt;
&lt;td&gt;Learning path.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is how review becomes mentorship.&lt;/p&gt;

&lt;p&gt;Without that, review becomes a gate. Gates do not create seniors. Mentorship does.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI dependence is a real risk
&lt;/h2&gt;

&lt;p&gt;There is a real danger in AI-assisted learning.&lt;/p&gt;

&lt;p&gt;The paper &lt;em&gt;The Widening Gap&lt;/em&gt; found that generative AI can help novice programmers, but weaker students may struggle more to ignore incorrect or unhelpful suggestions. [&lt;a href="https://arxiv.org/abs/2405.17739" rel="noopener noreferrer"&gt;The Widening Gap&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;A 2025 systematic review on GenAI and code comprehension found that AI explanations can support comprehension, but can also be inaccurate or difficult for novices to evaluate. [&lt;a href="https://arxiv.org/abs/2510.17894" rel="noopener noreferrer"&gt;Code comprehension SLR&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;That means teams should not tell juniors:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Just use AI."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They should teach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to verify generated output&lt;/li&gt;
&lt;li&gt;how to compare against docs&lt;/li&gt;
&lt;li&gt;how to write tests&lt;/li&gt;
&lt;li&gt;how to reject confident wrong answers&lt;/li&gt;
&lt;li&gt;how to disclose meaningful AI assistance&lt;/li&gt;
&lt;li&gt;when to ask a human&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is modern mentorship. Not nostalgia. Not tool panic.&lt;/p&gt;

&lt;h2&gt;
  
  
  The management failure nobody wants to own
&lt;/h2&gt;

&lt;p&gt;Many companies removed the apprenticeship layer and replaced it with vibes.&lt;/p&gt;

&lt;p&gt;They have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no onboarding map&lt;/li&gt;
&lt;li&gt;no junior-safe backlog&lt;/li&gt;
&lt;li&gt;no mentor capacity&lt;/li&gt;
&lt;li&gt;no documentation budget&lt;/li&gt;
&lt;li&gt;no pairing culture&lt;/li&gt;
&lt;li&gt;no AI policy&lt;/li&gt;
&lt;li&gt;no explicit progression rubric&lt;/li&gt;
&lt;li&gt;no time for seniors to teach&lt;/li&gt;
&lt;/ul&gt;

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

&lt;blockquote&gt;
&lt;p&gt;"Why are juniors not ready?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because nobody built readiness. That is the answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a real junior pipeline looks like
&lt;/h2&gt;

&lt;p&gt;A serious junior pipeline does not need to be fancy. It needs to be intentional.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Timeframe&lt;/th&gt;
&lt;th&gt;What should happen&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Week 1&lt;/td&gt;
&lt;td&gt;Environment setup, product overview, first docs fix, mentor assigned.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 1&lt;/td&gt;
&lt;td&gt;Small bug fixes, guided PRs, test-writing practice, codebase map.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 2&lt;/td&gt;
&lt;td&gt;Slightly larger feature work with review checkpoints.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 3&lt;/td&gt;
&lt;td&gt;Limited ownership of a small surface area.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 6&lt;/td&gt;
&lt;td&gt;Participation in production support with shadowing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Month 12&lt;/td&gt;
&lt;td&gt;Clear evaluation for mid-level readiness.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is not charity. That is workforce development.&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-34d7cb50-ab24-47cf-a36a-70f8d8d9f4db" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-34d7cb50-ab24-47cf-a36a-70f8d8d9f4db" alt="Chart: A realistic junior ramp grows scope from week one through month twelve" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Author framework for staged junior onboarding.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;Senior engineers are allowed to expect rigor. They are not allowed to pretend rigor appears without teaching.&lt;/p&gt;

&lt;p&gt;If juniors use AI badly, correct the behavior.&lt;/p&gt;

&lt;p&gt;If juniors use AI to learn, review the learning.&lt;/p&gt;

&lt;p&gt;If juniors cannot explain their code, teach them how to explain it.&lt;/p&gt;

&lt;p&gt;But stop acting like the new generation failed a system that the old generation forgot to maintain.&lt;/p&gt;

&lt;p&gt;The next senior engineers will not appear by accident. Somebody has to build them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tags/career" class="crayons-btn crayons-btn--primary"&gt;Interested in mentorship, junior developers, and engineering culture? Explore #career on DEV.&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>ai</category>
      <category>hiring</category>
      <category>career</category>
      <category>mentorship</category>
    </item>
    <item>
      <title>Entry-Level Job Descriptions Are Becoming Broken Product Specs</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:33:15 +0000</pubDate>
      <link>https://dev.to/bradleymatera/entry-level-job-descriptions-are-becoming-broken-product-specs-hgc</link>
      <guid>https://dev.to/bradleymatera/entry-level-job-descriptions-are-becoming-broken-product-specs-hgc</guid>
      <description>&lt;p&gt;A lot of "entry-level developer" job descriptions are not entry-level.&lt;/p&gt;

&lt;p&gt;They are broken product specs.&lt;/p&gt;

&lt;p&gt;They ask for one person to build frontend features, debug backend APIs, write SQL, manage cloud infrastructure, understand CI/CD, test everything, talk to stakeholders, support production, know security basics, and somehow still be "junior."&lt;/p&gt;

&lt;p&gt;That is not an entry-level role.&lt;/p&gt;

&lt;p&gt;That is a company trying to buy a small engineering team at junior pricing.&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://giphy.com/gifs/Biteable-biteable-biteableanimation-humanresources-KQzmhm1sowxyxU6e3v" 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%2Fmedia4.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExenE3d2R5ajAzczdtbndxcnJ2czN4YnE0Y2Nsc2thdm1qOWtzMGt1YSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FKQzmhm1sowxyxU6e3v%2Fgiphy.webp" height="270" class="m-0" width="480"&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://giphy.com/gifs/Biteable-biteable-biteableanimation-humanresources-KQzmhm1sowxyxU6e3v" rel="noopener noreferrer" class="c-link"&gt;
            Animation Hiring GIF by Biteable - Find &amp;amp; Share on GIPHY
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Discover &amp;amp; share this Animation Hiring GIF by Biteable with everyone you know. GIPHY is how you search, share, discover, and create GIFs.
          &lt;/p&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%2Fgiphy.com%2Fstatic%2Fimg%2Ffavicon.png" width="16" height="16"&gt;
          giphy.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The market is saying two things at once
&lt;/h2&gt;

&lt;p&gt;The long-term outlook for software developers is still strong.&lt;/p&gt;

&lt;p&gt;The U.S. Bureau of Labor Statistics projects software developer employment to grow 15.8% from 2024 to 2034, adding 267,700 jobs. [&lt;a href="https://www.bls.gov/opub/mlr/2026/article/industry-and-occupational-employment-projections-overview.htm" rel="noopener noreferrer"&gt;BLS projections&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-e8590180-bec4-483b-b024-1505f77206c0" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-e8590180-bec4-483b-b024-1505f77206c0" alt="Chart: BLS projects software developer employment growing from about 1.69 million jobs in 2024 to about 1.96 million jobs in 2034" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://www.bls.gov/opub/mlr/2026/article/industry-and-occupational-employment-projections-overview.htm" rel="noopener noreferrer"&gt;BLS employment projections&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;But the entry point is getting narrower.&lt;/p&gt;

&lt;p&gt;Indeed Hiring Lab reported that from Q2 2022 to Q2 2025, the share of tech job postings asking for at least five years of experience rose from 37% to 42%. The report specifically notes that the environment became more challenging for entry-level and early-career tech job seekers. [&lt;a href="https://www.hiringlab.org/2025/07/30/experience-requirements-have-tightened-amid-the-tech-hiring-freeze/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-fd6e909d-1f7f-4b4f-8a83-b33e07070c37" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-fd6e909d-1f7f-4b4f-8a83-b33e07070c37" alt="Chart: Tech job postings asking for at least five years of experience rose from 37% in Q2 2022 to 42% in Q2 2025" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://www.hiringlab.org/2025/07/30/experience-requirements-have-tightened-amid-the-tech-hiring-freeze/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That creates a broken labor-market shape:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;software work is projected to grow&lt;/li&gt;
&lt;li&gt;companies still need engineers&lt;/li&gt;
&lt;li&gt;job postings increasingly favor experienced candidates&lt;/li&gt;
&lt;li&gt;juniors are told to "get experience" before anyone will give them experience&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not just a candidate-quality problem. It is a pipeline design problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  The imaginary junior candidate
&lt;/h2&gt;

&lt;p&gt;Here is a common bad hiring pattern:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;Why it is a red flag for "junior"&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;3-5 years of production experience&lt;/td&gt;
&lt;td&gt;That is not entry-level.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;React, Node, Python, SQL, AWS, Docker, Kubernetes&lt;/td&gt;
&lt;td&gt;That is a platform surface, not a junior scope.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Own features end to end&lt;/td&gt;
&lt;td&gt;Ownership requires support and context.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build and maintain CI/CD&lt;/td&gt;
&lt;td&gt;That is DevOps/platform work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Understand security best practices&lt;/td&gt;
&lt;td&gt;Reasonable as learning goal, unrealistic as solo owner.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Work independently from day one&lt;/td&gt;
&lt;td&gt;That means the company does not plan to mentor.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Excellent UI/UX instincts&lt;/td&gt;
&lt;td&gt;That is a design skill, not automatically a dev skill.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support production incidents&lt;/td&gt;
&lt;td&gt;Fine with backup, reckless without it.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is nothing wrong with wanting broad engineers.&lt;/p&gt;

&lt;p&gt;There is something wrong with calling that role "entry-level" while refusing to say what the company will teach.&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-29a1f4cb-737d-4bd4-8005-2ab0e693ea0e" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-29a1f4cb-737d-4bd4-8005-2ab0e693ea0e" alt="Chart: Illustrative comparison showing how a bad junior posting can quietly imply three to five years of production experience" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Illustrative role-scope comparison based on the job-description pattern discussed in this article, not a market-wide statistic.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Skills-based hiring can still be lazy
&lt;/h2&gt;

&lt;p&gt;NACE's Job Outlook 2026 data shows employer use of skills-based hiring is growing for entry-level roles. [&lt;a href="https://www.naceweb.org/job-market/trends-and-predictions/employer-use-of-skills-based-hiring-practices-grows" rel="noopener noreferrer"&gt;NACE&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;In theory, that is good. Skills-based hiring can reduce overreliance on degrees, school prestige, and GPA filters.&lt;/p&gt;

&lt;p&gt;But in practice, it can become a new version of the same problem:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Show us evidence you already performed the job we refuse to train you for."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A portfolio project is useful.&lt;/p&gt;

&lt;p&gt;A take-home project can be useful.&lt;/p&gt;

&lt;p&gt;A technical screen can be useful.&lt;/p&gt;

&lt;p&gt;But none of those prove a junior can safely own ambiguous production work without mentorship.&lt;/p&gt;

&lt;p&gt;They prove the candidate can complete an assessment under artificial constraints.&lt;/p&gt;

&lt;p&gt;Companies confuse those things constantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI is now another requirement
&lt;/h2&gt;

&lt;p&gt;Handshake's research on the Class of 2026 in the AI economy found that 70% of hiring leaders say AI will change entry-level role requirements. [&lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" alt="Chart: 70% of hiring leaders say AI will change entry-level role requirements" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake Class of 2026 AI economy research&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is probably true. It also raises the question companies keep dodging:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are companies teaching AI-assisted engineering, or are they just adding AI to the list of things juniors are supposed to magically know?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The industry already expects juniors to understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Git&lt;/li&gt;
&lt;li&gt;testing&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;databases&lt;/li&gt;
&lt;li&gt;frontend frameworks&lt;/li&gt;
&lt;li&gt;deployment basics&lt;/li&gt;
&lt;li&gt;security basics&lt;/li&gt;
&lt;li&gt;agile workflow&lt;/li&gt;
&lt;li&gt;product communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prompt literacy&lt;/li&gt;
&lt;li&gt;AI code review&lt;/li&gt;
&lt;li&gt;tool privacy&lt;/li&gt;
&lt;li&gt;generated-code risk&lt;/li&gt;
&lt;li&gt;model limitations&lt;/li&gt;
&lt;li&gt;agent workflows&lt;/li&gt;
&lt;li&gt;AI policy compliance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a real skill stack. It needs training.&lt;/p&gt;

&lt;h2&gt;
  
  
  Older developers used shortcuts too
&lt;/h2&gt;

&lt;p&gt;Older developers often criticize juniors for using AI as if previous generations learned from pure fundamentals alone.&lt;/p&gt;

&lt;p&gt;That is not what happened.&lt;/p&gt;

&lt;p&gt;Previous generations learned through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stack Overflow answers&lt;/li&gt;
&lt;li&gt;blog snippets&lt;/li&gt;
&lt;li&gt;jQuery plugins&lt;/li&gt;
&lt;li&gt;Bootstrap templates&lt;/li&gt;
&lt;li&gt;WordPress themes&lt;/li&gt;
&lt;li&gt;forum posts&lt;/li&gt;
&lt;li&gt;copied config files&lt;/li&gt;
&lt;li&gt;outdated but useful tutorials&lt;/li&gt;
&lt;li&gt;internal code copied from another service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The issue was never "did the developer use outside help?"&lt;/p&gt;

&lt;p&gt;The issue was whether the developer understood the code before shipping it.&lt;/p&gt;

&lt;p&gt;That is still the standard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Smart AI use is not laziness
&lt;/h2&gt;

&lt;p&gt;Stack Overflow's 2025 survey says 84% of respondents are using or planning to use AI tools, and 44% used AI-enabled tools to learn coding techniques or a new language. [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;GitHub's Octoverse 2025 report says nearly 80% of new developers on GitHub used Copilot within their first week. [&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" alt="Chart: Developer AI adoption and learning signals, including Stack Overflow AI use and GitHub Copilot first-week usage for new developers" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt; and &lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is the world juniors are entering. Pretending otherwise is not discipline. It is denial.&lt;/p&gt;

&lt;p&gt;Lazy AI use looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;paste the output&lt;/li&gt;
&lt;li&gt;do not read it&lt;/li&gt;
&lt;li&gt;do not test it&lt;/li&gt;
&lt;li&gt;do not understand failure cases&lt;/li&gt;
&lt;li&gt;hide the tool use&lt;/li&gt;
&lt;li&gt;ship confidence without comprehension&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Smart AI-assisted learning looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ask for explanation&lt;/li&gt;
&lt;li&gt;compare with official docs&lt;/li&gt;
&lt;li&gt;generate test cases&lt;/li&gt;
&lt;li&gt;inspect edge cases&lt;/li&gt;
&lt;li&gt;rewrite in project style&lt;/li&gt;
&lt;li&gt;document assumptions&lt;/li&gt;
&lt;li&gt;ask a human for review where risk is high&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one deserves criticism. The second one deserves coaching.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real junior role has a smaller blast radius
&lt;/h2&gt;

&lt;p&gt;If companies want juniors to succeed, the job description should identify the first 90 days.&lt;/p&gt;

&lt;p&gt;Example of a bad junior scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Own the customer dashboard end-to-end across React, Node, PostgreSQL, AWS, CI/CD, analytics tracking, and production support.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example of a better junior scope:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In the first 90 days, ship small product fixes in the React dashboard, write tests for touched behavior, pair on API changes, and learn the deployment process with a mentor before joining the support rotation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That second version is still real work. It just does not pretend the junior is a full product team.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the job post should actually say
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Section&lt;/th&gt;
&lt;th&gt;What it should say&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Required skills&lt;/td&gt;
&lt;td&gt;The minimum needed on day one.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Teachable skills&lt;/td&gt;
&lt;td&gt;What the company expects to train.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First 30 days&lt;/td&gt;
&lt;td&gt;Onboarding, repo setup, first small fixes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First 90 days&lt;/td&gt;
&lt;td&gt;Expected independent scope.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mentorship&lt;/td&gt;
&lt;td&gt;Who reviews work and how often.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI policy&lt;/td&gt;
&lt;td&gt;Approved tools, disclosure rules, privacy limits.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Support expectations&lt;/td&gt;
&lt;td&gt;Whether production support is shadowed or owned.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Evaluation&lt;/td&gt;
&lt;td&gt;How the junior will be judged.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is not extra paperwork. It is basic hiring clarity.&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-34d7cb50-ab24-47cf-a36a-70f8d8d9f4db" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-34d7cb50-ab24-47cf-a36a-70f8d8d9f4db" alt="Chart: A realistic junior ramp grows scope from week one through month twelve instead of pretending day-one ownership is normal" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: Author framework for staged junior onboarding.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The leadership mistake
&lt;/h2&gt;

&lt;p&gt;Many leadership teams do not know whether they want:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an apprentice&lt;/li&gt;
&lt;li&gt;a junior developer&lt;/li&gt;
&lt;li&gt;a mid-level developer&lt;/li&gt;
&lt;li&gt;a full-stack generalist&lt;/li&gt;
&lt;li&gt;a platform engineer&lt;/li&gt;
&lt;li&gt;a cheap senior&lt;/li&gt;
&lt;li&gt;a product engineer&lt;/li&gt;
&lt;li&gt;a support engineer who can code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So they write all of it into one job description, then complain about the candidate pool.&lt;/p&gt;

&lt;p&gt;That is backwards. Bad requirements create bad hiring signals.&lt;/p&gt;

&lt;p&gt;If the role is confused, the hiring process will be confused.&lt;/p&gt;

&lt;p&gt;If the hiring process is confused, the team will reject good juniors for not being imaginary candidates.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI does not magically fix the gap
&lt;/h2&gt;

&lt;p&gt;AI does not fix this.&lt;/p&gt;

&lt;p&gt;It can even make the gap worse.&lt;/p&gt;

&lt;p&gt;The paper &lt;em&gt;The Widening Gap&lt;/em&gt; found that generative AI can help novice programmers, but it can also widen differences between learners who can evaluate suggestions and learners who accept bad output too easily. [&lt;a href="https://arxiv.org/abs/2405.17739" rel="noopener noreferrer"&gt;The Widening Gap&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;A 2025 systematic literature review on junior developers and LLMs found that most studies report both positive and negative perceptions of LLM adoption. [&lt;a href="https://arxiv.org/abs/2503.07556" rel="noopener noreferrer"&gt;Junior developers and LLMs SLR&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;That means AI can help juniors climb. It can also hide weak understanding.&lt;/p&gt;

&lt;p&gt;The difference is not moral character. The difference is training, review, and feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;Entry-level hiring is broken when the job description asks for a junior title, a mid-level skillset, a senior ownership model, and no mentorship plan.&lt;/p&gt;

&lt;p&gt;Companies can keep blaming juniors.&lt;/p&gt;

&lt;p&gt;Or they can write honest roles.&lt;/p&gt;

&lt;p&gt;If a company wants junior talent, it has to define what the junior is expected to know, what the company will teach, and how AI-assisted learning will be reviewed.&lt;/p&gt;

&lt;p&gt;Anything else is just a broken product spec disguised as hiring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tags/hiring" class="crayons-btn crayons-btn--primary"&gt;Interested in hiring, junior developers, and tech careers? Explore #hiring on DEV.&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>ai</category>
      <category>hiring</category>
      <category>career</category>
    </item>
    <item>
      <title>Companies Say There Are No Good Juniors. They Mean They Stopped Training Them"</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Wed, 29 Apr 2026 22:23:55 +0000</pubDate>
      <link>https://dev.to/bradleymatera/companies-say-there-are-no-good-juniors-they-mean-they-stopped-training-them-l68</link>
      <guid>https://dev.to/bradleymatera/companies-say-there-are-no-good-juniors-they-mean-they-stopped-training-them-l68</guid>
      <description>&lt;p&gt;Tech has a lazy line it keeps repeating:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"There are no good junior developers anymore."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It sounds like a talent diagnosis.&lt;/p&gt;

&lt;p&gt;It is usually a management confession.&lt;/p&gt;

&lt;p&gt;The industry spent years cutting apprenticeships, thinning mentorship, compressing onboarding, outsourcing training to bootcamps and universities, and turning entry-level job descriptions into mid-level wish lists.&lt;/p&gt;

&lt;p&gt;Now the same companies look at juniors using AI to learn and act shocked.&lt;/p&gt;

&lt;p&gt;That is not serious.&lt;/p&gt;

&lt;p&gt;AI did not create the junior developer problem. It exposed it.&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://giphy.com/gifs/clickup-teamwork-collaboration-productivity-qgTeviBmquASJZO08N" 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%2Fmedia3.giphy.com%2Fmedia%2Fv1.Y2lkPTc5MGI3NjExdndtNHVlY2hycjFoNWM3cmFmOW85OGd3ZjJ0a3Izb2YzYm96am84MSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw%2FqgTeviBmquASJZO08N%2Fgiphy.webp" height="270" class="m-0" width="480"&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://giphy.com/gifs/clickup-teamwork-collaboration-productivity-qgTeviBmquASJZO08N" rel="noopener noreferrer" class="c-link"&gt;
            Team Teamwork GIF by ClickUp - Find &amp;amp; Share on GIPHY
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            Discover &amp;amp; share this Team Teamwork GIF by ClickUp with everyone you know. GIPHY is how you search, share, discover, and create GIFs.
          &lt;/p&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%2Fgiphy.com%2Fstatic%2Fimg%2Ffavicon.png" width="16" height="16"&gt;
          giphy.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The pipeline is the problem
&lt;/h2&gt;

&lt;p&gt;Software is not a dying field.&lt;/p&gt;

&lt;p&gt;The U.S. Bureau of Labor Statistics projects employment for software developers to grow 15.8% from 2024 to 2034, adding 267,700 jobs. That is over five times faster than the all-occupation average in the same projection set. [&lt;a href="https://www.bls.gov/opub/mlr/2026/article/industry-and-occupational-employment-projections-overview.htm" rel="noopener noreferrer"&gt;BLS projections&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-e8590180-bec4-483b-b024-1505f77206c0" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-e8590180-bec4-483b-b024-1505f77206c0" alt="Chart: BLS projects software developer employment growing from about 1.69 million jobs in 2024 to about 1.96 million jobs in 2034" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://www.bls.gov/opub/mlr/2026/article/industry-and-occupational-employment-projections-overview.htm" rel="noopener noreferrer"&gt;BLS employment projections&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So no, the simple story is not "software is over."&lt;/p&gt;

&lt;p&gt;The problem is the pipeline.&lt;/p&gt;

&lt;p&gt;Companies still need software. They still need engineers. They still need future senior people.&lt;/p&gt;

&lt;p&gt;But many of them do not want to pay the cost of producing those senior people.&lt;/p&gt;

&lt;p&gt;They want developers who are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cheap enough to call junior&lt;/li&gt;
&lt;li&gt;experienced enough to ship like mid-levels&lt;/li&gt;
&lt;li&gt;broad enough to cover full-stack work&lt;/li&gt;
&lt;li&gt;mature enough to self-manage&lt;/li&gt;
&lt;li&gt;fast enough to justify headcount&lt;/li&gt;
&lt;li&gt;compliant enough not to challenge broken scope&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not a junior role.&lt;/p&gt;

&lt;p&gt;That is a budget fantasy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bar moved up
&lt;/h2&gt;

&lt;p&gt;The hiring market has been tightening around experience.&lt;/p&gt;

&lt;p&gt;Indeed Hiring Lab reported that between Q2 2022 and Q2 2025, the share of tech postings asking for at least five years of experience rose from 37% to 42%, while early-career candidates faced a harder environment after the tech posting decline. [&lt;a href="https://www.hiringlab.org/2025/07/30/experience-requirements-have-tightened-amid-the-tech-hiring-freeze/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-fd6e909d-1f7f-4b4f-8a83-b33e07070c37" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-fd6e909d-1f7f-4b4f-8a83-b33e07070c37" alt="Chart: Tech job postings asking for at least five years of experience rose from 37% in Q2 2022 to 42% in Q2 2025" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://www.hiringlab.org/2025/07/30/experience-requirements-have-tightened-amid-the-tech-hiring-freeze/" rel="noopener noreferrer"&gt;Indeed Hiring Lab&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;NACE's Job Outlook 2026 data shows employers are increasing skills-based hiring for entry-level roles. That sounds good until you remember that "skills-based" can mean "prove you already did the job somewhere else." [&lt;a href="https://www.naceweb.org/job-market/trends-and-predictions/employer-use-of-skills-based-hiring-practices-grows" rel="noopener noreferrer"&gt;NACE skills-based hiring&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;Handshake's research on the Class of 2026 in the AI economy found that 70% of hiring leaders say AI will change entry-level role requirements. [&lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-46c4a4ed-1f94-4084-bdb6-b06f85a267d5" alt="Chart: 70% of hiring leaders say AI will change entry-level role requirements" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://joinhandshake.com/blog/employers/what-does-ai-mean-for-early-talent-pipeline/" rel="noopener noreferrer"&gt;Handshake Class of 2026 AI economy research&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is the entry-level contradiction in plain English:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Company says&lt;/th&gt;
&lt;th&gt;Company often means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;"We want entry-level talent"&lt;/td&gt;
&lt;td&gt;We want someone already productive.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"We hire for skills"&lt;/td&gt;
&lt;td&gt;We want proof you have done production work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"AI is changing the role"&lt;/td&gt;
&lt;td&gt;We have not rewritten onboarding yet.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"There are no good juniors"&lt;/td&gt;
&lt;td&gt;We stopped building junior pipelines.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"We need ownership"&lt;/td&gt;
&lt;td&gt;We want low-management headcount.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is not a junior failure. It is hiring design failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  The old learning web is not enough anymore
&lt;/h2&gt;

&lt;p&gt;Older developers sometimes talk as if they learned in a cleaner era.&lt;/p&gt;

&lt;p&gt;They did not.&lt;/p&gt;

&lt;p&gt;They copied Stack Overflow answers. They pasted snippets from blogs. They modified WordPress themes. They followed YouTube tutorials. They used Bootstrap examples. They dropped in jQuery plugins. They learned from forums, old repos, templates, docs, and trial by fire.&lt;/p&gt;

&lt;p&gt;Some of that learning was deep.&lt;/p&gt;

&lt;p&gt;Some of it was shallow.&lt;/p&gt;

&lt;p&gt;That was always true.&lt;/p&gt;

&lt;p&gt;The difference now is that the old web is weaker as the main learning layer.&lt;/p&gt;

&lt;p&gt;Search results are noisier. Framework churn is faster. Tutorials age badly. Many of the most visible beginner resources for older tools are years old, while modern production expectations include testing, deployment, observability, security, accessibility, cloud platforms, CI/CD, API design, analytics, and AI tooling.&lt;/p&gt;

&lt;p&gt;The industry raised the floor while weakening the ladder.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI filled the hole
&lt;/h2&gt;

&lt;p&gt;Stack Overflow's 2025 Developer Survey says 84% of respondents are using or planning to use AI tools, up from 76% the year before. It also says 44% used AI-enabled tools to learn coding techniques or a new language. [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&lt;/a&gt;] [&lt;a href="https://stackoverflow.co/company/press/archive/stack-overflow-2025-developer-survey/" rel="noopener noreferrer"&gt;Stack Overflow press release&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-4abf537e-25cd-4472-ba99-d1df8df50aa2" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-4abf537e-25cd-4472-ba99-d1df8df50aa2" alt="Chart: Stack Overflow reported AI tool use or planned use rising from 76% in 2024 to 84% in 2025, while AI-enabled learning rose from 37% to 44%" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt; and &lt;a href="https://stackoverflow.co/company/press/archive/stack-overflow-2025-developer-survey/" rel="noopener noreferrer"&gt;Stack Overflow 2025 press release&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;GitHub's Octoverse 2025 report says nearly 80% of new developers on GitHub used GitHub Copilot within their first week. [&lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-2f39b837-f670-4a89-aff6-3bab69fe5190" alt="Chart: Developer AI adoption and learning signals, including Stack Overflow AI use and GitHub Copilot first-week usage for new developers" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt; and &lt;a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/" rel="noopener noreferrer"&gt;GitHub Octoverse 2025&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is not a weird side habit anymore. That is part of the learning surface.&lt;/p&gt;

&lt;p&gt;AI helps juniors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;explain unfamiliar code&lt;/li&gt;
&lt;li&gt;generate practice tasks&lt;/li&gt;
&lt;li&gt;translate documentation into plain English&lt;/li&gt;
&lt;li&gt;compare implementation options&lt;/li&gt;
&lt;li&gt;debug error messages&lt;/li&gt;
&lt;li&gt;create test cases&lt;/li&gt;
&lt;li&gt;rehearse interviews&lt;/li&gt;
&lt;li&gt;review resumes&lt;/li&gt;
&lt;li&gt;understand unfamiliar libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;None of that means the junior understands automatically.&lt;/p&gt;

&lt;p&gt;But it does mean AI is covering work teams used to handle through mentorship, pairing, code review, and onboarding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The catch: AI is wrong a lot
&lt;/h2&gt;

&lt;p&gt;The answer is not "AI good, juniors right, seniors bad."&lt;/p&gt;

&lt;p&gt;That would be cheap.&lt;/p&gt;

&lt;p&gt;AI output is often wrong.&lt;/p&gt;

&lt;p&gt;Stack Overflow's 2025 survey says more developers distrust AI output accuracy than trust it: 46% distrust versus 33% trust. The biggest frustration is that answers are "almost right, but not quite," cited by 66% of respondents. [&lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow AI survey&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%2Fquickchart.io%2Fchart%2Frender%2Fzf-0cb70d32-659d-4b1d-8407-981bc3a9d1ee" 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%2Fquickchart.io%2Fchart%2Frender%2Fzf-0cb70d32-659d-4b1d-8407-981bc3a9d1ee" alt="Chart: Stack Overflow 2025 shows 46% distrust AI output accuracy, 33% trust it, and 66% cite almost-right answers as a frustration" width="2000" height="1160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Source: &lt;a href="https://survey.stackoverflow.co/2025/ai" rel="noopener noreferrer"&gt;Stack Overflow 2025 Developer Survey&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is why juniors need training, not shame.&lt;/p&gt;

&lt;p&gt;The strongest junior AI workflow is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Generate the code and ship it."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Use AI to understand the problem, then verify the answer with docs, tests, code review, and actual system behavior."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Those are not the same workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The research is not a slogan
&lt;/h2&gt;

&lt;p&gt;The education research does not support a simple anti-AI panic.&lt;/p&gt;

&lt;p&gt;It supports a more serious claim: AI helps some learners and hurts others depending on how they use it.&lt;/p&gt;

&lt;p&gt;The 2024 paper &lt;em&gt;The Widening Gap: The Benefits and Harms of Generative AI for Novice Programmers&lt;/em&gt; observed 21 novice programming lab sessions. The researchers found that GenAI could help students complete tasks, but weaker students were more vulnerable to accepting incorrect or unhelpful suggestions. [&lt;a href="https://arxiv.org/abs/2405.17739" rel="noopener noreferrer"&gt;The Widening Gap&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;A 2025 systematic review on junior developers adopting LLMs found both positive and negative perceptions across most of the literature it reviewed. [&lt;a href="https://arxiv.org/abs/2503.07556" rel="noopener noreferrer"&gt;Junior developers and LLMs SLR&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;A 2025 review on GenAI and code comprehension found that generated explanations can support learning, but can also be inaccurate, unclear, or hard for novices to evaluate. [&lt;a href="https://arxiv.org/abs/2510.17894" rel="noopener noreferrer"&gt;Code comprehension SLR&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;That is not an argument for banning AI. It is an argument for teaching AI literacy as part of engineering literacy.&lt;/p&gt;

&lt;h2&gt;
  
  
  This is leadership work
&lt;/h2&gt;

&lt;p&gt;If a company hires juniors with no plan to teach them, it is not running a junior program. It is gambling.&lt;/p&gt;

&lt;p&gt;A real junior program needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;scoped work&lt;/li&gt;
&lt;li&gt;named mentors&lt;/li&gt;
&lt;li&gt;clear review standards&lt;/li&gt;
&lt;li&gt;onboarding tasks tied to production concepts&lt;/li&gt;
&lt;li&gt;time for questions&lt;/li&gt;
&lt;li&gt;code review that teaches reasoning&lt;/li&gt;
&lt;li&gt;documentation that is not tribal memory&lt;/li&gt;
&lt;li&gt;a path from small fixes to system ownership&lt;/li&gt;
&lt;li&gt;explicit AI usage rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most companies do not need a 12-month academy.&lt;/p&gt;

&lt;p&gt;They do need to stop pretending a junior becomes production-ready by osmosis while seniors are booked 110% and managers ask for "ownership" on week two.&lt;/p&gt;

&lt;h2&gt;
  
  
  Ask better questions
&lt;/h2&gt;

&lt;p&gt;Stop asking:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Why are juniors worse now?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Better question&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What do we expect a junior to know on day one?&lt;/td&gt;
&lt;td&gt;Prevents hidden mid-level expectations.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What do we teach in the first 90 days?&lt;/td&gt;
&lt;td&gt;Turns hiring into development.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Who reviews their work and how?&lt;/td&gt;
&lt;td&gt;Creates accountability for mentorship.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Which tasks are junior-safe but still real?&lt;/td&gt;
&lt;td&gt;Avoids fake work and impossible work.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What AI use is allowed?&lt;/td&gt;
&lt;td&gt;Prevents inconsistent punishment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do we test understanding?&lt;/td&gt;
&lt;td&gt;Separates learning from blind copying.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That is how companies get better juniors. Complaining on LinkedIn is not a training plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bottom line
&lt;/h2&gt;

&lt;p&gt;There are juniors. There are motivated graduates. There are self-taught developers doing the work.&lt;/p&gt;

&lt;p&gt;Many of them use AI because the modern learning stack is fragmented, outdated, noisy, and incomplete without it.&lt;/p&gt;

&lt;p&gt;The shortage is not curiosity. The shortage is serious training.&lt;/p&gt;

&lt;p&gt;If companies want senior engineers in five years, they need to build juniors now.&lt;/p&gt;

&lt;p&gt;If they refuse, they should stop blaming the generation that showed up after the ladder was already pulled up.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tags/career" class="crayons-btn crayons-btn--primary"&gt;Interested in junior developer hiring, AI, and tech careers? Explore #career on DEV.&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>hiring</category>
      <category>bestofdev</category>
      <category>career</category>
    </item>
    <item>
      <title>The Orphaned ID Bug from My First Job (And What It Taught Me About Being a Junior Dev)</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Tue, 28 Apr 2026 05:20:55 +0000</pubDate>
      <link>https://dev.to/bradleymatera/the-orphaned-id-bug-from-my-first-job-and-what-it-taught-me-about-being-a-junior-dev-2ojb</link>
      <guid>https://dev.to/bradleymatera/the-orphaned-id-bug-from-my-first-job-and-what-it-taught-me-about-being-a-junior-dev-2ojb</guid>
      <description>&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%2F4sb8uo1cuumu9p7h0anf.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%2F4sb8uo1cuumu9p7h0anf.gif" alt="frustrated" width="480" height="270"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About two weeks into my first web-dev job, I had a Trello card that said the LMS was sometimes leaving orphaned IDs behind when assigned trainings were finished or deleted.&lt;/p&gt;

&lt;p&gt;The app was a corporate LMS for a global manufacturer that made machine protection, chip and coolant management systems, and facility safety products.&lt;/p&gt;

&lt;p&gt;This was not a small internal team tool. It was the training system for the whole company, and they wanted every training assignment for anyone to go through this broken LMS.&lt;/p&gt;

&lt;p&gt;The frontend was simple: jQuery dialogs, table rows, and AJAX calls.&lt;/p&gt;

&lt;p&gt;The bug was not a dramatic React failure. It was a row-based edge case in a table view.&lt;/p&gt;

&lt;p&gt;Sometimes the AJAX response would arrive and the data would be missing. Sometimes the table would render, but an empty row would appear where an assignment should have been.&lt;/p&gt;

&lt;p&gt;That was enough for the card to hit the board and for me to start investigating.&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%2Fkavp99b0qps56ulua2tz.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%2Fkavp99b0qps56ulua2tz.gif" alt="bug report" width="540" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the bug was more than a blank row
&lt;/h2&gt;

&lt;p&gt;At first, it was easy to dismiss this as a rendering issue.&lt;/p&gt;

&lt;p&gt;Maybe the list component was failing to fill the template. Maybe the CSS was swallowing the text. Maybe the client was accidentally rendering an empty object.&lt;/p&gt;

&lt;p&gt;Then I opened the network tab.&lt;/p&gt;

&lt;p&gt;The API was returning assignment objects. Some of them had &lt;code&gt;training_id&lt;/code&gt;, some of them had &lt;code&gt;completed_at&lt;/code&gt;, and some of them had fields set to &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The client never filtered those out. It rendered every row it received.&lt;/p&gt;

&lt;p&gt;That meant the bug was not just on the page. It was in the data the page was given.&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%2Fyl98527j67un33ptn0ni.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%2Fyl98527j67un33ptn0ni.gif" alt="empty table row" width="500" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was told
&lt;/h2&gt;

&lt;p&gt;When I asked my senior for more context, the answer was basically, “Figure it out without AI.”&lt;/p&gt;

&lt;p&gt;That line was a punch in the face, because this was the same team that had told me they liked that I understood AI. The same team that had hired me after I talked about how I used free tools to speed up small fixes and keep my commits focused.&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%2Fzdrxyomzaxibexghyxtm.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%2Fzdrxyomzaxibexghyxtm.gif" alt="AI feedback" width="420" height="234"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was not being asked to build a feature. I was being asked to debug a failure in a system I did not own.&lt;/p&gt;

&lt;p&gt;I was not given:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the schema for &lt;code&gt;assigned_trainings&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the intended lifecycle of a completed assignment&lt;/li&gt;
&lt;li&gt;whether deletes were supposed to cascade&lt;/li&gt;
&lt;li&gt;whether &lt;code&gt;completed_trainings&lt;/code&gt; was supposed to be a source of truth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was only given the symptom and an expectation.&lt;/p&gt;

&lt;p&gt;That is a very common junior-dev situation: the problem is clear, but the contract is not.&lt;/p&gt;

&lt;p&gt;It got worse after I was fired.&lt;/p&gt;

&lt;p&gt;The official reason was that I used AI too much. I had spent one month on the job, made forty small commits, and the only real problem I had found was one that was creating blank rows in the UI.&lt;/p&gt;

&lt;p&gt;The contradiction stung. They paid for the work, accepted the fixes, and then told me they did not want my process. It left me angry, confused, and more than a little ashamed.&lt;/p&gt;

&lt;p&gt;That was the context I brought to the bug: a team that liked the results but disliked the tool, a junior dev who felt stuck between expectations and execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following the data trail like a junior detective
&lt;/h2&gt;

&lt;p&gt;Once I stopped looking at the UI and started looking at the database, the problem became more concrete.&lt;/p&gt;

&lt;p&gt;The symptoms were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;blank rows appeared after delete or completion&lt;/li&gt;
&lt;li&gt;the user record still existed&lt;/li&gt;
&lt;li&gt;the training record still existed in some form&lt;/li&gt;
&lt;li&gt;the list view did not know which rows were stale&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In plain English: the UI was still receiving references to assignments that had lost their parent record.&lt;/p&gt;

&lt;p&gt;That usually means one of two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the database is missing a foreign key constraint, or&lt;/li&gt;
&lt;li&gt;code that cleans up stale assignments is not running consistently.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I began checking the tables in the order the app was likely using them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;assigned_trainings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;completed_trainings&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;users&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trainings&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I was looking for rows that should have been gone but were still visible.&lt;/p&gt;

&lt;h2&gt;
  
  
  The SQL I wrote to prove the orphan
&lt;/h2&gt;

&lt;p&gt;I did not have a polished schema diagram. I had a terminal and a query editor.&lt;/p&gt;

&lt;p&gt;The first query I used was a simple orphan finder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&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;id&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;user_id&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;training_id&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;assigned_at&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;completed_id&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;assigned_trainings&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;completed_trainings&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;
  &lt;span class="k"&gt;ON&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;user_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;
  &lt;span class="k"&gt;AND&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;training_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;training_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="k"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That returned assignment rows that had no matching completion row.&lt;/p&gt;

&lt;p&gt;Then I extended it to catch assignments that referenced missing training metadata.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&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;id&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;user_id&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;training_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;training_title&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;assigned_trainings&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;trainings&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="k"&gt;ON&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;training_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;IS&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those queries were not meant to be elegant. They were meant to answer one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is there data in the system that should not still be shown?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer was yes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the SQL mattered more than the frontend
&lt;/h2&gt;

&lt;p&gt;This bug was not a broken component. It was stale data flowing through the app.&lt;/p&gt;

&lt;p&gt;The frontend code was basically doing this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fetch assignment rows&lt;/li&gt;
&lt;li&gt;render each row&lt;/li&gt;
&lt;li&gt;assume each row was valid&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was not validating status, it was not filtering by &lt;code&gt;deleted_at&lt;/code&gt;, and it was not checking whether the associated training still existed.&lt;/p&gt;

&lt;p&gt;That made the UI brittle.&lt;/p&gt;

&lt;p&gt;So I shifted the fix to the place where the contract belonged: the database.&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%2Fz0m54v96k1nerbtflem8.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%2Fz0m54v96k1nerbtflem8.gif" alt="debugging" width="480" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The cleanup fix I shipped
&lt;/h2&gt;

&lt;p&gt;I did not have enough confidence to rewrite the whole lifecycle.&lt;/p&gt;

&lt;p&gt;What I had enough confidence to do was this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Identify stale assignment rows with SQL&lt;/li&gt;
&lt;li&gt;Delete them in a controlled cleanup operation&lt;/li&gt;
&lt;li&gt;Confirm the UI stopped showing blank rows&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The frontend trigger was tiny:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/cleanup-orphans&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deleted orphans&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deletedCount&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 backend controller looked like this in rough form:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/cleanup-orphans&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="o"&gt;=&amp;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;orphanIds&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`
    SELECT a.id
    FROM assigned_trainings a
    LEFT JOIN completed_trainings c
      ON a.user_id = c.user_id
      AND a.training_id = c.training_id
    WHERE c.id IS NULL
  `&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;deleted&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE FROM assigned_trainings WHERE id = ANY($1)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;orphanIds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;row&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="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="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;deletedCount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;deleted&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rowCount&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also added a small log statement so I could see the number of deleted rows in the server output.&lt;/p&gt;

&lt;p&gt;This was not a permanent fix.&lt;/p&gt;

&lt;p&gt;It was a controlled cleanup that removed the broken rows and let the UI go back to behaving.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this taught me about junior work
&lt;/h2&gt;

&lt;p&gt;There are two kinds of fixes in a codebase like that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;quick patches that make the symptoms disappear&lt;/li&gt;
&lt;li&gt;deeper fixes that make the system enforce the invariant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A junior developer is often asked to deliver the first one while learning the second.&lt;/p&gt;

&lt;p&gt;This bug mattered because it exposed a gap in the system’s contract.&lt;/p&gt;

&lt;p&gt;The frontend expected valid assignment rows. The database did not guarantee them.&lt;/p&gt;

&lt;p&gt;Until that was fixed, the app was fragile.&lt;/p&gt;

&lt;p&gt;It also mattered because I was not just fixing a bug for a product. I was fixing a bug while trying to prove that I belonged in that role.&lt;/p&gt;

&lt;p&gt;After the firing, the problem became more than technical. It became personal.&lt;/p&gt;

&lt;p&gt;I was unemployed again. I had a recruiter apologizing on the phone. I had a wife and kids depending on me. I felt worthless for a day, then angry, then confused.&lt;/p&gt;

&lt;p&gt;That is what made the lack of guidance especially painful. I was being measured on results, but I was not given the information that would have led to a better result.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I wish someone had said
&lt;/h2&gt;

&lt;p&gt;If my senior had said any of the following, the work would have been clearer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“This looks like a data integrity problem, not a UI bug.”&lt;/li&gt;
&lt;li&gt;“We need to know whether assignment rows should be deleted, archived, or left as history.”&lt;/li&gt;
&lt;li&gt;“Check if the &lt;code&gt;assigned_trainings&lt;/code&gt; table has a foreign key on &lt;code&gt;user_id&lt;/code&gt;.”&lt;/li&gt;
&lt;li&gt;“Find out whether &lt;code&gt;completed_trainings&lt;/code&gt; is the source of truth.”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead I got, “Figure it out.”&lt;/p&gt;

&lt;p&gt;That is a useful outcome sometimes, but it is not a substitute for explaining the problem domain.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Blank rows are usually a data problem, not a render problem.&lt;/strong&gt;&lt;br&gt;
The UI can only show what it receives.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;A query is a debugger.&lt;/strong&gt;&lt;br&gt;
SQL is a powerful way to prove whether the data actually exists.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CRUD is not enough without constraints.&lt;/strong&gt;&lt;br&gt;
Adding a row is easy. Making sure it is still valid later is the hard part.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ask for the contract.&lt;/strong&gt;&lt;br&gt;
If you are told to fix something, ask what the data model is supposed to guarantee.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Patches are not the same as system fixes.&lt;/strong&gt;&lt;br&gt;
A cleanup endpoint can make the app behave, but the real fix is enforcing the invariant at the source.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  If I did the bug again today
&lt;/h2&gt;

&lt;p&gt;I would still start with the same questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What exactly should a completed assignment look like?&lt;/li&gt;
&lt;li&gt;Which table is the source of truth for assignment status?&lt;/li&gt;
&lt;li&gt;Should deletes remove the row, or should the row stay marked as completed?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I would also look for missing constraints and missing cleanup paths.&lt;/p&gt;

&lt;p&gt;In a better design, the database can help.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;assigned_trainings&lt;/span&gt;
&lt;span class="k"&gt;ADD&lt;/span&gt; &lt;span class="k"&gt;CONSTRAINT&lt;/span&gt; &lt;span class="n"&gt;fk_user&lt;/span&gt;
&lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;CASCADE&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That would cause the database to delete assignments automatically when the user is deleted.&lt;/p&gt;

&lt;p&gt;But even that is not always the right answer.&lt;/p&gt;

&lt;p&gt;If the business needs a record of completed training for audits, a history row is the right fix, not a cascade delete.&lt;/p&gt;

&lt;p&gt;That is why the first job of a debugging session is always: ask what the data should mean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final takeaways
&lt;/h2&gt;

&lt;p&gt;This story is not about one query or one jQuery call.&lt;/p&gt;

&lt;p&gt;It is about the way junior developer work often happens:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you are handed a symptom&lt;/li&gt;
&lt;li&gt;you are expected to turn it into a fix&lt;/li&gt;
&lt;li&gt;you may not be told what the system is supposed to enforce&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I fixed this bug with SQL, with a cleanup endpoint, and with enough caution to avoid deleting something live.&lt;/p&gt;

&lt;p&gt;It was not the perfect design.&lt;/p&gt;

&lt;p&gt;It was the right fix for the moment.&lt;/p&gt;

&lt;p&gt;The bigger lesson was not the query itself. It was how much the work depended on context.&lt;/p&gt;

&lt;p&gt;If I had been told whether this was supposed to be a one-time cleanup or a permanent contract, the answer could have looked very different.&lt;/p&gt;

&lt;p&gt;The code I wrote was useful. The team knowledge I did not get was the thing that would have made it better.&lt;/p&gt;

&lt;p&gt;If you are a junior dev, learn to ask for the data contract.&lt;/p&gt;

&lt;p&gt;If you are a senior dev, help the junior dev understand whether the fix is temporary or permanent.&lt;/p&gt;

&lt;p&gt;If you are a team, document your schema and your data assumptions before the blank rows appear.&lt;/p&gt;

&lt;p&gt;That is what separates a band-aid from a reliable system.&lt;/p&gt;

&lt;p&gt;This story is not just about a blank row in an LMS. It is about how much more fragile a junior engineer feels when the rules keep changing.&lt;/p&gt;

&lt;p&gt;A team can survive one fired junior dev if the work is real and the feedback is honest. It becomes a different problem when the team refuses to say what the contract is.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/tags/junior-dev" class="crayons-btn crayons-btn--primary"&gt;Want other junior dev stories? Explore #junior-dev on DEV.&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>jquery</category>
      <category>php</category>
      <category>ajax</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Testing Bifrost CLI and Code Mode: What Worked, What Broke, and What I Verified</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Mon, 27 Apr 2026 04:40:01 +0000</pubDate>
      <link>https://dev.to/bradleymatera/testing-bifrost-cli-and-code-mode-what-worked-what-broke-and-what-i-verified-7c3</link>
      <guid>https://dev.to/bradleymatera/testing-bifrost-cli-and-code-mode-what-worked-what-broke-and-what-i-verified-7c3</guid>
      <description>&lt;div class="ltag-slides ltag-slides--carousel"&gt;
  &lt;div class="ltag-slides__track"&gt;
    &lt;div class="ltag-slide"&gt;
      &lt;img class="ltag-slide__image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmaximhq%2Fbifrost%2Fmain%2Fdocs%2Fmedia%2Fgetting-started.png" alt="Bifrost quick start screenshot from the official repository" width="799" height="315"&gt;
      &lt;div class="ltag-slide__title"&gt;Bifrost Quick Start&lt;/div&gt;
&lt;/div&gt;


&lt;div class="ltag-slide"&gt;
      &lt;img class="ltag-slide__image" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmaximhq%2Fbifrost%2Fmain%2F.github%2Fassets%2Ffeatures.png" alt="Bifrost feature overview from the official repository" width="800" height="331"&gt;
      &lt;div class="ltag-slide__title"&gt;Bifrost Features&lt;/div&gt;
&lt;/div&gt;



  &lt;/div&gt;
    ‹
    ›
    &lt;div class="ltag-slides__dots"&gt;&lt;/div&gt;
    
      (function() {
        var container = document.currentScript.closest('.ltag-slides--carousel');
        var track = container.querySelector('.ltag-slides__track');
        var slides = track.querySelectorAll('.ltag-slide');
        var prevBtn = container.querySelector('.ltag-slides__nav--prev');
        var nextBtn = container.querySelector('.ltag-slides__nav--next');
        var dotsContainer = container.querySelector('.ltag-slides__dots');
        var current = 0;
        var total = slides.length;

        for (var i = 0; i &amp;lt; total; i++) {
          var dot = document.createElement('button');
          dot.className = 'ltag-slides__dot' + (i === 0 ? ' ltag-slides__dot--active' : '');
          dot.setAttribute('aria-label', 'Go to slide ' + (i + 1));
          dot.dataset.index = i;
          dot.addEventListener('click', function() { goTo(parseInt(this.dataset.index)); });
          dotsContainer.appendChild(dot);
        }

        function goTo(index) {
          current = ((index % total) + total) % total;
          track.style.transform = 'translateX(-' + (current * 100) + '%)';
          var dots = dotsContainer.querySelectorAll('.ltag-slides__dot');
          for (var i = 0; i &amp;lt; dots.length; i++) {
            dots[i].classList.toggle('ltag-slides__dot--active', i === current);
          }
        }

        prevBtn.addEventListener('click', function() { goTo(current - 1); });
        nextBtn.addEventListener('click', function() { goTo(current + 1); });
      })();
    
&lt;/div&gt;


&lt;p&gt;I spend a lot of time wiring AI coding tools together: VS Code, Copilot, Claude Code, Codex-style flows, local agents, and MCP servers.&lt;/p&gt;

&lt;p&gt;The problem is not the model anymore. It is the plumbing.&lt;/p&gt;

&lt;p&gt;Every new provider needs a key. Every MCP server adds another tool catalog. Every tool adds schema, API shapes, and prompt context.&lt;/p&gt;

&lt;p&gt;That is where Bifrost caught my attention.&lt;/p&gt;

&lt;p&gt;Bifrost is an open-source gateway from Maxim AI. It is not meant to replace models or agents. It is meant to sit between them and make the whole system easier to inspect and control.&lt;/p&gt;

&lt;p&gt;This test had a simple goal: start the gateway, route real model traffic through it, attach a filesystem MCP server, enable Code Mode, and see whether a coding agent could actually work through that stack.&lt;/p&gt;

&lt;p&gt;I also wanted practical answers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which key did this agent use?&lt;/li&gt;
&lt;li&gt;Which model did it call?&lt;/li&gt;
&lt;li&gt;Which tools could it reach?&lt;/li&gt;
&lt;li&gt;What did the run cost?&lt;/li&gt;
&lt;li&gt;Where could I inspect the logs?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the thread through this post. It is not a marketing summary. It is a field test of the local gateway, the CLI, provider routing, MCP setup, Code Mode, and a real coding-agent launch.&lt;/p&gt;

&lt;p&gt;Repository:&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/maximhq" rel="noopener noreferrer"&gt;
        maximhq
      &lt;/a&gt; / &lt;a href="https://github.com/maximhq/bifrost" rel="noopener noreferrer"&gt;
        bifrost
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fastest enterprise AI gateway (50x faster than LiteLLM) with adaptive load balancer, cluster mode, guardrails, 1000+ models support &amp;amp; &amp;lt;100 µs overhead at 5k RPS.
    &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;Bifrost AI Gateway&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://goreportcard.com/report/github.com/maximhq/bifrost/core" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7f7e70df9fdaaf4f485f59ca6bc0b5cbbf134d03dd5721da4e31f90f618fc304/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f6d6178696d68712f626966726f73742f636f7265" alt="Go Report Card"&gt;&lt;/a&gt;
&lt;a href="https://discord.gg/exN5KAydbU" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/282b7719f04b28f5959f5e1e17aee806d65f8eea3b862b57af350df0ab57be6f/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f68747470733a2f2f646973636f72642e67672f65784e354b41796462553f7374796c653d666c6174" alt="Discord badge"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/maximhq/bifrost" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8bc2db302c566210d14c09b278639a3f63f07def5fc635a8869e59c996b3100f/68747470733a2f2f636f6465636f762e696f2f67682f6d6178696d68712f626966726f73742f6272616e63682f6d61696e2f67726170682f62616467652e737667" alt="codecov"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b0899925aadfed8626116707178a4015d8cf4aaa0b80acb632cb4782c6dc7272/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6d6178696d68712f626966726f7374"&gt;&lt;img src="https://camo.githubusercontent.com/b0899925aadfed8626116707178a4015d8cf4aaa0b80acb632cb4782c6dc7272/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6d6178696d68712f626966726f7374" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://app.getpostman.com/run-collection/31642484-2ba0e658-4dcd-49f4-845a-0c7ed745b916?action=collection%2Ffork&amp;amp;source=rip_markdown&amp;amp;collection-url=entityId%3D31642484-2ba0e658-4dcd-49f4-845a-0c7ed745b916%26entityType%3Dcollection%26workspaceId%3D63e853c8-9aec-477f-909c-7f02f543150e" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/82ccefddb001e2caf9d399f1153fdda561cf3da341bb270e18644d516906bc64/68747470733a2f2f72756e2e7073746d6e2e696f2f627574746f6e2e737667" alt="Run In Postman"&gt;&lt;/a&gt;
&lt;a href="https://artifacthub.io/packages/search?repo=bifrost" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a6a3c734d6bd57fa8e1d508ac0cdba555bdbcd9191b29b32cf37a964b86b9c67/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f61727469666163746875622e696f2f62616467652f7265706f7369746f72792f626966726f7374" alt="Artifact Hub"&gt;&lt;/a&gt;
&lt;a href="https://github.com/maximhq/bifrost/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3cb44c15a532770a066ba8e61bf11506ad5400e5c61d48f6b639101e442bee79/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6178696d68712f626966726f7374" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The fastest way to build AI applications that never go down&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Bifrost is a high-performance AI gateway that unifies access to 23+ providers (OpenAI, Anthropic, AWS Bedrock, Google Vertex, and more) through a single OpenAI-compatible API. Deploy in seconds with zero configuration and get automatic failover, load balancing, semantic caching, and enterprise-grade features.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/maximhq/bifrost/./docs/media/getting-started.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmaximhq%2Fbifrost%2FHEAD%2F.%2Fdocs%2Fmedia%2Fgetting-started.png" alt="Get started"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Go from zero to production-ready AI gateway in under a minute.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Start Bifrost Gateway&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Install and run locally&lt;/span&gt;
npx -y @maximhq/bifrost

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Or use Docker&lt;/span&gt;
docker run -p 8080:8080 maximhq/bifrost&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Configure via Web UI&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Open the built-in web interface&lt;/span&gt;
open http://localhost:8080&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Make your first API call&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -X POST http://localhost:8080/v1/chat/completions \
  -H &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Content-Type: application/json&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; \
  -d &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;{&lt;/span&gt;
&lt;span class="pl-s"&gt;    "model": "openai/gpt-4o-mini",&lt;/span&gt;
&lt;span class="pl-s"&gt;    "messages": [{"role": "user", "content": "Hello, Bifrost!"}]&lt;/span&gt;
&lt;span class="pl-s"&gt;  }&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt; Your AI gateway is running with a web interface for visual configuration…&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/maximhq/bifrost" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Official setup docs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.getbifrost.ai/quickstart/gateway/setting-up" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;Open the official Bifrost gateway setup guide.&lt;/a&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  What I was actually testing
&lt;/h2&gt;

&lt;p&gt;MCP is useful because it gives AI agents a standard way to call tools. Those tools can be filesystem access, search, databases, internal APIs, browser automation, or anything else exposed through an MCP server.&lt;/p&gt;

&lt;p&gt;That sounds good until your tool list gets large.&lt;/p&gt;

&lt;p&gt;Classic MCP can put a big tool catalog into the model's context. With a few servers that is okay. With many servers, the model spends tokens just reading what tools exist.&lt;/p&gt;

&lt;p&gt;That is the problem I want to avoid.&lt;/p&gt;

&lt;p&gt;I do not want my coding agent spending context on every possible tool every time. I want it to discover what it needs and keep the prompt smaller.&lt;/p&gt;

&lt;p&gt;Bifrost's Code Mode is designed for that issue.&lt;/p&gt;

&lt;p&gt;So the question was not "does Bifrost look useful?" The question was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I install it, wire it into a real project, and see the tool-control layer work end to end?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Why the Bifrost CLI matters
&lt;/h2&gt;

&lt;p&gt;The gateway routes providers. The CLI is what makes the setup usable for coding agents.&lt;/p&gt;

&lt;p&gt;I wanted to avoid hand-editing agent config every time I switched models or providers.&lt;/p&gt;

&lt;p&gt;The workflow I tested was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launch the gateway&lt;/li&gt;
&lt;li&gt;run &lt;code&gt;bifrost-cli&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;pick a harness&lt;/li&gt;
&lt;li&gt;pick a model&lt;/li&gt;
&lt;li&gt;launch the agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CLI stores state under &lt;code&gt;~/.bifrost/&lt;/code&gt;, including gateway URL, selected model, and harness.&lt;/p&gt;

&lt;p&gt;That matters because it keeps the gateway and agent shared in one place instead of every agent maintaining a separate, brittle config.&lt;/p&gt;

&lt;p&gt;Supported harnesses in the docs included:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code&lt;/li&gt;
&lt;li&gt;Codex CLI&lt;/li&gt;
&lt;li&gt;Gemini CLI&lt;/li&gt;
&lt;li&gt;Opencode&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installation and integration
&lt;/h2&gt;

&lt;p&gt;I tested both ways to run the gateway.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local NPX
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx &lt;span class="nt"&gt;-y&lt;/span&gt; @maximhq/bifrost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/data:/app/data maximhq/bifrost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That gives you a dashboard at:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I always start there. If the dashboard does not respond, nothing else matters.&lt;/p&gt;
&lt;h3&gt;
  
  
  First smoke test
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Once the gateway was up, the next step was provider setup, MCP setup, and CLI testing.&lt;/p&gt;
&lt;h3&gt;
  
  
  First model request
&lt;/h3&gt;

&lt;p&gt;A basic OpenAI-compatible request looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "openai/gpt-4o-mini",
    "messages": [
      { "role": "user", "content": "Hello, Bifrost!" }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I did not use RunKit here because RunKit cannot reach &lt;code&gt;localhost:8080&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Add an MCP client and enable Code Mode
&lt;/h3&gt;

&lt;p&gt;The Bifrost path is:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Dashboard → MCP Gateway → add client → choose STDIO, HTTP, or SSE → configure command or URL → choose tool permissions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For this test, I used a STDIO filesystem MCP server scoped to the &lt;code&gt;donotpush&lt;/code&gt; draft folder.&lt;/p&gt;

&lt;p&gt;That scope matters. A gateway should not become an excuse to give every agent access to the whole machine.&lt;/p&gt;

&lt;p&gt;Once the MCP client exists, Code Mode can be enabled for that client. When Code Mode is on, the model does not get the full tool catalog directly. It gets four meta-tools first, then inspects and executes only what it needs.&lt;/p&gt;
&lt;h2&gt;
  
  
  Where Code Mode fits in
&lt;/h2&gt;

&lt;p&gt;This was the part I cared about most.&lt;/p&gt;

&lt;p&gt;Classic MCP can work fine. It can also force the model to carry a lot of extra tool metadata.&lt;/p&gt;

&lt;p&gt;Code Mode is meant to change that.&lt;/p&gt;

&lt;p&gt;Bifrost exposes these four meta-tools:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;listToolFiles
readToolFile
getToolDocs
executeToolCode
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That means the model can ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;what tool files are available?&lt;/li&gt;
&lt;li&gt;what is in this stub?&lt;/li&gt;
&lt;li&gt;what are the docs for this tool?&lt;/li&gt;
&lt;li&gt;execute this code against the tool binding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is to give the model an index instead of a giant binder.&lt;/p&gt;
&lt;h3&gt;
  
  
  Why Code Mode exists
&lt;/h3&gt;

&lt;p&gt;The problem is context bloat. In a small MCP setup, every tool definition may be fine. In a larger setup, it becomes waste.&lt;/p&gt;

&lt;p&gt;Bifrost's docs use an example with five MCP servers and around 100 tools. In the classic flow, the model carries that catalog across multiple turns. In Code Mode, it carries only four meta-tools and then loads the specific stubs it needs.&lt;/p&gt;

&lt;p&gt;This is why Code Mode uses code instead of a long chain of individual tool calls. The model can orchestrate the workflow in a constrained Starlark interpreter, and intermediate results do not have to get pushed back through the model.&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance and cost claims
&lt;/h3&gt;

&lt;p&gt;Bifrost's docs claim that for about 100 tools across five MCP servers, Code Mode can cut the interaction shape from six LLM turns with a full catalog to three or four turns with about 50 tool-definition tokens.&lt;/p&gt;

&lt;p&gt;Their published benchmark goes further: 55.7% lower estimated cost with 96 tools, 83.4% with 251 tools, and 92.2% with 508 tools.&lt;/p&gt;

&lt;p&gt;Those are vendor claims. I am including them here because they explain why the feature is worth testing, not because my one-server filesystem test reproduced them.&lt;/p&gt;
&lt;h3&gt;
  
  
  When I would enable it
&lt;/h3&gt;

&lt;p&gt;My rule of thumb after this pass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep classic MCP for one or two small servers&lt;/li&gt;
&lt;li&gt;enable Code Mode when you have three or more MCP servers&lt;/li&gt;
&lt;li&gt;enable it for heavier servers like filesystem, search, docs, databases, CRM, or internal APIs&lt;/li&gt;
&lt;li&gt;use tool-level binding when one server has many tools or big schemas&lt;/li&gt;
&lt;li&gt;keep the allowed tool list tight either way&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  How it works
&lt;/h3&gt;

&lt;p&gt;Code Mode exposes MCP tools as virtual &lt;code&gt;.pyi&lt;/code&gt; stub files. There are two binding levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;server-level binding: one stub file per MCP server&lt;/li&gt;
&lt;li&gt;tool-level binding: one stub file per tool&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Server-level binding is simpler when a server has a small tool set. Tool-level binding is better when a server has many tools or large schemas.&lt;/p&gt;

&lt;p&gt;The code runs in Starlark, a deterministic Python-like runtime. Bifrost's docs describe it as intentionally constrained: no imports, no file I/O, no network access, just allowed tool calls and basic Python-like logic. That constraint is what makes Code Mode interesting for agent workflows.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  "Classic MCP vs Code Mode in plain English"
  &lt;br&gt;
Classic MCP is like handing someone a giant binder full of every tool manual before every task.

&lt;p&gt;Code Mode is more like giving them a small index first. They look up the exact tool they need, read only that tool's instructions, then run the task.&lt;/p&gt;

&lt;p&gt;That matters when the number of tools grows.&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why that matters for coding agents
&lt;/h2&gt;

&lt;p&gt;Coding agents already use a lot of context.&lt;/p&gt;

&lt;p&gt;They read files, inspect diffs, look at errors, review stack traces, and sometimes pull in project history. If they also carry every connected MCP tool definition on every request, the context gets noisy fast.&lt;/p&gt;

&lt;p&gt;That can hurt:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;cost&lt;/li&gt;
&lt;li&gt;latency&lt;/li&gt;
&lt;li&gt;tool selection&lt;/li&gt;
&lt;li&gt;reliability&lt;/li&gt;
&lt;li&gt;debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For small setups, this may not matter. If you only have one or two MCP servers with a few tools, classic MCP can be fine.&lt;/p&gt;

&lt;p&gt;But once you start connecting heavier tools, Code Mode makes more sense.&lt;/p&gt;

&lt;p&gt;That is why I tested the flow directly instead of only repeating the docs.&lt;/p&gt;
&lt;h2&gt;
  
  
  What I tested
&lt;/h2&gt;

&lt;p&gt;My test setup used the tools I actually work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VS Code&lt;/li&gt;
&lt;li&gt;Bifrost gateway&lt;/li&gt;
&lt;li&gt;Bifrost CLI&lt;/li&gt;
&lt;li&gt;Codex CLI and OpenCode&lt;/li&gt;
&lt;li&gt;one filesystem MCP server&lt;/li&gt;
&lt;li&gt;a real local project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test needed to answer one practical question: can the gateway sit between the agent, the provider, and the MCP server without turning the workflow into a black box?&lt;/p&gt;

&lt;p&gt;The flow looked like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Start Bifrost gateway
↓
Open Bifrost dashboard
↓
Configure provider
↓
Start Bifrost CLI
↓
Launch coding agent through Bifrost
↓
Run a small repo task
↓
Compare classic MCP flow vs Code Mode flow
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The task was intentionally small. I did not want a fake benchmark. I wanted enough proof to answer this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can I route a coding agent through Bifrost, expose MCP tools, turn on Code Mode, and see the control layer working?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Everything after this point is evidence for that question.&lt;/p&gt;
&lt;h2&gt;
  
  
  The small agent task
&lt;/h2&gt;

&lt;p&gt;For the coding-agent check, I used a deliberately small prompt:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Do not edit files. Reply with exactly: opencode through bifrost ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That prompt is boring on purpose. It does not prove the agent can solve every repo task. It proves the path: agent starts, uses the configured Bifrost provider, calls the model through the gateway, and returns a response.&lt;/p&gt;

&lt;p&gt;Then I split the MCP behavior into two questions:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Classic MCP:
- Did the model see the direct filesystem tools?
- Did it produce a normal MCP tool call?
- Could I execute that tool call through Bifrost?

Code Mode:
- Could I enable Code Mode on the MCP client?
- Did the four meta-tools work?
- Could executeToolCode call the underlying filesystem server?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  What I am not claiming
&lt;/h2&gt;

&lt;p&gt;This is not a benchmark.&lt;/p&gt;

&lt;p&gt;Bifrost publishes token-savings numbers for Code Mode. My test did not try to reproduce those claims.&lt;/p&gt;

&lt;p&gt;I only used one filesystem MCP server. With one server, there is not enough tool sprawl to make a serious token-savings claim. The useful result is narrower:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gateway&lt;/li&gt;
&lt;li&gt;provider route&lt;/li&gt;
&lt;li&gt;local Ollama&lt;/li&gt;
&lt;li&gt;Ollama cloud&lt;/li&gt;
&lt;li&gt;MCP server&lt;/li&gt;
&lt;li&gt;Code Mode meta-tools&lt;/li&gt;
&lt;li&gt;coding agent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the difference between "I read the docs" and "I ran the workflow."&lt;/p&gt;
&lt;h2&gt;
  
  
  What I measured
&lt;/h2&gt;

&lt;p&gt;I also have Ollama installed locally, with both local models and Ollama cloud variants available. That let me test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local Ollama model routing&lt;/li&gt;
&lt;li&gt;Ollama cloud model routing&lt;/li&gt;
&lt;li&gt;Bifrost provider behavior&lt;/li&gt;
&lt;li&gt;MCP tool discovery&lt;/li&gt;
&lt;li&gt;Code Mode meta-tool behavior&lt;/li&gt;
&lt;li&gt;one coding-agent launch through Bifrost&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the checklist from the hands-on pass:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install/setup:
- [x] NPX start cleanly
- [x] Docker start cleanly
- [x] Dashboard available at localhost:8080
- [x] Provider setup persists
- [x] OpenAI config bootstrap tested
- [ ] OpenAI provider request blocked by missing OPENAI_API_KEY

CLI:
- [x] Bifrost CLI detects the gateway
- [x] Bifrost CLI asks for the expected config
- [x] Bifrost CLI shows Codex CLI as installed
- [x] Bifrost CLI lets me set the gateway URL and model
- [x] Config is stored in ~/.bifrost/config.json and ~/.bifrost/state.json
- [x] Bifrost CLI launches Codex CLI
- [x] Bifrost CLI prints the MCP server URL for Codex CLI
- [x] Codex CLI launch works
- [ ] Codex CLI request blocked because current Codex expects Responses API for this route

MCP:
- [x] Add at least one MCP server
- [x] Gateway can see the tools
- [x] Model can produce a classic MCP tool call
- [x] Classic MCP tool call works
- [x] Enable Code Mode
- [x] Code Mode exposes the four meta-tools
- [x] Run the same "list allowed directories" task with classic MCP and Code Mode
- [x] Route local Ollama models through Bifrost
- [x] Route Ollama cloud models through Bifrost

Agent workflow:
- [x] Complete a minimal coding-agent request through Bifrost with OpenCode
- [x] Keep the response understandable
- [x] Confirm tool-governed filesystem access through MCP
- [ ] OpenAI-vs-Ollama provider fallback blocked by missing OpenAI key
- [out of scope] Prove token savings with a large multi-server setup

Cost/context:
- [out of scope] Fewer tokens used in a realistic multi-server setup
- [x] Latency is acceptable for small local tests
- [x] Workflow is inspectable from one gateway dashboard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This is the evidence I care about more than a marketing number: what launched, what routed, what exposed tools, what returned output, and what failed.&lt;/p&gt;

&lt;p&gt;The unresolved items were clear: OpenAI fallback needs a real key, Codex needs a Responses-compatible route, and a larger multi-server setup is required for any real token-savings claim.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hands-on results
&lt;/h2&gt;

&lt;p&gt;The first thing I verified was the gateway.&lt;/p&gt;

&lt;p&gt;I started the local gateway and confirmed &lt;code&gt;http://127.0.0.1:8080&lt;/code&gt; was alive.&lt;/p&gt;

&lt;p&gt;The dashboard loaded cleanly.&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%2Fk7am4r8ixzrmoeo6pe0u.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%2Fk7am4r8ixzrmoeo6pe0u.png" alt="Bifrost dashboard after local requests" width="800" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That dashboard is useful because it gives a second source of truth. It shows request volume, token usage, model usage, latency, cache state, and cost.&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%2Fzvyuygjhdxnr06fnm6zk.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%2Fzvyuygjhdxnr06fnm6zk.png" alt="Bifrost dashboard main observability grid" width="800" height="915"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the panels were meaningful for this test.&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%2F1bi7qk479kyuqahsn1b3.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%2F1bi7qk479kyuqahsn1b3.gif" alt="Bifrost dashboard tour through request volume, token usage, cache, model usage, and latency" width="800" height="791"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With that working, I moved to provider wiring.&lt;/p&gt;

&lt;p&gt;The Bifrost CLI defaulted to &lt;code&gt;Codex CLI&lt;/code&gt;. I chose &lt;code&gt;openai-ollama2/gpt-oss:20b-cloud&lt;/code&gt; after confirming the custom provider could route Ollama cloud requests.&lt;/p&gt;

&lt;p&gt;On disk, the CLI state was exactly where I expected:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;~/.bifrost/config.json&lt;/code&gt; pointed at &lt;code&gt;http://localhost:8080&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;~/.bifrost/state.json&lt;/code&gt; stored the selected harness and model&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;./bifrost-data/config.db&lt;/code&gt; had the usual config tables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I also checked the repo &lt;code&gt;.env&lt;/code&gt;. It had project secrets, but not an OpenAI key for Bifrost.&lt;/p&gt;

&lt;p&gt;So I did one more bootstrap test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;created &lt;code&gt;bifrost-temp/config.json&lt;/code&gt; with &lt;code&gt;providers.openai.keys[0].value = "env.OPENAI_API_KEY"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;launched Bifrost on &lt;code&gt;http://127.0.0.1:8081&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the gateway started and wrote state to &lt;code&gt;./config.db&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;the provider row existed, but Bifrost reported "no valid keys found for provider: openai"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That was the exact failure mode: the key was missing from the shell.&lt;/p&gt;
&lt;h2&gt;
  
  
  Ollama routing worked
&lt;/h2&gt;

&lt;p&gt;With OpenAI blocked by a missing secret, I tested the local provider I could fully verify: Ollama.&lt;/p&gt;

&lt;p&gt;I started &lt;code&gt;ollama serve&lt;/code&gt; on &lt;code&gt;http://127.0.0.1:11434&lt;/code&gt; and confirmed the API exposed models such as &lt;code&gt;gemma3:1b&lt;/code&gt;, &lt;code&gt;qwen3-coder:30b&lt;/code&gt;, &lt;code&gt;tinyllama:latest&lt;/code&gt;, and &lt;code&gt;mistral:latest&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;I configured a custom Bifrost provider through &lt;code&gt;/api/providers&lt;/code&gt;. The right pattern for Ollama was a key with an empty &lt;code&gt;models&lt;/code&gt; list, which allows all models through.&lt;/p&gt;

&lt;p&gt;The provider config looked like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openai-ollama2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"keys"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openai-ollama2-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dummy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"weight"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"network_config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"base_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:11434"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"default_request_timeout_in_seconds"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"custom_provider_config"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"base_provider_type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"openai"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowed_requests"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"chat_completion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"chat_completion_stream"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With that in place, Bifrost routed both local Ollama and Ollama cloud requests.&lt;/p&gt;

&lt;p&gt;The request volume panel captured the setup process honestly: successful checks and tuning failures.&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%2Fm0ypstaorfh0k38axpvm.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%2Fm0ypstaorfh0k38axpvm.png" alt="Bifrost request volume panel showing successful and failed local test requests" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The token usage panel was not a benchmark, but it gave me a baseline.&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%2Frdwmiz4vvml43dz9enet.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%2Frdwmiz4vvml43dz9enet.png" alt="Bifrost token usage panel after local and cloud Ollama requests" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model usage panel confirmed the requests were hitting the models I 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%2Fp140pz0e844qnqz9c08a.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%2Fp140pz0e844qnqz9c08a.png" alt="Bifrost model usage panel showing gemma3 and another routed model" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Latency was uneven, which is no surprise for mixed local/cloud routing.&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%2F3j6m4o36krj2v7lkgp6g.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%2F3j6m4o36krj2v7lkgp6g.png" alt="Bifrost latency panel after gateway requests" width="800" height="612"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cache was effectively unused in this small test.&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%2Fq9gt24lv8lo17hy0v6ee.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%2Fq9gt24lv8lo17hy0v6ee.png" alt="Bifrost cache hit rate panel showing no cached input tokens in this small test" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also verified the Docker path on &lt;code&gt;http://127.0.0.1:8082&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8082:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;pwd&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;/bifrost-temp:/app/data maximhq/bifrost
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That instance also responded.&lt;/p&gt;

&lt;p&gt;At that point the provider layer was proven enough to move on.&lt;/p&gt;
&lt;h2&gt;
  
  
  Classic MCP versus Code Mode
&lt;/h2&gt;

&lt;p&gt;Next, I added a filesystem MCP server scoped to the &lt;code&gt;donotpush&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8080/api/mcp/client &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "filesystem_blog",
    "connection_type": "stdio",
    "stdio_config": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/bradleymatera/Desktop/gatsby-starter-minimal-blog/donotpush"
      ],
      "envs": ["HOME", "PATH"]
    },
    "tools_to_execute": ["*"],
    "is_ping_available": false
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Bifrost discovered 14 tools from that server.&lt;/p&gt;

&lt;p&gt;In classic MCP mode, the model produced a direct tool call:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;filesystem_blog-list_allowed_directories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;I executed it through Bifrost:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST http://127.0.0.1:8080/v1/mcp/tool/execute &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "id": "call_pjlop9a3",
    "type": "function",
    "function": {
      "name": "filesystem_blog-list_allowed_directories",
      "arguments": "{}"
    }
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Allowed directories:
/Users/bradleymatera/Desktop/gatsby-starter-minimal-blog/donotpush
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is the governance point in miniature: the server only saw one draft folder.&lt;/p&gt;

&lt;p&gt;Then I flipped the same client into Code Mode.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; PUT http://127.0.0.1:8080/api/mcp/client/f771c023-8a16-4b34-b03f-ffbfffd34e4b &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "name": "filesystem_blog",
    "connection_type": "stdio",
    "stdio_config": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/bradleymatera/Desktop/gatsby-starter-minimal-blog/donotpush"
      ],
      "envs": ["HOME", "PATH"]
    },
    "tools_to_execute": ["*"],
    "is_ping_available": false,
    "is_code_mode_client": true
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The four Code Mode meta-tools worked.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listToolFiles&lt;/code&gt; returned:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;servers/
  filesystem_blog.pyi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;readToolFile&lt;/code&gt; returned a compact stub with signatures like:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def read_text_file(path: str, head: float = None, tail: float = None) -&amp;gt; dict
def list_allowed_directories() -&amp;gt; dict
def list_directory(path: str) -&amp;gt; dict
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;getToolDocs&lt;/code&gt; returned docs for a specific function.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;executeToolCode&lt;/code&gt; ran the filesystem server from inside the Code Mode layer:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Execution completed successfully.
Return value: "Allowed directories:\n/Users/bradleymatera/Desktop/gatsby-starter-minimal-blog/donotpush"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So the behavior matched the docs. The model saw a small tool-file surface first, then executed the specific tool binding it needed.&lt;/p&gt;

&lt;p&gt;The task was the same in both modes:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List the allowed filesystem directory.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Classic MCP exposed the filesystem tools directly. Code Mode exposed a smaller meta-tool surface.&lt;/p&gt;

&lt;p&gt;On this setup, I am not claiming savings. I am claiming behavior verification.&lt;/p&gt;
&lt;h2&gt;
  
  
  Coding agent results
&lt;/h2&gt;

&lt;p&gt;The final step was the coding-agent launch.&lt;/p&gt;

&lt;p&gt;Bifrost CLI launched Codex CLI and showed:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Harness       Codex CLI (codex-cli 0.125.0)
Model         openai-ollama2/gpt-oss:20b-cloud
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It also printed:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MCP: Codex CLI has no native auto-attach yet. Use server URL: http://localhost:8080/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;So the launch path worked.&lt;/p&gt;

&lt;p&gt;But the actual Codex request did not complete. Codex expects the Responses API, while my Ollama route was using chat completions.&lt;/p&gt;

&lt;p&gt;Codex reported:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error loading config.toml: `wire_api = "chat"` is no longer supported.
How to fix: set `wire_api = "responses"` in your provider config.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That is a real provider compatibility issue, not a gateway failure.&lt;/p&gt;

&lt;p&gt;For the working agent test, I used OpenCode, which supports OpenAI-compatible chat completions.&lt;/p&gt;

&lt;p&gt;The config was:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://opencode.ai/config.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"model"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bifrost/openai-ollama2/gpt-oss:20b-cloud"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"provider"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bifrost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"npm"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"@ai-sdk/openai-compatible"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Bifrost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"options"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:8080/v1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"apiKey"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dummy"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"models"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"openai-ollama2/gpt-oss:20b-cloud"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ollama cloud through Bifrost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="nl"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;32768&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"output"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then I ran:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;OPENCODE_CONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;/tmp/bifrost-opencode.json opencode run &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--dir&lt;/span&gt; /Users/bradleymatera/Desktop/gatsby-starter-minimal-blog &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--model&lt;/span&gt; bifrost/openai-ollama2/gpt-oss:20b-cloud &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Do not edit files. Reply with exactly: opencode through bifrost ok'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Result:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;opencode through bifrost ok
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Usage reported:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;17154 total tokens
17100 input tokens
54 output tokens
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That was the first real coding-agent request through Bifrost in this test.&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%2Fc00e5lwxuq3prp5hq836.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%2Fc00e5lwxuq3prp5hq836.png" alt="Bifrost terminal results for provider routing, MCP, Code Mode, and OpenCode" width="800" height="1109"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Why governance matters here
&lt;/h2&gt;

&lt;p&gt;This setup is not just about making a request succeed.&lt;/p&gt;

&lt;p&gt;It is about making the request visible and controllable.&lt;/p&gt;

&lt;p&gt;A gateway lets you answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which virtual key was used?&lt;/li&gt;
&lt;li&gt;which provider routed the request?&lt;/li&gt;
&lt;li&gt;which MCP server was available?&lt;/li&gt;
&lt;li&gt;what did the dashboard record?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That matters more than one successful completion.&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%2Fke1uzqt147p7ucgd22op.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%2Fke1uzqt147p7ucgd22op.png" alt="Bifrost control plane sidebar showing observability, models, MCP gateway, governance, and guardrails" width="760" height="3833"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bifrost also surfaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;virtual keys&lt;/li&gt;
&lt;li&gt;budget controls&lt;/li&gt;
&lt;li&gt;provider routing&lt;/li&gt;
&lt;li&gt;MCP tool governance&lt;/li&gt;
&lt;li&gt;audit logs&lt;/li&gt;
&lt;li&gt;cost tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is not only enterprise language. Even for solo projects, it is useful to know what key is being used, what model is being called, and what tools the agent can reach.&lt;/p&gt;

&lt;p&gt;If I am running multiple demos or experiments, I want separate keys, usage tracking, and some protection against accidental spending.&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%2Fbztb7otrdquyj40j8han.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%2Fbztb7otrdquyj40j8han.png" alt="Bifrost governance navigation showing virtual keys, users, teams, roles, audit logs, and guardrails" width="760" height="2227"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Bifrost as the control plane
&lt;/h2&gt;

&lt;p&gt;Without Bifrost, the setup looks like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → Provider
Agent → MCP server
Agent → another provider
Agent → another tool config
Agent → another local config file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With Bifrost:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → Bifrost → Providers
              → MCP tools
              → routing
              → governance
              → logs
              → cost tracking
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That second layout is easier to reason about.&lt;/p&gt;

&lt;p&gt;It does not make agents perfect, but it does make the system easier to inspect.&lt;/p&gt;
&lt;h2&gt;
  
  
  Benefits and limitations
&lt;/h2&gt;

&lt;p&gt;What was clear from this pass:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the gateway is easy to start with NPX or Docker&lt;/li&gt;
&lt;li&gt;the dashboard makes traffic, latency, tokens, and errors visible&lt;/li&gt;
&lt;li&gt;the CLI reduces per-agent setup work&lt;/li&gt;
&lt;li&gt;the CLI can switch between supported agents without hand-editing every config&lt;/li&gt;
&lt;li&gt;virtual keys, audit logs, and budget controls add governance&lt;/li&gt;
&lt;li&gt;Code Mode turns the MCP surface into a smaller discovery-and-execute flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What was also clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code Mode is not a magic switch. It is worth validating in every environment.&lt;/li&gt;
&lt;li&gt;Classic MCP can still be the better choice for very small setups.&lt;/li&gt;
&lt;li&gt;Provider compatibility matters. One OpenAI-compatible route is not the same as another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My local dashboard was on &lt;code&gt;v1.4.24&lt;/code&gt;. The docs call out Code Mode from &lt;code&gt;v1.4.0-prerelease1&lt;/code&gt;. That is a good reminder: verify the exact version where you run this.&lt;/p&gt;

&lt;p&gt;The provider-specific limitation was real. OpenCode worked through Bifrost + Ollama. Codex CLI launched, but the request failed because the route needed Responses compatibility.&lt;/p&gt;

&lt;p&gt;That is not a reason to discard the setup. It is a reason to test each agent/provider pair instead of assuming every OpenAI-compatible route behaves identically.&lt;/p&gt;
&lt;h2&gt;
  
  
  Related reading
&lt;/h2&gt;

&lt;p&gt;Bifrost GitHub repository:&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/maximhq" rel="noopener noreferrer"&gt;
        maximhq
      &lt;/a&gt; / &lt;a href="https://github.com/maximhq/bifrost" rel="noopener noreferrer"&gt;
        bifrost
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Fastest enterprise AI gateway (50x faster than LiteLLM) with adaptive load balancer, cluster mode, guardrails, 1000+ models support &amp;amp; &amp;lt;100 µs overhead at 5k RPS.
    &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;Bifrost AI Gateway&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://goreportcard.com/report/github.com/maximhq/bifrost/core" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/7f7e70df9fdaaf4f485f59ca6bc0b5cbbf134d03dd5721da4e31f90f618fc304/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f6d6178696d68712f626966726f73742f636f7265" alt="Go Report Card"&gt;&lt;/a&gt;
&lt;a href="https://discord.gg/exN5KAydbU" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/282b7719f04b28f5959f5e1e17aee806d65f8eea3b862b57af350df0ab57be6f/68747470733a2f2f646362616467652e6c696d65732e70696e6b2f6170692f7365727665722f68747470733a2f2f646973636f72642e67672f65784e354b41796462553f7374796c653d666c6174" alt="Discord badge"&gt;&lt;/a&gt;
&lt;a href="https://codecov.io/gh/maximhq/bifrost" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8bc2db302c566210d14c09b278639a3f63f07def5fc635a8869e59c996b3100f/68747470733a2f2f636f6465636f762e696f2f67682f6d6178696d68712f626966726f73742f6272616e63682f6d61696e2f67726170682f62616467652e737667" alt="codecov"&gt;&lt;/a&gt;
&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/b0899925aadfed8626116707178a4015d8cf4aaa0b80acb632cb4782c6dc7272/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6d6178696d68712f626966726f7374"&gt;&lt;img src="https://camo.githubusercontent.com/b0899925aadfed8626116707178a4015d8cf4aaa0b80acb632cb4782c6dc7272/68747470733a2f2f696d672e736869656c64732e696f2f646f636b65722f70756c6c732f6d6178696d68712f626966726f7374" alt="Docker Pulls"&gt;&lt;/a&gt;
&lt;a href="https://app.getpostman.com/run-collection/31642484-2ba0e658-4dcd-49f4-845a-0c7ed745b916?action=collection%2Ffork&amp;amp;source=rip_markdown&amp;amp;collection-url=entityId%3D31642484-2ba0e658-4dcd-49f4-845a-0c7ed745b916%26entityType%3Dcollection%26workspaceId%3D63e853c8-9aec-477f-909c-7f02f543150e" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/82ccefddb001e2caf9d399f1153fdda561cf3da341bb270e18644d516906bc64/68747470733a2f2f72756e2e7073746d6e2e696f2f627574746f6e2e737667" alt="Run In Postman"&gt;&lt;/a&gt;
&lt;a href="https://artifacthub.io/packages/search?repo=bifrost" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a6a3c734d6bd57fa8e1d508ac0cdba555bdbcd9191b29b32cf37a964b86b9c67/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f75726c3d68747470733a2f2f61727469666163746875622e696f2f62616467652f7265706f7369746f72792f626966726f7374" alt="Artifact Hub"&gt;&lt;/a&gt;
&lt;a href="https://github.com/maximhq/bifrost/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/3cb44c15a532770a066ba8e61bf11506ad5400e5c61d48f6b639101e442bee79/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f6d6178696d68712f626966726f7374" alt="License"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;The fastest way to build AI applications that never go down&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Bifrost is a high-performance AI gateway that unifies access to 23+ providers (OpenAI, Anthropic, AWS Bedrock, Google Vertex, and more) through a single OpenAI-compatible API. Deploy in seconds with zero configuration and get automatic failover, load balancing, semantic caching, and enterprise-grade features.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Quick Start&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/maximhq/bifrost/./docs/media/getting-started.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fmaximhq%2Fbifrost%2FHEAD%2F.%2Fdocs%2Fmedia%2Fgetting-started.png" alt="Get started"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Go from zero to production-ready AI gateway in under a minute.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Start Bifrost Gateway&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Install and run locally&lt;/span&gt;
npx -y @maximhq/bifrost

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Or use Docker&lt;/span&gt;
docker run -p 8080:8080 maximhq/bifrost&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Configure via Web UI&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Open the built-in web interface&lt;/span&gt;
open http://localhost:8080&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Make your first API call&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -X POST http://localhost:8080/v1/chat/completions \
  -H &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;Content-Type: application/json&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt; \
  -d &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;'&lt;/span&gt;{&lt;/span&gt;
&lt;span class="pl-s"&gt;    "model": "openai/gpt-4o-mini",&lt;/span&gt;
&lt;span class="pl-s"&gt;    "messages": [{"role": "user", "content": "Hello, Bifrost!"}]&lt;/span&gt;
&lt;span class="pl-s"&gt;  }&lt;span class="pl-pds"&gt;'&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;That's it!&lt;/strong&gt; Your AI gateway is running with a web interface for visual configuration…&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/maximhq/bifrost" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Bifrost CLI article:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/anthonymax/bifrost-cli-codex-cli-one-command-to-set-up-openais-coding-agent-with-any-model-caa" class="crayons-story__hidden-navigation-link"&gt;Bifrost CLI + Codex CLI: One Command to Set Up OpenAI's Coding Agent with Any Model&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="/anthonymax" 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%2F2103048%2F716988a5-9c51-49bf-acef-191bc6dd2fee.jpeg" alt="anthonymax profile" class="crayons-avatar__image" width="400" height="400"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/anthonymax" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Anthony Max
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Anthony Max
                &lt;a href="/++"&gt;&lt;img alt="Subscriber" class="subscription-icon" src="https://assets.dev.to/assets/subscription-icon-805dfa7ac7dd660f07ed8d654877270825b07a92a03841aa99a1093bd00431b2.png" width="166" height="102"&gt;&lt;/a&gt;
              
              &lt;div id="story-author-preview-content-3369445" 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="/anthonymax" 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%2F2103048%2F716988a5-9c51-49bf-acef-191bc6dd2fee.jpeg" class="crayons-avatar__image" alt="" width="400" height="400"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Anthony Max&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/anthonymax/bifrost-cli-codex-cli-one-command-to-set-up-openais-coding-agent-with-any-model-caa" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Mar 19&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/anthonymax/bifrost-cli-codex-cli-one-command-to-set-up-openais-coding-agent-with-any-model-caa" id="article-link-3369445"&gt;
          Bifrost CLI + Codex CLI: One Command to Set Up OpenAI's Coding Agent with Any Model
        &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/webdev"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;webdev&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/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&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/anthonymax/bifrost-cli-codex-cli-one-command-to-set-up-openais-coding-agent-with-any-model-caa" 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/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;111&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/anthonymax/bifrost-cli-codex-cli-one-command-to-set-up-openais-coding-agent-with-any-model-caa#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              5&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 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;Bifrost MCP Gateway and Code Mode article:&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/hadil/how-bifrosts-mcp-gateway-and-code-mode-power-production-grade-llm-gateways-235i" class="crayons-story__hidden-navigation-link"&gt;How Bifrost’s MCP Gateway and Code Mode Power Production-Grade LLM Gateways&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="/hadil" 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%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" alt="hadil profile" class="crayons-avatar__image" width="768" height="1376"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/hadil" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Hadil Ben Abdallah
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Hadil Ben Abdallah
                
              
              &lt;div id="story-author-preview-content-3202891" 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="/hadil" 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%2F1209000%2Fb29d37d8-2efe-4391-9796-a6f8a483f1bd.png" class="crayons-avatar__image" alt="" width="768" height="1376"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Hadil Ben Abdallah&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/hadil/how-bifrosts-mcp-gateway-and-code-mode-power-production-grade-llm-gateways-235i" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jan 29&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/hadil/how-bifrosts-mcp-gateway-and-code-mode-power-production-grade-llm-gateways-235i" id="article-link-3202891"&gt;
          How Bifrost’s MCP Gateway and Code Mode Power Production-Grade LLM Gateways
        &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/llm"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;llm&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/mcp"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;mcp&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/opensource"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;opensource&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/hadil/how-bifrosts-mcp-gateway-and-code-mode-power-production-grade-llm-gateways-235i" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/multi-unicorn-b44d6f8c23cdd00964192bedc38af3e82463978aa611b4365bd33a0f1f4f3e97.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/exploding-head-daceb38d627e6ae9b730f36a1e390fca556a4289d5a41abb2c35068ad3e2c4b5.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;97&lt;span class="hidden s:inline"&gt;&amp;nbsp;reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/hadil/how-bifrosts-mcp-gateway-and-code-mode-power-production-grade-llm-gateways-235i#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              

              16&lt;span class="hidden s:inline"&gt;&amp;nbsp;comments&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            7 min read
          &lt;/small&gt;
            
              &lt;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;Official Bifrost setup article on Medium:&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__body flex items-center justify-between"&gt;
        &lt;a href="https://medium.com/@kuldeep.paul08/how-to-set-up-bifrost-your-llm-gateway-in-30-seconds-3b152fd9b7a3" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;medium.com&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Final status
&lt;/h2&gt;

&lt;p&gt;Here is the final state of the test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[x] Install Bifrost locally with NPX&lt;/li&gt;
&lt;li&gt;[x] Install Bifrost locally with Docker&lt;/li&gt;
&lt;li&gt;[x] Open the dashboard and confirm the UI works&lt;/li&gt;
&lt;li&gt;[x] Configure at least one provider (Ollama)&lt;/li&gt;
&lt;li&gt;[ ] Configure OpenAI provider request blocked by missing secret&lt;/li&gt;
&lt;li&gt;[x] Start Bifrost CLI&lt;/li&gt;
&lt;li&gt;[x] Confirm Bifrost CLI asks for the right config&lt;/li&gt;
&lt;li&gt;[x] Confirm Bifrost CLI config storage&lt;/li&gt;
&lt;li&gt;[x] Launch Codex CLI through Bifrost CLI&lt;/li&gt;
&lt;li&gt;[x] Record the Codex limitation with this route&lt;/li&gt;
&lt;li&gt;[x] Launch one working coding agent through Bifrost with OpenCode&lt;/li&gt;
&lt;li&gt;[x] Add at least one MCP server&lt;/li&gt;
&lt;li&gt;[x] Verify the tool surface&lt;/li&gt;
&lt;li&gt;[x] Verify classic MCP tool execution&lt;/li&gt;
&lt;li&gt;[x] Enable Code Mode&lt;/li&gt;
&lt;li&gt;[x] Verify the Code Mode meta-tools&lt;/li&gt;
&lt;li&gt;[x] Run the same small MCP task with and without Code Mode&lt;/li&gt;
&lt;li&gt;[x] Verify local Ollama routing through Bifrost&lt;/li&gt;
&lt;li&gt;[x] Verify Ollama cloud routing through Bifrost&lt;/li&gt;
&lt;li&gt;[ ] Check provider selection and fallback path blocked by missing OpenAI key&lt;/li&gt;
&lt;li&gt;[x] Capture screenshots of the dashboard and terminal results&lt;/li&gt;
&lt;li&gt;[x] Record exact errors, fixes, and commands&lt;/li&gt;
&lt;li&gt;[out of scope] Replace vendor benchmark claims with my own benchmark for a one-server test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is still not a benchmark. It is a tested setup walkthrough and an initial MCP + Code Mode proof. I do not want to turn a one-server smoke test into a fake performance claim.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;I am not testing Bifrost because I need another AI tool.&lt;/p&gt;

&lt;p&gt;I am testing it because the wiring is getting messy.&lt;/p&gt;

&lt;p&gt;Every agent wants a config file. Every provider wants a key. Every MCP server adds tools. Every tool adds context.&lt;/p&gt;

&lt;p&gt;Bifrost does not solve all of that, but it does give you one place to inspect and control it.&lt;/p&gt;

&lt;p&gt;In this setup, the core pieces worked:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the gateway installed cleanly&lt;/li&gt;
&lt;li&gt;the dashboard gave me visibility&lt;/li&gt;
&lt;li&gt;Ollama routed through it&lt;/li&gt;
&lt;li&gt;MCP tools were governable&lt;/li&gt;
&lt;li&gt;Code Mode exposed the expected meta-tools&lt;/li&gt;
&lt;li&gt;OpenCode completed a request through the gateway&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The limits are also clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OpenAI routing still needs a real &lt;code&gt;OPENAI_API_KEY&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Codex CLI launched, but the request path needs Responses compatibility&lt;/li&gt;
&lt;li&gt;the Code Mode savings claim still needs a larger multi-server test&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My takeaway is practical: Bifrost can be a useful control layer for local agent experiments, but the value depends on provider wiring, MCP scoping, and agent-specific testing.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Testing That I Actually Run: A Small Pyramid</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Thu, 29 Jan 2026 19:38:41 +0000</pubDate>
      <link>https://dev.to/bradleymatera/testing-that-i-actually-run-a-small-pyramid-pmk</link>
      <guid>https://dev.to/bradleymatera/testing-that-i-actually-run-a-small-pyramid-pmk</guid>
      <description>&lt;h2&gt;
  
  
  The "Testing Guilt" Cycle
&lt;/h2&gt;

&lt;p&gt;There is a cycle that every developer goes through. It starts with a vow: &lt;em&gt;"This time, I will have 100% code coverage. I will write E2E tests for every button click. I will be a 'Responsible Engineer'."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Two months later, the CI pipeline takes 20 minutes to run. The E2E tests flake out randomly because a div moved 2 pixels. You start commenting out tests just to get a hotfix deployed. Eventually, you stop running &lt;code&gt;npm test&lt;/code&gt; altogether.&lt;/p&gt;

&lt;p&gt;I have abandoned more test suites than I care to admit.&lt;/p&gt;

&lt;p&gt;The problem isn't the &lt;em&gt;desire&lt;/em&gt; to test; it's the &lt;em&gt;strategy&lt;/em&gt;. We often build an "Ice Cream Cone" of testing: massive, slow, expensive UI tests on top, with a tiny cone of unit tests at the bottom. This is unstable and exhausting.&lt;/p&gt;

&lt;p&gt;In 2025, I flipped the script. I use a "Small Pyramid" strategy. It relies on a high volume of ultra-fast unit tests, a complete absence of complex E2E frameworks (for personal projects), and a rigorous, documented "Smoke Protocol."&lt;/p&gt;

&lt;p&gt;This post is the blueprint for that stack.&lt;/p&gt;




&lt;h2&gt;
  
  
  Level 1: The Infrastructure (Why Vitest Won)
&lt;/h2&gt;

&lt;p&gt;For the better part of a decade, &lt;strong&gt;Jest&lt;/strong&gt; was the undisputed king of JavaScript testing. But as the ecosystem shifted toward ESM (ECMAScript Modules) and TypeScript, Jest started showing its age.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Problem with Jest:&lt;/strong&gt; Jest operates by overriding the Node.js require system. To make it work with modern TypeScript or Vite projects, you essentially have to configure a Babel pipeline &lt;em&gt;just for your tests&lt;/em&gt;. It is slow, memory-hungry, and debugging "SyntaxError: Cannot use import statement outside a module" is a rite of passage I never want to repeat.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Solution (Vitest):&lt;/strong&gt; Vitest is a native Vite-powered test runner. It reads your existing &lt;code&gt;vite.config.ts&lt;/code&gt;. It supports ESM out of the box. It uses Worker threads for true parallelism.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Setup
&lt;/h3&gt;

&lt;p&gt;We don't just install a library; we define a standard. The &lt;code&gt;package.json&lt;/code&gt; is the contract.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Command:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-D&lt;/span&gt; vitest @vitest/coverage-v8

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Configuration (&lt;code&gt;package.json&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest run"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:watch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test:coverage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vitest run --coverage"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Config File (&lt;code&gt;vitest.config.ts&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
We create a dedicated config to ensure our testing environment isolates side effects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest/config&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Use 'jsdom' if testing React components&lt;/span&gt;
    &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**/*.test.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;coverage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;v8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;reporter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;html&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="c1"&gt;// Fail the build if we accidentally leave a .only() in the code&lt;/span&gt;
    &lt;span class="na"&gt;allowOnly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&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;Why this matters:&lt;/strong&gt;&lt;br&gt;
Using &lt;code&gt;vitest run&lt;/code&gt; (single pass) vs &lt;code&gt;vitest&lt;/code&gt; (watch mode) is a crucial distinction for CI/CD pipelines. If you put &lt;code&gt;vitest&lt;/code&gt; in your GitHub Action, it will hang forever waiting for input.&lt;/p&gt;


&lt;h2&gt;
  
  
  Level 2: The Unit Test (The Bedrock)
&lt;/h2&gt;

&lt;p&gt;The bottom of the pyramid must be wide and stable. These tests verify &lt;strong&gt;Pure Logic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A "Pure Function" is a function that, given the same input, always returns the same output and produces no side effects (no API calls, no DOM updates). These are the easiest to test and the most critical to verify.&lt;/p&gt;
&lt;h3&gt;
  
  
  Real World Example: Data Transformation
&lt;/h3&gt;

&lt;p&gt;Imagine an e-commerce app where we need to format a messy API response into a clean UI object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Logic (&lt;code&gt;src/utils/formatter.ts&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserAPIResponse&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ISO Date string&lt;/span&gt;
  &lt;span class="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;UserUI&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;memberSince&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;formatUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserAPIResponse&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;UserUI&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;first&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;first_name&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;last_name&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="c1"&gt;// Format Date (simple implementation for demo)&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;created_at&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;year&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFullYear&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;fullName&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="nx"&gt;first&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="nx"&gt;last&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="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;memberSince&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="na"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Test Suite (&lt;code&gt;src/utils/formatter.test.ts&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vitest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;formatUser&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./formatter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;formatUser utility&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;combines names correctly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-01-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;formatUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Jane Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;handles null names gracefully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
      &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-01-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
      &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;formatUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;fullName&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Guest&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;identifies admin privileges&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
        &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2023-01-01&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;formatUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;isAdmin&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;handles invalid dates&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;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;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
          &lt;span class="na"&gt;first_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Test&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="na"&gt;last_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="na"&gt;created_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;invalid-date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
          &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; 
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;formatUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;memberSince&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Unknown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The Lesson:&lt;/strong&gt;&lt;br&gt;
This suite runs in 4 milliseconds. It protects us against &lt;code&gt;null&lt;/code&gt; pointer exceptions and ensures our UI never says "undefined undefined". This is the highest ROI (Return on Investment) coding you can do.&lt;/p&gt;


&lt;h2&gt;
  
  
  Level 3: The "Smoke Protocol" (The Human Element)
&lt;/h2&gt;

&lt;p&gt;This is where I diverge from the "Best Practices" dogma.&lt;/p&gt;

&lt;p&gt;Standard advice says "Automate Everything." But setting up Cypress or Playwright to click a "Login" button, handle Authentication tokens, deal with 2FA, and wait for animations to finish is a massive maintenance burden. For a solo developer or a small team, &lt;strong&gt;maintenance is the enemy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Instead, I use a rigorous &lt;strong&gt;Manual Smoke Protocol&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This isn't just "clicking around." It is a standardized checklist committed to the repository that must be physically checked off before a release.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Protocol File (&lt;code&gt;docs/QA_SMOKE_CHECK.md&lt;/code&gt;):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# 🛑 Release Smoke Check Protocol&lt;/span&gt;
&lt;span class="gs"&gt;**Do not merge to main until all items are verified.**&lt;/span&gt;

&lt;span class="gu"&gt;## 1. Critical User Flows&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Authentication:**&lt;/span&gt; Log out and Log back in using Google Auth.
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Data Persistence:**&lt;/span&gt; Update the user profile name, refresh the page. Does the new name persist?
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Payment Flow:**&lt;/span&gt; Go to /pricing, click "Buy", reach the Stripe Checkout hosted page. (Do not need to complete purchase).

&lt;span class="gu"&gt;## 2. Responsive Check&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Mobile Menu:**&lt;/span&gt; Open on iPhone viewport (Chrome DevTools). Does the hamburger menu expand?
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Grid Layout:**&lt;/span&gt; Resize window to 768px. Does the 3-column grid snap to 1-column?

&lt;span class="gu"&gt;## 3. The "Stupid" Check&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Console Errors:**&lt;/span&gt; Open DevTools console. Are there any red text blocks on the homepage?
&lt;span class="p"&gt;-&lt;/span&gt; [ ] &lt;span class="gs"&gt;**Links:**&lt;/span&gt; Click the "Contact Us" link in the footer. Does it 404?

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this works:&lt;/strong&gt;&lt;br&gt;
It forces you to look at your application. Automated tests pass silently. Manual tests force you to feel the latency, see the layout shifts, and notice the janky animations that a script would ignore.&lt;/p&gt;


&lt;h2&gt;
  
  
  The "Gap" Analysis: What Are We Missing?
&lt;/h2&gt;

&lt;p&gt;To be an honest engineer, you must admit what you are &lt;em&gt;not&lt;/em&gt; testing. In this "Small Pyramid" stack, we have deliberate gaps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visual Regression:&lt;/strong&gt; We are not using Percy or Chromatic to check pixel-perfect rendering.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Risk:&lt;/em&gt; I might accidentally change the button color from blue to slightly-less-blue.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Acceptance:&lt;/em&gt; I can live with this risk in exchange for development speed.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integration Tests:&lt;/strong&gt; We are not mocking the full API and testing the connection between the Frontend and Backend components.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Risk:&lt;/em&gt; The API contract might change (e.g., &lt;code&gt;firstName&lt;/code&gt; becomes &lt;code&gt;first_name&lt;/code&gt;) and the frontend will crash.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Mitigation:&lt;/em&gt; This is caught during the Manual Smoke Check.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-Browser Testing:&lt;/strong&gt; I am mostly testing on Chrome.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Risk:&lt;/em&gt; Safari might render flexbox differently.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;Acceptance:&lt;/em&gt; 90% of my traffic is Chrome/Mobile Safari. The Smoke Check covers the Mobile Safari viewport.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Bonus: Automating the Bedrock (GitHub Actions)
&lt;/h2&gt;

&lt;p&gt;We can't automate the Smoke Check easily, but we &lt;em&gt;must&lt;/em&gt; automate the Unit Tests. If tests only run on your laptop, they don't exist.&lt;/p&gt;

&lt;p&gt;Here is the exact workflow file I drop into every project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;File: `.github/workflows/test.yml&lt;/strong&gt;`&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Unit Tests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout Code&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup Node&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;node-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
          &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install Dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run Vitest&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This ensures that no code can be merged into &lt;code&gt;main&lt;/code&gt; unless the math functions and data formatters are working perfectly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final Verdict
&lt;/h2&gt;

&lt;p&gt;Testing is not binary. It is not "Tested" vs "Untested." It is a spectrum of confidence.&lt;/p&gt;

&lt;p&gt;By using &lt;strong&gt;Vitest&lt;/strong&gt; for the logic that &lt;em&gt;must&lt;/em&gt; be correct (math, data formatting) and a &lt;strong&gt;Smoke Protocol&lt;/strong&gt; for the things that &lt;em&gt;must&lt;/em&gt; look right (layout, navigation), you achieve 95% of the confidence with 10% of the maintenance cost of a full E2E suite.&lt;/p&gt;

&lt;p&gt;That is a trade I will take every single time.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>devops</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>AWS vs. Azure vs. Google Cloud: The Ultimate Free Tier Battle &amp; Survival Guide</title>
      <dc:creator>Bradley Matera</dc:creator>
      <pubDate>Thu, 29 Jan 2026 18:40:57 +0000</pubDate>
      <link>https://dev.to/bradleymatera/aws-vs-azure-vs-google-cloud-the-ultimate-free-tier-battle-survival-guide-2fam</link>
      <guid>https://dev.to/bradleymatera/aws-vs-azure-vs-google-cloud-the-ultimate-free-tier-battle-survival-guide-2fam</guid>
      <description>&lt;p&gt;&lt;strong&gt;Which cloud provider actually supports a developer’s growth for free, and which one is designing a billing trap?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In my previous post, I broke down the mechanics of the AWS Free Tier—specifically how to survive the first 12 months without incurring surprise debt. Since then, the conversation has shifted toward a broader comparison. It is not enough to just know how AWS works; as developers, we need to know if we are even betting on the right horse.&lt;/p&gt;

&lt;p&gt;If you are building a portfolio, launching a startup prototype, or just trying to learn &lt;code&gt;cloud&lt;/code&gt; without melting your credit card, you need a side-by-side technical and financial breakdown.&lt;/p&gt;

&lt;p&gt;This is that breakdown.&lt;/p&gt;

&lt;p&gt;We are going to pit &lt;strong&gt;AWS&lt;/strong&gt;, &lt;strong&gt;Microsoft Azure&lt;/strong&gt;, and &lt;strong&gt;Google Cloud Platform (GCP)&lt;/strong&gt; against each other. We will analyze their compute limits, database constraints, hidden network costs, and the specific "gotchas" that each provider uses to monetize their free users.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Philosophy of "Free"
&lt;/h2&gt;

&lt;p&gt;Before looking at the numbers, you have to understand the business model, because it dictates the limitations you will face.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The cloud is not a charity. The Free Tier is a customer acquisition funnel designed to integrate you into an ecosystem."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;AWS&lt;/strong&gt; wants you to build habits. Their 12-month model is designed to get you addicted to their specific proprietary tools (RDS, S3, IAM) so that when the year ends, the switching cost is too high to leave.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Azure&lt;/strong&gt; wants enterprise adoption. They front-load credits ($200) to let you taste the "premium" power, hoping you'll convince your boss to migrate the company infrastructure later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GCP&lt;/strong&gt; plays the long game. They are the distant third in market share, so they offer the most generous "Always Free" tier to attract hobbyists and students, hoping that grassroots loyalty will grow their market share.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. Compute: The Engine Room
&lt;/h2&gt;

&lt;p&gt;The biggest cost for any project is the Virtual Machine (VM). Here is how they compare when you strip away the marketing fluff.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS: The Standard (EC2)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Offer:&lt;/strong&gt; 750 Hours/month of &lt;code&gt;t2.micro&lt;/code&gt; or &lt;code&gt;t3.micro&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Specs:&lt;/strong&gt; 2 vCPUs (burstable), 1 GiB Memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Reality:&lt;/strong&gt; This is enough to run one instance continuously (24/7) for a month. However, AWS uses a "CPU Credit" system. If your website gets a sudden spike in traffic, you burn credits. If you run out of credits, your CPU is throttled to baseline performance, making your site crawl.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Trap:&lt;/strong&gt; It is strictly &lt;strong&gt;12 months&lt;/strong&gt;. On day 366, you are billed standard on-demand rates.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Azure: The Burstable (B-Series)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Offer:&lt;/strong&gt; 750 Hours/month of &lt;code&gt;B1s&lt;/code&gt; instances.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Specs:&lt;/strong&gt; 1 vCPU, 1 GiB Memory.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Reality:&lt;/strong&gt; Similar to AWS, this uses a credit banking system. The &lt;code&gt;B1s&lt;/code&gt; is noticeably weaker than the AWS &lt;code&gt;t3.micro&lt;/code&gt; for multi-threaded tasks because it only offers 1 vCPU compared to AWS's 2.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Trap:&lt;/strong&gt; The interface. Azure’s portal is complex. It is very easy to accidentally select a "Standard SSD" (paid) instead of a "Standard HDD" (free) during setup.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GCP: The Forever Server (Compute Engine)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Offer:&lt;/strong&gt; &lt;code&gt;e2-micro&lt;/code&gt; instance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Specs:&lt;/strong&gt; 2 vCPUs, 1 GiB Memory (0.25 vCPU sustained).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Reality:&lt;/strong&gt; &lt;strong&gt;This is the winner for longevity.&lt;/strong&gt; As of this writing, this offer is part of the "Always Free" program, meaning it does not expire after 12 months.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Trap:&lt;/strong&gt; Location. This is only free in specific regions (usually &lt;code&gt;us-west1&lt;/code&gt;, &lt;code&gt;us-central1&lt;/code&gt;, &lt;code&gt;us-east1&lt;/code&gt;). If you deploy in &lt;code&gt;us-east4&lt;/code&gt; by mistake, you pay full price immediately.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Databases: The Expensive Part
&lt;/h2&gt;

&lt;p&gt;Stateless servers are cheap; stateful data is expensive. This is where the cloud providers try to squeeze you.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS (RDS)
&lt;/h3&gt;

&lt;p&gt;AWS offers 750 hours of &lt;code&gt;db.t2.micro&lt;/code&gt; or &lt;code&gt;db.t3.micro&lt;/code&gt; (Single-AZ).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; You get a real, managed relational database (MySQL, PostgreSQL, MariaDB).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; It stops being free after 12 months. Migrating data &lt;em&gt;out&lt;/em&gt; of AWS later can be tricky due to egress fees.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Azure (SQL Database)
&lt;/h3&gt;

&lt;p&gt;Azure offers 250 GB of Azure SQL Database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; 250 GB is massive compared to the 20GB limit often seen elsewhere.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; This is specifically "Azure SQL," which is Microsoft SQL Server. If your project is built on Postgres or MySQL, this free tier doesn't help you much. You have to adapt your stack to their technology.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  GCP (Firestore)
&lt;/h3&gt;

&lt;p&gt;GCP does &lt;strong&gt;not&lt;/strong&gt; offer a generous free tier for Cloud SQL (their managed relational service). Instead, they push you toward Firestore (NoSQL).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Pros:&lt;/strong&gt; Firestore is incredibly fast and easy for mobile apps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; It is NoSQL. If you are trying to learn traditional SQL table relationships, GCP forces you to pay roughly $10-$15/month for the smallest SQL instance.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. The "Silent Killers" of Cloud Billing
&lt;/h2&gt;

&lt;p&gt;Regardless of which provider you choose, the billing algorithms share the same ruthless logic regarding "optional" resources. These are the line items that do not appear on the main pricing page but appear on your invoice.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Orphaned Volume
&lt;/h3&gt;

&lt;p&gt;When you terminate a server, the cloud provider assumes you want to keep the data. They delete the compute resource but leave the hard drive (EBS/Disk) active.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Cost:&lt;/strong&gt; Roughly $0.10 per GB per month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Fix:&lt;/strong&gt; You must manually locate the "Storage" or "Volumes" dashboard and delete these unattached disks. There is no auto-delete for these.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The Static IP Tax
&lt;/h3&gt;

&lt;p&gt;A static IP (Elastic IP) is free &lt;em&gt;only while it is being used&lt;/em&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Logic:&lt;/strong&gt; IPv4 addresses are a scarce global resource. The providers punish you for hoarding them.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Cost:&lt;/strong&gt; If you stop your server but keep the IP reserved, you are charged ~$0.005/hour. That is roughly $3.60/month for doing absolutely nothing.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Data Egress (The "Hotel California" Fee)
&lt;/h3&gt;

&lt;p&gt;You can check out any time you like, but you can never leave—without paying.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ingress (Data In):&lt;/strong&gt; Always Free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Egress (Data Out):&lt;/strong&gt; Charged per GB after a small threshold.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Risk:&lt;/strong&gt; If you host a large media file and it gets hotlinked on a popular site, your egress fees will skyrocket instantly.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Verdict: Which One Should You Choose?
&lt;/h2&gt;

&lt;p&gt;After deploying stacks on all three, here is my decision matrix for new projects:&lt;/p&gt;

&lt;h3&gt;
  
  
  Choose AWS If:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;You are job hunting.&lt;/strong&gt; AWS holds the largest market share. Having "Deployed MERN stack on EC2" on your resume is statistically more valuable than the others.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You need a standard SQL database.&lt;/strong&gt; The RDS free tier is the most straightforward way to run MySQL/Postgres for a year.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Choose GCP If:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;You are building a permanent personal tool.&lt;/strong&gt; If you want a Discord bot or a script runner that stays online for 5 years for $0, the &lt;code&gt;e2-micro&lt;/code&gt; is unmatched.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You are comfortable with Linux/Command Line.&lt;/strong&gt; GCP’s interface is developer-focused but less "hand-holding" than Azure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Choose Azure If:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;You work in the .NET ecosystem.&lt;/strong&gt; Visual Studio integration with Azure is seamless.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;You need massive database storage.&lt;/strong&gt; The 250GB SQL limit is generous if you are willing to use Microsoft SQL Server.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The Golden Rule
&lt;/h3&gt;

&lt;p&gt;The only true way to stay free is &lt;strong&gt;vigilance&lt;/strong&gt;. Set up "Billing Alerts" the moment you create your account. Set an alert for $0.01. The moment you get that email, you know you have crossed a line, and you can fix it before it becomes a $500 problem.&lt;/p&gt;

&lt;p&gt;Stay curious, keep building, and check your billing dashboard every single morning.&lt;/p&gt;

&lt;p&gt;— &lt;strong&gt;Bradley Matera&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(bradleymatera.dev)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>cloud</category>
      <category>azure</category>
      <category>googlecloud</category>
    </item>
  </channel>
</rss>
