Coding Is Not Solved: Why Writing Code Is Just the Tip of the Software Engineering Iceberg

AI can generate code, but software engineering's real challenges — requirements, architecture, maintenance — remain unsolved.
In his post *Coding Is Not Solved*, developer Alex Ewerlöf argues that equating "writing code" with "software engineering" is a fundamental categorical error. While AI can rapidly generate working code, code is only the most surface-level part of the software lifecycle. The real work lies in interpreting ambiguous requirements, navigating conflicting architectural constraints, and managing long-term system maintenance. More worrying still, AI-generated code may accelerate technical debt accumulation, shifting complexity from the writing phase to the harder-to-manage review and maintenance stages. The Hacker News discussion reveals the core divide: AI tools do boost local productivity, but "useful" is far from "solved."
The Misconception Behind a Popular Narrative
As large language models become increasingly impressive at generating code, the idea that "Coding Is Solved" has spread widely across the tech community and even investment circles. Developer Alex Ewerlöf pushes back directly against this notion in his blog post Coding Is Not Solved, which sparked lively discussion on Hacker News — earning 215 points and over 200 comments — striking a nerve at one of the software industry's most sensitive pressure points.
His core argument is straightforward: equating "writing code" with "software engineering" is a categorical error. AI can certainly generate working code snippets at speed, but code is merely the most surface-level — and most easily automated — part of the entire software lifecycle. The truly hard work happens outside the code itself: understanding ambiguous requirements, navigating trade-offs between conflicting constraints, and preserving a system's long-term evolvability.

Writing Code Is Not the Same as Software Engineering
Ewerlöf emphasizes that programming as a professional activity is far more than typing syntactically correct functions into a keyboard. Software engineering is better understood as a continuous decision-making process: requirements are often incomplete or even self-contradictory, and engineers must dig beneath what clients say to uncover what they actually need. System architecture involves trade-offs between performance, cost, security, and maintainability — and none of those trade-offs have a standard right answer.
When a model generates code that passes tests, it has only solved the well-defined sub-problem of "how to implement this." In real-world projects, "what should be implemented" and "why implement it this way" typically consume the bulk of an engineer's energy. These judgments depend on deep familiarity with business context, accumulated technical debt, and team dynamics — precisely where current generative AI is weakest.
The Gap Between Context and Intent
The quality of AI-generated code depends heavily on the context provided in the prompt. But in large, real-world codebases, tacit knowledge, organizational conventions, and historical decisions are nearly impossible to feed completely into a model. A seemingly reasonable code suggestion can introduce subtle bugs simply by overlooking a boundary condition or an unwritten team convention. This kind of "looks correct" output actually increases the cognitive burden on human reviewers.
This phenomenon is sometimes called the "tacit knowledge" problem in software engineering — a vast number of design decisions in any system are never documented, existing only in the collective memory of the development team: why a certain interface was designed the way it was, why a particular piece of code deliberately avoids a certain optimization, what business change a specific field name maps to. This kind of knowledge cannot be obtained by reading the code itself, and it cannot be structured and passed to a language model. Researchers call this "the world outside the context window" — even as model context windows expand to hundreds of thousands of tokens, they still cannot hold the complete history and organizational context embedded in a medium-sized codebase. This explains why AI performs far better on greenfield projects (starting from scratch) than on legacy system maintenance: the former has almost no implicit constraints, while the latter is full of landmines that only long-tenured team members know about.
Maintenance Cost Is Where Software's True Weight Lies
The software industry has long recognized that code is read and modified far more often than it is written. As the article notes, from the moment a piece of code is written, it enters a long maintenance period — fixing bugs, adapting to new requirements, refactoring to handle growth. This work demands a holistic understanding of the existing system, not the isolated generation of new snippets.
When AI produces large volumes of code without architectural guardrails, it can accelerate the accumulation of technical debt. The faster code is generated, the more code humans must understand and maintain. In other words, AI increases the speed of code output but does not necessarily reduce the overall complexity of software engineering — it may simply shift that complexity into the harder-to-manage stages of review and maintenance.
The concept of technical debt, coined by software engineering pioneer Ward Cunningham in 1992, describes design compromises made in pursuit of short-term delivery speed — compromises that accumulate like interest and are eventually repaid through higher maintenance costs. AI-assisted programming introduces a new risk structure in this dimension: traditional technical debt is at least generated through deliberate decisions by engineers who understand the system, whereas debt introduced by AI-generated code may be far more insidious. The generator (the model) has no genuine understanding of the system's overall architecture, while the reviewer (the human) faces mounting pressure from an ever-growing volume of code. Together, these factors can allow debt to spread at scale before it is ever identified. Some teams have begun responding by introducing mandatory architectural review gates in their AI-assisted development workflows, explicitly distinguishing between "AI can generate it" and "it can be merged into the main branch" as two distinct quality standards.
Divisions in the Community Discussion
The reason this article resonated so broadly is that it touches on the widespread anxiety and reflection among practitioners regarding the "AI replaces programmers" narrative. In the Hacker News discussion, supporters felt the author had precisely identified the conceptual conflation of "coding" and "engineering" — a conflation often used to overstate the boundaries of AI's capabilities.
Dissenting voices cautioned against using this argument to underestimate the productivity gains AI tools provide. For well-defined tasks like prototyping, boilerplate code, and scripting, AI does meaningfully improve efficiency. The core disagreement isn't about whether AI is useful — it clearly is. The question is whether "useful" equals "solved." A tool that accelerates one part of a process is a fundamentally different thing from an entire discipline being conquered.
Practical Implications for Developers
For working developers, the value of this debate lies in recalibrating how they understand their own work. If professional value is anchored purely in "writing code," then AI does feel threatening. But once engineers recognize that their core competency lies in problem definition, system design, and long-term decision-making, AI is better seen as a capability multiplier rather than a replacement.
- Use AI as an accelerator for well-defined, repetitive coding tasks, and reserve your energy for requirements analysis and architectural trade-offs.
- Maintain a critical eye when reviewing AI-generated code, paying particular attention to whether it respects the system's implicit constraints.
- Keep investing in capabilities that are difficult to automate: business understanding, abstract design thinking, and cross-team communication.
The hard parts of software engineering have never lived at the syntax level. The judgment that "coding is not solved" is less a denial of AI's capabilities than a clarification of what software engineering actually is: the real complexity is hiding outside the code.
Related articles

Black Forager Alexis Nelson: From Foraging to Publishing, Happy Snacking, Don't Die
Black Forager Alexis Nikole Nelson visits Talks at Google, sharing her journey from childhood plant walks with her mother to publishing the cookbook Happy Snacking, Don't Die!, revealing the racial and land history behind foraging's rise and fall in America.

How to Present Your Ideas Effectively: Three Types of Revelation Talks
Revelation talks are the most direct way to convey ideas. This article breaks down three types — Wonder Walk, Dynamic Demo, and DreamScape — with classic examples from David Gayo, Michael Pritchard, and Sylvia Earle.

Modern Web Guidance: Letting AI Write Native Declarative Dialog Popovers
Google's Modern Web Guidance makes AI coding assistants prefer native declarative dialog capabilities over repetitive JavaScript event listeners, measurably cutting boilerplate code.