Office Hours — What specific coding tasks have become genuinely harder to learn well now that LLMs can solve them quickly? A daily developer question about AI/LLMs, answered with a direct, opinionated take. 2026-10-27T12:00:00.000Z Office Hours Office Hours office-hoursq-and-apractical-ai

Office Hours — What specific coding tasks have become genuinely harder to learn well now that LLMs can solve them quickly?

A daily developer question about AI/LLMs, answered with a direct, opinionated take.

Daily One question from the trenches, one opinionated answer.

What specific coding tasks have become genuinely harder to learn well now that LLMs can solve them quickly?

The Learning Gap Nobody Talks About

Debugging. Not in the sense of “finding bugs”—that’s gotten easier—but in the deeper sense of understanding why a bug exists and how to prevent the class of mistakes that created it. When you ask Claude Opus 5 or GPT-6 Astra to fix a segfault or race condition, you get a working answer in thirty seconds. You don’t get the mental model of memory layout or thread safety that comes from spending two hours reading compiler output and stepping through a debugger.

This isn’t abstract pedagogical hand-wringing. A junior engineer at a large Bay Area infrastructure company told me they’ve shipped three years of code without ever owning a memory leak investigation end-to-end. They prompt an LLM with valgrind output, get the patch, merge it. Their senior engineer catches increasingly subtle bugs in code review that the junior never would have written alone because they never internalized the patterns.

Why This Matters More Than “People Won’t Learn to Code”

The hard-to-learn tasks aren’t the ones that disappear—they’re the ones where the skill transfer breaks. Coding tasks that have become genuinely harder to learn well fall into a few categories:

Error diagnosis in unfamiliar domains. If you’re handed a TypeScript codebase using an obscure type-level library you’ve never seen, an LLM can immediately suggest a fix for a type error. But the way you learn TypeScript—building intuition for when variance rules apply, when to use conditional types, why a union gets discriminated—is by getting stuck and incrementally building a mental model. That’s gone now. You ask Claude and move on. Three years later, you still can’t design a type-safe API from scratch because you never built the pattern-recognition system through struggle.

Optimization and performance tuning. An LLM can tell you to use map instead of a loop, memoize a computation, or batch database queries. It does this correctly most of the time. But learning when to optimize, what actually matters in your specific system, and how to validate that an optimization is real versus premature—those come from profiling your own code, watching it fail in production, and building empirical judgment. If the LLM does that work, you’re left with cargo-cult optimization knowledge. You know the what but not the when.

Here’s a concrete example. A team using Claude for backend work asked it to optimize N+1 queries in their Django ORM code. Claude rewrote it with select_related and prefetch_related. The code ran faster. Six months later, a new feature added a filter that made the prefetch ineffective, and the team had no idea why performance tanked because nobody on the team had ever written prefetch_related by hand and debugged it when it didn’t work as expected.

# Claude's suggestion (initially fast):
authors = Author.objects.prefetch_related('books').all()

# New feature added a filter:
authors = Author.objects.prefetch_related('books').filter(books__genre='fiction')
# Prefetch becomes useless; N+1 returns silently
# Team doesn't understand why because they never debugged prefetch behavior

Knowing when a simple solution is actually wrong. LLMs are confident and often right. When they’re wrong, they’re confidently wrong. A junior engineer asking “how do I implement this caching strategy” gets back code that works in the happy path and fails in edge cases—concurrent writes, key expiration race conditions, stale reads after invalidation. An LLM can generate the implementation, but learning what questions to ask about caching—when eventual consistency is acceptable, when you need strong guarantees, what invalidation strategy fits your workload—that requires building broken systems, watching them fail in production, and iterating. If the LLM writes the cache layer and it mostly works, you never develop that judgment.

Architectural Decision-Making

A subtler category: understanding why certain patterns exist. Why is it better to queue writes and batch them than to write immediately? Why do you need circuit breakers? Why does your cache need TTLs instead of just storing indefinitely? These aren’t implementation details—they’re principles that emerge from experience.

An LLM can generate circuit breaker code. But if you’ve never experienced a cascading failure because you didn’t have one, the pattern remains a piece of cargo cult architecture you copy, not a principle you understand well enough to violate safely when warranted.

What Actually Got Harder

Not all learning broke equally. The tasks that got genuinely harder are the ones where:

  • The learning comes from failure and iteration, not from memorizing a correct answer.
  • The skill is pattern-recognition built through repeated exposure to problems and their solutions.
  • The value is in knowing when to apply a technique, not just knowing how to implement it.
  • Edge cases and production reality teach you more than the happy path.

Tasks that got easier: implementing a well-known algorithm, translating a spec into code, refactoring for readability, writing boilerplate, integrating a library you’ve never used.

Tasks that got harder: understanding performance behavior at scale, building judgment about trade-offs, debugging production systems you didn’t write, learning languages through deliberate struggle on hard problems, building systems that degrade gracefully when everything goes wrong.

The Uneven Impact

New people hit this hardest. A developer with ten years of embedded systems experience can ask an LLM to write a web API and still understand the concurrency model, even though they didn’t write every line. A developer with six months of experience gets code that works and ships it, and three years later realizes they still don’t have the pattern library in their head that a six-year veteran built through deliberate pain.

Team leads are noticing this. The developers who learned to code before LLMs can spot which problems need redesign versus a quick patch. Developers who’ve always had an LLM doing the writing struggle to distinguish the two, because they never developed the intuition through building broken things, watching them fail, and learning why.

Bottom line: If you’re early in your career, don’t let an LLM write your way out of debugging and optimization work—those are the apprenticeship tasks that build judgment. If you’re hiring, be skeptical of resumes that show fast shipping but no evidence of someone having owned a production incident or rewritten a system from first principles.

Question via Hacker News