When asked to modify or rewrite functionality, LLMs often attempt to preserve compatibility with previous versions, even on greenfield projects. This defensive behavior can lead to overly complex code and technical debt. Developers must explicitly state that backward compatibility is not a requirement.
Overly structured, workflow-based systems that work with today's models will become bottlenecks tomorrow. Engineers must be prepared to shed abstractions and rebuild simpler, more general systems to capture the gains from exponentially improving models.
Features built to guide AI agents, like an explicit "plan mode," will become obsolete as models become more capable. The Claude Code team embraces this, building what's needed for the best current experience and fully expecting to delete that code when a new model renders it unnecessary.
Newer LLMs exhibit a more homogenized writing style than earlier versions like GPT-3. This is due to "style burn-in," where training on outputs from previous generations reinforces a specific, often less creative, tone. The model’s style becomes path-dependent, losing the raw variety of its original training data.
AI can generate code that passes initial tests and QA but contains subtle, critical flaws like inverted boolean checks. This creates 'trust debt,' where the system seems reliable but harbors hidden failures. These latent bugs are costly and time-consuming to debug post-launch, eroding confidence in the codebase.
AI coding tools dramatically accelerate development, but this speed amplifies technical debt creation exponentially. A small team can now generate a massive, fragile codebase with inconsistent patterns and sparse documentation, creating maintenance burdens previously seen only in large, legacy organizations.
The long-held rule by Joel Spolsky to "never rewrite your code" no longer applies in the AI era. For an increasing number of scenarios, it is more efficient to have an LLM regenerate an entire system, like a unit test suite, from scratch than to attempt to incrementally fix or refactor it.
LLMs may use available packages in a project's environment without properly declaring them in configuration files like `package.json`. This leads to fragile builds that work locally but break on fresh installations. Developers must manually verify and instruct the LLM to add all required dependencies.
When given ambiguous instructions, LLMs will choose the most common technology stack from their training data (e.g., React with Tailwind), even if it contradicts the project's goals. Developers must provide explicit constraints to avoid this unwanted default behavior.
Instead of fighting for perfect code upfront, accept that AI assistants can generate verbose code. Build a dedicated "refactoring" phase into your process, using AI with specific rules to clean up and restructure the initial output. This allows you to actively manage technical debt created by AI-powered speed.
Developing LLM applications requires solving for three infinite variables: how information is represented, which tools the model can access, and the prompt itself. This makes the process less like engineering and more like an art, where intuition guides you to a local maxima rather than a single optimal solution.