AI and their Hackathon Mentality
Jun 5, 2026
Estimated reading time: 4 minutes and 51 seconds
Table of Contents

Imagine your team is building an auditability layer for a payment platform that serves millions of requests per day.
The feature needs to track changes across payment providers, configuration updates and user-triggered payment operations. At the same time, the system is being migrated from legacy components into a more modular architecture with clearer domain boundaries.
Following your team’s commitment to AI adoption, you use Claude to help write the code.
──────────────────────────────────────────────────────────────────────────────
❯ Create an audit system for payments and save records linking the
current user changing the payment configuration or making a payment.
──────────────────────────────────────────────────────────────────────────────After a couple of minutes, it will spew out code that works for your intended use case and you seem to be happy.
However…
You start to review the generated code and you find things like:
- A service class that depends on a bunch of things and ties many systems together.
- Code using legacy patterns and functions you are trying to deprecate.
- Different domains use the service in slightly different ways.
- Illegal coupling between domains characterizing a diamond dependency graph.
- God component that knows about all domains.
- Unnecessary abstractions and fallback behavior that makes no sense for this usecase.
In the end, the senior engineer reviewing the code asks you to change your code to make it simpler and more aligned to the design principles of the system.
In the end, the problems boil down to unmaintainable code that does not evolve with the system and principles in place.

A very messy codebase
The Hackathon Mentality
The generated output fits into what I like to call the “hackathon mentality”, since it implements a workable solution using pre-existing components and hacking quick-wins to achieve the desired outcome. It is much like your typical hackathon competition where code maintainability is not a priority, only producing something that “wow’s” the judges.
Products of any kind evolve with time, they are organic little creatures that grow and adapt from customer feedback and changing business requirements. Backlogs and short deadlines often lead to some creative ways to achieve something on time, at the cost of accruing tech debt: you borrow from tomorrow’s work to ship something today.
However, AIs by their nature do not have the full picture of the system, of the problem to solve, of the ADRs defined for the system; you have to tell them all that upfront before they can do any work.
Even if we are to assume that we have RAG systems, skills and what not, there is still the well known problem of context degradation. The problem still persists even on top-of-the-line models with exceptionally huge context windows.
The maintenance problem with AI-generated code
Jialong Chen et al (Mar 2026) published their SWE-CI paper that explores the problem of evolving codebases written by AIs over time and how much regressions they introduce on subsequent iterations. The gist of what they did is picking up some projects, letting models define the next set of improvements and handing over to agents to implement those changes, tracking the amount of regressions (failed tests) introduced by each iteration.
This novel methodology allows us to quantify how well models handle codebase evolution, even though regression is just one of the metrics we can use to measure codebase evolution. The main finding of this study is that none of the models behave well by this metric and break tests quite often.
It is important to highlight the obvious upward trend of this metric as newer models are released, but unfortunately, I haven’t seen a follow-up article with this update.

SWE-CI benchmark metric of different models
Despite this, let’s do a little thought exercise and see if we can spot a trend:
- Code generated by AIs are often verbose and aggressively defensive on features, leading to a large of lines of code (LOC)
- Their hackathon mentality leads it to devise new patterns that solve this only problem and is not shared across the codebase, leading to more LOC
- The next iteration will read all this new code and consume more tokens in the context window
- Context degradation makes the agent unaware of bits of the codebase, so it writes new structures to solve newer problems
- The next iteration needs even more context to understand the codebase before writing new code
and so on, you can see the picture. This can lead to even more complex codebases and a growing budget to cover increased token consumption.
How to mitigate this issue?
Johntek values high quality codebases that are well suited for future iterations, reducing tech debt and improving maintainability. So what should we be aware to use these tools effectively without falling into these traps?
I’d recommend, in no particular order:
- Give the agent the architectural boundaries before asking for code.
- Define the desired integration point before implementation starts.
- Keep changes small enough to review with real attention.
- Reject code that introduces new patterns without justification.
- Treat generated code as a draft, not as a pull request.
- Prefer deleting unnecessary abstractions over accepting “flexible” code.
- Review for system fit, not only for correctness.
The last bullet is the most important one, and often I find myself writing code on my own instead of relying on agents, because I find it faster to do this rather than waiting for the agent to generate the code, saving precious tokens.
In the end, always ask yourself the following:
“Will my code be maintainable in the long run?”
Where I can help you
AI assisted development is not going away anytime soon. The teams that benefit most from it are those that combine automation with strong architectural judgment.
If your team is modernizing a legacy system or trying to keep a growing codebase maintainable, Johntek can help define the boundaries, review the architecture, and keep implementation aligned with long-term evolution.
If this is something you’d like to do, call me on one of my channels here.
Caveat
This is a super simplified example of a one-shot code generation. I am well aware that there are techniques that help produce more reliable code, like defining your problem upfront and delegating little tasks to agents.
But even in those cases I still anecdotally see issues like this emerge.
