...now, I pride myself on being good at my job, I'm fast at catching mistakes, I'm efficient at reviewing code and I'm quick to spot patterns across systems. But ever since I knew how to use AI ( maybe around mid 2024, I was still doing the old trad way when i started in 2018 ), I've been letting AI write ALOT of my code.
And I thought I was still learning.
Then one day I sat down to write an HTTP handler in Go from scratch, and I froze... and I can't describe how scary this was.
Not because I don't understand HTTP or because I don't know Go because I recognize these patterns instantly:
func (s *Server) handleJobNext(w http.ResponseWriter, r *http.Request) {
// ...
}
I can review it, spot mistakes, discuss the design. But build it from scratch? I found myself thinking: "Wait... is it http.HandleFunc? ServeMux? How do I start the server?"
That's when I realized something was wrong, I realized the trap I'd fallen into and I had to do something about it.
Recognition is not Production
This biggest illusion that AI makes much easier to fall into is the thinking that goes:
"I understand this" and it feels exactly like "I can produce this."
I also wanna clarify that AI isn't the first one to inven this problem, Stack Overflow, copy-pasted frameworks and tutorials all created it first and AI's just accelarating the distance.
Recognizing a solution is just one skill. Your brain does pattern matching beautifully and way effortlessly than you think once you get used to it, you see http.HandleFunc, think "yep, that's how you register routes," and feel confident.But try retriving that knowledge from scratch, constructing it... that's a whole other level, those are completely different neural pathways because the ability to review code, design & architecture aren't the same as writing it from memory and it should never be mistaken.
I got really good at reviewing, too good I guess, I am fast & efficient, I could critique architecture, spot edge cases, ask the right questions and basically start a whole drunken bar vibe conversation with it but you know what scares me despite being able to do all of this? I couldn't write an HTTP handler from memory.
I WAS practicing some skills. just some. just not the ones I thought.
The Gap and I Started A Series
There's also a dangerous confidence trap here: convincing yourself you're still learning because you're the "architect" or "reviewer", you're making decisions, you understand the system.
But how would you feel if knowing you can't write what the AI wrote, not without looking. that's the gap.
Anyway, a few months ago, I started writing distributed systems algorithms in Go from scratch, each algorithm belonging to their own repo. No AI. I write entirely, then ask it to review and I tell you it's very rewarding!
I am doing the series for 2 reasons:
- This will help me strengthen my skill in Go, I love Go but it's also the least used language of mine too but a very important one.
- I hope to help others understand algorithms in distributed systems where it's written with as much as simplicity as I could but also not leaving out edge cases and failure modes. Many developers work with one unknowingly and wonder why their simple code causes data corruption as soon as someone adds another instance of the backend.
I will be releasing the article one by one each after I'm done where I will document every hell and tasmanian devil I would've had gone through, no filters with the exception of bad languages.
You Can't Download Experience
Great software doesn't come from perfect code, It comes from surviving bad code.
Engineering intuition is built from mistakes, failed designs, debugging at 2 AM, edge cases that shouldn't exist, trade-offs that haunt you for years. The final code is just the artifact. The scar tissue is the education.
Take a system like PostgreSQL represents decades of accumulated engineering decisions.
I'm picking on Postgres specifically because I saw someone tried to rewrite Postgres with Rust nearly entirely with agents. It's not a bad thing, in fact, it's improving Postgres tremendously: with Rust, it's moving from the historic process-per-connection to thread-per-connection, massive performance gain and some of the long-standing postgres pain points.
You can rewrite it. You can reproduce the behavior. But you won't reproduce the journey that created that understanding—the bugs fixed, the performance lessons learned, the constraints that forced particular designs.
Letting an agent write everything and you get the artifact without the scar tissue.
And expertise lives in the scar tissue.
The Real Principle
The skills you practice will grow. The skills you outsource will weaken.
I outsourced writing and my writing muscle atrophied. I got better at reviewing and architecture, but lost something important.
Now I'm deliberate: distributed systems algorithms in Go, I write. from scratch.
Not because I am better than AI but because I'm choosing which muscles to exercise and the choice matters.
What I'm Not Saying
- AI is not bad. I use it daily. Heck, I still use it for work because businesses' deadlines now are unrealistic standards compared to what they were a few years ago.
- Code review is still critical work.
- AI is still my thinking partner and my force multiplier, I still consult it from time to time when making decisions, it builds me up and makes me a better developer and I make decisions faster because I'm not the only one thinking when no one's around.
What I'm saying is: Be intentional about which parts of expertise you allow to change.
Every tool reshapes what engineers need to know. The goal isn't to preserve manual typing forever. The goal is to ensure that the parts of engineering you want to own are still exercised by you.
If you want to stay sharp at writing, you have to pick code you're not going to outsource.
Because expertise follows exercise. Always.
The question isn't whether you can write without AI.
The question is: Will you?
Top comments (49)
I would love to load the highly challenging problem into the "Brain" and then let the brain handle the analysis, deep reasoning work. However, taking help of AI is optional though. But one thing is sure - Need to have a tough time for the brain to think in-depth. That's the only way; one can make sure the muscle is strong enough to think and solve critical problems. That's how one can beat any "AI" in this world 😁
Yah and it can be hard at first, you know, having to wake your brain up from its beauty nap but once it's hooked - flows like a river, like what a brain's supposed to do -- think!
Adam, you are bring to light the question of is AI making humans dumber. Is creating from scratch better?
Before the widespread use and push of using AI, I experienced developing and seeing a build up of technical debt in projects. Now I think there is a cognitive debt happening, because AI has become king of speed development and that pulls deep technical knowledge away from humans.
I think any debt is bad and some might not see issues right away, but the long view fix to me is think creatively about problems and use AI as tool to sharpen you skills and not as a silent cognitive off loader.
If you want to get old school philosophical en.wikipedia.org/wiki/The_Phenomen...
In Georg Wilhelm Friedrich Hegel’s original theory, two competing self-consciousnesses engage in a life-or-death struggle for dominance. The one who is willing to die for freedom becomes the Master; the one who submits out of a fear of death becomes the Servant. This sets up a paradoxical dynamic:
I think we're actually making a similar point. AI can definitely create cognitive debt.
this pattern existed before AI with every abstraction layer. The solution has always been intentional practice, not rejecting the tool. We don't need to preserve every old skill, but we do need to consciously decide which skills are core to our expertise and keep exercising those. AI should move our ceiling higher, not lower our foundation.
Those old school philosophers sure loved the idea of shoving the messy reality of human existence into neat categories; absolutely defined and with plenty of void in between lest they touch and create fuzzy gradients.
messy is what makes us humans, if it's too perfect, that's not human.
used to make fun of alot of chunky, clunky personal blog sites back then but looking at "perfection" today, I realize those imperfections were actually traces of what being human is and perhaps, what many on the internet demands.
I remember watching a video not too long ago that basically made the same point; might have been by hank green?
Actually I just looked it up, it was this one: youtube.com/watch?v=koKDP6kPvvY
And yea, similar sentiment, these days everything is just too rounded off and perfect but also kind of all the same.
I like weird. Its interesting. Google dream was weird.
Will we let it get weird and does that help it actually be creative?
The book A Wrinkle in Time, there is a planet in the Black Thing and the houses in the neighborhood are a copy and everyone is acts exactly the same as each other and everything is controlled by CENTRAL Central Intelligence.
Haven't seen the vid yet, watching it rn
Camazotz is the perfect metaphor for a sterile, over-optimized internet.
We definitely need to let things stay weird and messy, otherwise, we just end up with a boring, algorithm-driven copy of everything. Google DeepDream was an absolute chaos that needs to be brought back.
Hey Adam, thanks for this article. It’s validating to see someone else has been feeling the same way.
I discussed this with my senior a few days back and also told him that I’m not getting the kick I used to get out of writing code and seeing it run.
To this he said that manually writing code will become an extinct skill soon, and I should not bother spending time on this specifically. The industry will now change and these new skills are what’ll make us relevant.
I wanted to disagree hard, but didn’t have a lot of points since I don’t know what the future holds.
Would like to know your thoughts on this.
Well, with the velocity of the tech industry's moving at, the uncomfortable truth I sit with everyday is that, writing code manually will be extinct in the near inevitable future, we can't avoid that. writing code is becoming cheap now, it doesn't matter what you say or argue and AI is improving its ability to write code everyday and as long as you prompt and reason it right, make right architectural decisions, you'll actually get a great performing piece of software out of it.
Soon, the definition of software engineering will be much more different than it is today and manually writing everything won't be a part of it. every generation of engineers mourns what they "lost." And every generation becomes more productive anyway.
You didn't see people in 2010 writing blog posts about how they could no longer write C without looking up
mallocsyntax. They just... used the tools.This piece I've written here is just an invitation to write give manual coding a try once in a while because it rewards you differently than just being the " reviewer " or the " architect "
It's very likely, but there's still plenty of things that could throw AI off course.
There's the feedback loop problem (AI filling the internet is destroying its primary source of training data), the open question about intellectual property (Are LLMs an IP infringement if they're trained without consent? Do FOSS licenses cover LLM training?), there's the cost question too (Will there be a breakthrough to decrease operating costs, or will the bubble burst and AI become unaffordable?), etc.
ooooh this is something I've been doing alot of research on... will the human creativity be needed when the internet is full of its own, generated & saturated content?
Hmm. I agree
The split you name between reviewing and producing lines up with something I see in evals too: a model, or a person, can rate an output correctly and still not generate it, so review skill quietly overstates real capability. Your fix of writing first and only letting the AI review afterward keeps the harder pathway active, which I think is the right ordering. One thing I would add is picking problems where you can check your own answer objectively, so the practice does not turn into confident-but-wrong reps.
keeping this in mind!
I would distinguish between three levels of understanding, from lesser to greater:
And it's a spectrum with intermediate levels of course.
I find that using AI heavily will necessarily reduce how often you're in level #3, because that one requires writing the code by hand.
Using AI heavily can reduce how often you're in level #2, depending on how hands-on you are at the design stage, and how closely you review the code. If you're careful, you can stay in level #2.
And I would say that because of generative AI, level #2 is now a better place to be than it ever was before, because being in level #3 won't significantly improve quality or productivity for most tasks now. There are still going to be times when you want to operate at level #3, however, for certain subsystems you're very opinionated about or need to do very carefully. For the most critical pieces of software, you want to be at level #3 still.
Before generative AI, I could only write code either by being in level #3 already, or by reading all that documentation and putting in reps that would eventually get me to level #3. Now I can write code from level #2.
Reviewing code has always been possible from level #2 (though level #3 could do higher quality reviewing). Many of the code reviews I've done in the past were in areas I was level #2 in. Most code reviews don't require deep review of every single line, but just a design-level sanity check and ability to ask some pointed questions. What's new with generative AI is I'm often reviewing "my" code now (generated by AI) from level #2.
thank you so much for your perspective on this, i really like the way you put it here.
I believe I may have missed out a bit more details in the piece I've written here but I've already discussed and added it with others in the comment section.
number 3 is extremely hard and despite having done it a few times, I'm not really good at it but every time I successfully did it, it rewards me very differently and I love it but the thing I'm probably missing or yearning for is actually #2 because I believe it's the most realistic way with how we build software and how I used to build software. it was slow but you learn a lot and you see way more missing edges than just reviewing.
number 2 also exercises multiple parts of your brain. You're not just writing code, you’re researching, reading documentation (which builds domain knowledge), evaluating trade-offs, debugging, and constantly switching between dozens of small cognitive tasks that many of us don't even consciously notice.
Finally, I'm not fighting AI. This post is just an invitation to give #2 a try. We don't really know what manually writing code will look like in a few years.
As @darkwiiplayer mentioned, maybe it'll become a niche skill, kind of like writing assembly today. Most developers don't do it anymore, but the people who still do are invaluable when it comes to low-level optimization and performance tuning.
edit: iI had to replace some
#symbols with the word "number" because they were turning everything into giant headings lolthe banner image is hilarious .
I accidentally spent 1$ on this AI image generate site, gives me full premium access for a whole week, might as well use the best of it.
Your problem is you never learned that programming is about managing sources of knowledge just as much as knowing things. This is something most devs had to find out in the Pre-AI days: nobody codes everything from memory, relying on manuals is the norm.
AI doesn't need to read a manual because it isn't human; it doesn't write code like a normal person would and shouldn't be confused for a new standard.
I mean, do you care? I know I do; I enjoy writing the low-level parts of code by hand, but that's just me. I couldn't do the job of a compiler by hand, even if I might be able to look at the code it spits out and make some sense of it. That used to be what programming was, then technology moved on, and now it's just another hobby.
Some people enjoy programming in assembly. I see the appeal, even if it's not for me. Maybe that's the future of writing code too: something you do as a hobby, or as an exercise to improve your understanding of underlying systems, but not a skill you need anymore.
And who knows, maybe being good at writing code by hand will remain as a niche skill, just like being good at assembly still has value today. AI is good at synthesis, but it isn't great at innovation.
hmmm... I've always known and told people that programming is never about coding things from memory but there's just something in me that rewards my ability to do it from memory and also that's not the core point of the piece here, I also don't think it's completely realistic to be able to completely program a software without ever looking at a manual but it's more like:
copy pasting from somewhere yourself + writing it from memory triggers a good load of cognitive reasoning than having an agent generate it entirely for you. you get first seat in seeing the edges where many who only review, would miss.
and the part where you're asking if I do care if i could write something from memory, then yesssss, i do, it triggers that good, addictive kind of dopamine and kinda keeps you optimistic, keeps you up and going.
and I also love the way you put it here where you mention people enjoy programming i assembly and they find that appealing when many do not. it's just part of the productivity evolution and writing code is probably just gonna be one of them and I love another one here where you mentioned coding will be comparable to writing assembly in today's world hahaha, i can't wait to flex in my 50s ( assuming streaming is still thing so i could title: " veteran dev writes a crud app by hand in NestJS, typescript " )
Most people go through that stage, I think; it's when you know you don't have to memorize everything but you still haven't fully let go of that standard. A few more years of writing code with a "getting things done" attitude would normally drive that point home, but I suspect AI with its ability to just code everything "from memory" gets in the way of that.
Same here. I can't say if this will be the way we build software in 10 years, but I can say that I enjoy it and it would be annoying if things changed to be more boring. I can deal with letting AI write the code, at least if I set my moral problems with AI aside; but if it starts to do all the reasoning and I'm left writing requirements, then I'll start placing bets on how many months it'll take to get diagnosed with burnout.
Yea, although I imagine it more like being that one specialist with a somewhat niche skill that only gets called when something really needs to get fine-tuned to the extreme. The kind of expensive specialist you don't need many of, but also can't do without.
People keep saying, "Yeah, but you'll still need humans for architecture. AI can't make those decisions." I don't really buy that.
Give it enough context and it'll come up with a pretty solid architecture, explain the trade-offs, point out the risks, and even tell you why it picked one approach over another ( and I've reviewed many of its " recommended " one and most usually, it's pretty reasonable )
And it's getting better at it all the time.
I feel like "AI can't do architecture" is one of those statements that gets updated every few months as AI gets better.
Might save up some money for a farm so I can wake up to the sound of chickens and ducks everyday to water my plants.
That gap between reviewing and creating is important. AI can make us feel more capable because we can inspect and refine output, but generation and ownership are different muscles. The danger is mistaking editorial confidence for construction confidence. Both matter, but they are not the same skill.
repeating this again from my piece because it's the trap that i fell into. imagine suddenly you're able to review and under complex output, your brain unconsciously tricking you into believing that you can also write that just because you understand it... man!!! that little 3 pound organ is something.
That makes sense. The review/create gap is uncomfortable because review can feel like mastery even when the generative muscle is not there yet. I think the useful workflow is to make AI support the weaker side deliberately: force yourself to outline, predict, or write the first ugly version before using the model to sharpen it.
"Recognition trap" is exactly right. The dangerous part is that AI doesn't just fill in the gaps â it fills them in convincingly. You feel like you're still thinking, but you're rubber-stamping outputs you can no longer independently evaluate.
The scary part isn't forgetting syntax. It's losing the calibration that lets you catch when an AI's suggestion is locally correct but globally wrong â the error that only shows up at 3am during an incident. Without that internal model of the system, you're not reviewing, you're rubber-stamping with extra steps.
I'd push back slightly on "write everything from scratch" as the solution though. That's a high-friction workaround that throws away the productivity gains. The real fix is maintaining minimum viable engagement with the production layer â enough friction to stay calibrated, not enough to halt delivery.
What's worked for me: occasionally do a deliberate "blind write" â solve a small problem without AI, then compare. The gap between your instinct and what the AI produced tells you something about what you've lost. Do you do anything like that?
Recognition trap is the exact name for something a few of us have spent this week formalizing in a completely different domain, and the fact that it shows up here means it's probably not an AI-writing-code problem specifically. It's a can't-audit-your-own-blind-spot problem, and code review is just one place it happens to live.
The version we've been chasing: when you build an adversarial test case yourself to check whether a system catches a failure it's never seen, the test carries your fingerprint whether you intend it to or not, your habits, your phrasing, the specific way you construct a plausible-but-wrong case. If the thing under test can learn to recognize that fingerprint, it starts passing your test for the wrong reason, and you can't see that from the inside, because the tell that would break it is by definition the one you can't perceive.
Your blind write is the same fix applied to a person instead of a model. You can't self-report whether you actually understand something or just recognize it fluently, the two feel identical from the inside. The only thing that breaks the tie is producing the thing cold and measuring the gap against what the crutch would have given you, the same move as interleaving self-authored test cases with real ones and comparing pass rates instead of trusting either set alone. Not a workaround for weak discipline. The only available ground truth, because "I get this" is exactly the signal that's been contaminated.
Your adversarial test point is the key insight here -- the tester's fingerprint contaminates the test and you can't see it because the thing you'd need to notice is, by definition, in your blind spot. It's the Goedel sentence of evaluation.
This maps cleanly onto something I hit building moteDB's test suite for concurrent writes. I wrote a property-based test that generated random interleavings of reads and writes, convinced it would catch ordering bugs. Ran it for weeks, zero failures. Then a user hit a corruption bug in their first hour. The generator was biased by my mental model of what "concurrent" means -- I was generating interleavings that looked like the ones I'd written in the code, not the ones the user's workload actually produced.
The fix wasn't a better generator. It was recording traces from real workloads and using those as test inputs. Which is basically your blind write idea applied to testing -- if the test comes from inside your head, it carries your assumptions. If it comes from production, it carries reality.
The uncomfortable question: how do you know when your adversarial tests have been contaminated? The whole point is you can't see your own fingerprints. Is there a signal that's independent of the test author?
Oooooh, I love this. My favorite part is definitely the adversarial test contamination.
And yeah, gathering traces and logs from production is also one of the ways I use to verify whether an application is actually safe against edge cases, rather than just assuming it is. Not only from my own production servers, but sometimes from other people's systems as well.
There’s another reason I like looking through public repo pull request discussions too: there’s a good chance someone is bringing up a scenario, edge case, or concern that I haven’t encountered yet or completely overlooked.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.