A few years ago, writing code was one of the hardest parts of being a software developer.
Today, AI can generate an entire feature in seconds. It can write functions, create APIs, fix bugs, and even suggest architectural decisions.
But here's something interesting:
The less time we spend writing code, the more time we seem to spend figuring out whether that code is actually worth trusting.
We still have to understand the requirements, question the decisions, verify the output, catch hidden assumptions, and take responsibility when something breaks.
AI made writing code cheaper. But did it make thinking more expensive?
Or did it simply expose how much thinking we were avoiding while writing code?
1. The coding problem is disappearing
Let's be honest: the syntax barrier is gone. The "how do I center a div" era is over. The "how do I set up an Express server with JWT authentication" era is also coming to an end.
You type a prompt into Cursor, Claude, or ChatGPT, and within thirty seconds, you have a beautifully formatted, syntactically correct block of code. It feels like magic. The dopamine hit of instant creation is real.
But if writing the code is no longer the hard part... what is?
2. But the thinking didn't disappear
AI is an incredible executor, but it is a terrible visionary. It doesn't know your business logic, your legacy constraints, or your users' pain points unless you explicitly spell them out.
Example 1: AI writes the API.
Ask an AI to build a user profile endpoint, and it will do it in seconds. But the AI won't decide:
- Should this endpoint be accessible to admins only, or the user themselves?
- What happens if the payload contains a malicious script?
- How do we handle a 10MB profile picture upload?
The AI wrote the code. But the developer still has to do the thinking. If you skip the thinking phase, you end up with a fast API that is fundamentally insecure.
3. The new hidden workload
The bottleneck of software engineering has shifted. It used to be typing speed; now, it is cognitive load and verification.
Example 2: AI fixes the bug.
Imagine a bug where the app crashes because a user's profile object is null. You paste the stack trace into the AI, and it immediately spits out a fix: if (user.profile != null) { ... }.
The bug is gone. The tests pass. But the thinking isn't done.
Why was the profile null? Was it deleted? Did the database query fail? Is this fix just a band-aid hiding a deeper data integrity issue?
If we just accept the AI's fix without reverse-engineering the root cause, we aren't engineering anymore; we are just playing whack-a-mole with errors.
4. The illusion of understanding
This is the scariest part of AI-assisted development.
Example 3: AI builds the feature.
You prompt an AI to build a CSV export feature. It works perfectly on your local machine. But the AI doesn't know that your production database has 2 million rows, or that it needs to be scoped to a specific tenant.
The code runs. The feature "works." But as the developer, you don't actually understand the system anymore. You are just managing a black box.
When it inevitably breaks in production at 2 AM, you can't debug it, because you never truly understood how it worked in the first place.
5. Are we losing problem-solving skills?
This is the uncomfortable question that nobody wants to ask.
If AI writes the code, explains the code, and fixes the code... are we losing the ability to do it ourselves?
For junior developers, this is a massive risk. The struggle of figuring out a syntax error, tracing a bug through the call stack, or wrestling with a complex algorithm is exactly how you build muscle memory. If AI removes that struggle, does it also remove the learning?
We have to be careful not to outsource our brains completely. The goal is to use AI to automate the typing, not the reasoning.
6. Maybe thinking is the real engineering skill
We are transitioning from an era of "Code Writers" to an era of "Code Editors and Systems Thinkers."
The most valuable engineer in 2026 isn't the one who can type out a Redux boilerplate the fastest. It's the one who can look at 500 lines of AI-generated code, instantly spot the architectural flaw, and know exactly how to fix it.
The value is no longer in the production of code. The value is in the judgment.
AI is a powerful force multiplier, but it multiplies whatever you give it. If you give it shallow thinking, it produces shallow code very quickly. If you give it deep thinking, it builds something incredible.
Now, I want to leave you with two questions to think about:
If AI can write the code, explain the code, and even fix the code, what exactly should developers become exceptionally good at?
And more importantly, are we using AI to improve our thinking, or slowly outsourcing that too?
Drop your thoughts in the comments below. I'd love to know how you are balancing AI execution with human judgment.
Top comments (20)
When one input drops toward zero cost, the bottleneck moves onto the scarce complement paired with it. Code generation got cheap, so specifying constraints and verifying behavior under production edge cases now absorb the real engineering budget.
Your null profile and tenant scoping examples show why that shift feels heavier than writing from scratch. Auditing 500 lines someone else generated takes more concentration than checking code you reasoned through yourself, and patching a symptom hides the upstream data failure. Skipping that debugging friction also removes the repetitions that train junior developers to spot those flaws in the first place.
Dean the economic framing of scarce complement is absolutely brilliant. I hadn't thought of it that way, but you're completely right. When the cost of writing code drops to zero, the value immediately shifts to the thing that is hardest to automate: human judgment.
And your point about auditing 500 lines of generated code vs. writing from scratch is spot on. It requires a completely different type of cognitive load. When you write it yourself, you know the map. When the AI writes it, you're exploring a maze someone else built.
But your last point about junior developers is the one that should scare the industry the most. If we remove the debugging friction' for them, how do they ever build those instincts?
How do you think we should solve this? Do we need to create no-AI zones for juniors while they are learning, or is the answer just better code review mentorship? I'd love to hear your take on that.
Blanket no-AI bans rarely survive deadline pressure because managers still measure ticket throughput, so juniors look slower than peers who use models. Relying only on heavier senior mentorship hits the same wall when review bandwidth is already the scarce input.
A workable middle ground is separating drafting from verification. Juniors can use models to scaffold changes, while owning the edge-case tests, database query checks, and first-pass incident debugging without pasting the trace straight back into a prompt. That keeps debugging friction where judgment forms without pulling them out of the real stack.
Dean this is a brilliant reality check. You're 100% right blanket no-AI bans will always lose to deadline pressure because managers will just look at the ticket throughput. And relying only on senior mentorship is unfair when the review bandwidth is already drowning.
Your middle ground of separating drafting from verification is incredibly practical. But the most powerful part is the rule about not pasting the stack trace back into the prompt. That is genius.
If a junior has to manually trace a bug in AI-generated code and can't just ask the AI to fix it they are forced to actually read and understand the architecture. It shifts the learning curve from writing syntax to reading systems.
How do you actually enforce that 'no-paste' rule in practice though? Is it just a cultural expectation, or do you have a specific way of tracking which tickets a junior truly debugged themselves?
deanlee has the economics right, so the useful thing to add is the measurement that follows from it. If generation got cheap and review did not, delivery cost stops tracking generation and starts tracking review rate - a few hundred lines an hour for careful reading, and that is a human constant a better model does not move.
So the question is not whether thinking got expensive, it is whether time-to-merge fell. If your PRs grew faster than your merges did, generation was never the constraint, and the tool moved work into a queue that looks like progress. Lead time before and after is one number, and it settles what the post asks.
Cheap code in front of a fixed review budget only makes the queue longer.
This is a brilliant addition. Combining Dean's economics with your measurement framework (time-to-merge vs. review rate) completely cuts through the AI hype.
Cheap code in front of a fixed review budget only makes the queue longer' is the best summary of the illusion of progress I've ever read. It perfectly explains why Jira boards look incredibly busy but the actual release date hasn't moved. We are just generating a massive backlog of unreviewed PRs.
Since review rate is a human constant (a few hundred lines an hour), how does your team manage the queue today? Do you limit the Work In Progress (WIP) for AI-generated PRs, or do you batch them into specific review windows? I'd love to know how you prevent the queue from just becoming a graveyard.
When you use AI too much, you soon wont know how to do anything anymore. AI does everything for you. So you will lose brain power and become incredbly stupid.
And highly dependent. It will become a equivariant to a delphinine effect asking AI for the time with a watch on your wrist.
That asking AI for the time while wearing a watch analogy is painfully accurate. It perfectly captures the danger of cognitive atrophy. The goal should be to use AI for things we can't easily do not to outsource the basic thinking we already have the tools for. The dependency is the real trap!
totally agree
There is a real effect there, and it is narrower than it sounds: what atrophies is the part you stop doing. Someone who stopped writing boilerplate lost nothing worth keeping; someone who stopped reading diffs lost the ability to catch the one that mattered.
So my rule is not about how much AI, but about which part stays manual. Never let it write the thing you would be asked to debug at 3am. Everything else is fair game.
The dependency test I find useful: can you still reject its output? If you can look at what it produced and say "no, that is wrong" for a specific reason, you used a tool. If the best you can do is accept it because it looks plausible, you outsourced the judgment - and that part does not come back on its own.
The moment to worry is not when you are faster. It is the first time you pass a wrong answer you could not have spotted.
AI only writes truly good code if you give it all the information required to do so. Our job was never to produce code as fast as possible. Good engineers have always been systems-level thinkers, and the value of a good engineer has always been in the mental models he or she has in their heads.
This is what some executives who think coders are interchangeable don't understand: Building up a mental model of a technology, of a technological landscape, and most of all of an application takes loads of time and effort. AI doesn't change this. To use AI to produce code that is correct, rather than just looking correct, is hard work. It requires harnesses, skills, tools, a whole ecosystem build just for the agent to work correctly.
Any amateur can produce code which seems correct on surface level examination. This has always been the case, it just has gotten easier now (a whole lot easier). The challenge of software engineering has always been producing code that both works correctly and fits into the system in a structural sense. Only the latter allows us to evolve our systems over time with reasonable effort, and to keep systems understandable and debuggable.
I see this first hand in my workplace with people who put in the effort to do agentic engineering rather than just vibe coding. It is a form of engineering. You need to produce artifacts like harnesses that you simply didn't need before. If you don't create these harnesses, these skills, these workflows, the whole thing will degenerate into vibe coding sessions which produce the worst kind of code: The one which looks reasonable on the surface, but is really not correct if you think about it a little.
We can preserve our abilities in two ways:
Write something yourself every now and then, even if it takes longer
Engage with AI output. This is the key thing: We need to engage with the code mentally, so our mental models of the application don't get corrupted over time
Agentin engineering doesn't have to erode anything, but you have to treat it as serious engineering, not as vibe coding.
Andreas this is a masterclass of a comment. The distinction between vibe coding and agentic engineering is the most accurate description of the current AI landscape I've read.
You nailed it when you said our job was never to produce code as fast as possible. Anyone can make an AI spit out a function that 'looks correct' on the surface. But building the harnesses, the mental models, and the ecosystem so that the code actually fits the system structurally that is the real engineering work. If you don't build those guardrails, you just end up with a beautiful house built on sand.
Your two strategies for preserving our abilities are spot on. Especially point #2: 'Engage with AI output mentally.' If we just approve PRs without tracing the logic, our mental models decay.
You mentioned building harnesses so the agent works correctly. What does that look like on your team? Are we talking about strict repository-level instructions, custom linters, or a dedicated context-retrieval pipeline? I'd love to know what your engineering setup looks like.
Your fixed review budget point is why I decide attempts by expected value, not by how big the prize looks. A small chance at something large can beat a sure small thing — but only if I can afford the attempts. Counting the attempts I can actually afford changed which bets I take.
Your Jira observation is the signature of it, and it is measurable: track open PRs against merges per week. If WIP climbs while merges stay flat, you are not shipping faster, you are generating backlog with extra steps.
The first number to move is not velocity, it is review queue age - median hours between opening a PR and its first review. It rises before anything else does, so it works as the early warning. Release date lags it by weeks, which is why the date looks like it moved for no reason at all.
review queue age is a brilliant leading indicator. You're absolutely right it rises before velocity drops and it's the earliest warning sign that we are generating faster than we can verify.
Tracking open PRs against merges per week is a much better health metric for an AI-assisted team than just lines of code or story points.
Since review queue age is the metric to watch, what has worked for you to actually bring it down? Do you enforce a strict WIP limit on open PRs, or just strictly timebox the reviews (e.g. first review within 4 hours)? I'm curious how you tackle the backlog once you spot it growing.
WIP limits, not review SLAs. A four-hour first-review rule cannot create reviewer capacity; it just relocates the lateness to somewhere less visible than the queue.
One refinement mattered more than the limit itself: cap review-hours, not PR count. A 40-line change and a 2,000-line one cost wildly different review time, so counting them equally makes the cap decorative.
And the fastest lever is not reviewing faster, it is closing. Latency is outstanding divided by throughput, so deciding ten stale PRs merge-or-abandon cuts queue age immediately, while reviewing ten more only holds it flat. Close the queue before you drain it.
The CSV export example is the one that stuck with me — works locally, 2 million rows in prod, tenant scoping nobody asked about. I've had that exact 2 AM moment where the fix was easy and the understanding was just... gone. Dean's scarce-complement framing is sharp, but the junior-dev point is the one I keep coming back to. If the struggle never happens, the muscle memory never forms — and then who reviews the 500 lines?
Paul the fix was easy and the understanding was just gone' is the most terrifying sentence in modern software engineering. It's that 2 AM feeling when you realize you are just a passenger in your own codebase.
And you've hit the nail on the head with the junior dev dilemma. We are essentially eating our seed corn. If they never write the 500 lines, they will never have the context to review the 500 lines.
I think the industry is going to have to completely rethink junior training. We might need to enforce no-AI periods for juniors just so they build that debugging muscle memory, or we lean heavily into pair programming where a senior walks them through reverse-engineering the AI's output.
How is your team handling this right now? Are you forcing juniors to struggle on purpose, or letting them use AI and trying to teach the concepts afterward?