5 Expensive AI Coding Pitfalls That Blew Up on Launch Day
This is not clickbait. Last month, I used Claude Code + Cursor to write an internal tool platform from scratch in 7 days, delivering it two weeks ahead of schedule. My boss praised me by name at the weekly meeting. Then, on the first day it went live, the alert group exploded with 47 messages.
Background First
Our team took on an internal request: build a data dashboard + ticket system for the operations team.
The requirements were not complex. The tech stack was React + Node.js + PostgreSQL. The normal schedule was two people for three weeks. But at that time, another colleague was pulled away to fight fires, leaving just me, with the schedule unchanged.
I thought, isn't this perfect? I just topped up Claude Code Max last month and renewed Cursor. For a CRUD project like this, wouldn't AI write the code effortlessly?
So I made a bold decision: Use AI to assist development throughout, aiming to deliver in one week.
The result was—I indeed finished writing it in one week. The codebase was roughly 12,000 lines, covering frontend, backend, database, and deployment scripts—the full package.
But on the first day after launch, three online incidents occurred.
In this article, I will write out the complete real experience of these 7 days and the 5 pitfalls I stepped into. Not to bash AI—AI indeed boosted my efficiency by more than 3 times. But the dark side that those "AI coding is awesome" articles won't tell you, I will.
Pitfall 1: AI-generated code "looks right," but data boundaries are full of landmines
On the third day, I asked Claude Code to write a data aggregation API that grouped and counted tickets by department, status, and time dimension.
The code AI provided was very clean:
async function getTicketStats(startDate, endDate, department) {
const result = await db.query(`
SELECT
department,
status,
DATE_TRUNC('day', created_at) as date,
COUNT(*) as count
FROM tickets
WHERE created_at BETWEEN $1 AND $2
AND ($3 IS NULL OR department = $3)
GROUP BY department, status, DATE_TRUNC('day', created_at)
ORDER BY date DESC
`, [startDate, endDate, department]);
return result.rows;
}
At first glance, no problem. Ran it in the test environment, data came out, charts rendered.
Performance after launch: The Operations Director said, "This data is wrong."
Where were the problems?
- Timezone issue:
DATE_TRUNCdefaults to UTC, but operations viewed data in Beijing time. Tickets spanning across days were assigned to the previous day. - Null value handling: When
departmentwas passed asundefined, the condition$3 IS NULLin PostgreSQL did not mean "ignore filtering," but matched records wheredepartment IS NULL. - Missing large pagination: No LIMIT was set. When a full year's time range was selected, it directly returned 120,000 rows of data, freezing the frontend chart library ECharts.
Each of these three problems was "AI wrote it correctly" at the code level, but all were bugs at the business level.
Fixed code:
async function getTicketStats(startDate, endDate, department) {
const conditions = [
'created_at >= $1',
'created_at < $2'
];
const params = [startDate, endDate];
if (department) {
conditions.push(`department = $${params.length + 1}`);
params.push(department);
}
const result = await db.query(`
SELECT
department,
status,
DATE_TRUNC('day', created_at AT TIME ZONE 'Asia/Shanghai') as date,
COUNT(*) as count
FROM tickets
WHERE ${conditions.join(' AND ')}
GROUP BY department, status, date
ORDER BY date DESC
LIMIT 10000
`, params);
return result.rows;
}
Lesson: AI doesn't understand your business timezone, doesn't know who your users are, doesn't grasp your data volume. It won't proactively ask you for this context; if you don't mention it, it doesn't care.
Pitfall 2: AI is exceptionally good at "reinventing the wheel," but never tells you there's an existing one
On the second day, I asked AI to write a file upload module supporting chunked uploads, resumable transfers, and progress display.
AI very excitedly wrote nearly 400 lines of code for me, including:
- Frontend chunking logic
- MD5 checksum
- Backend chunk merging
- Progress callbacks
It was written very completely, and I thought at the time, "This is amazing."
Until after launch, a colleague looked at my code and said:
"Um... why didn't you use the TUS protocol?
tus-js-client+tus-node-server, two packages combined, less than 20 lines of configuration and it's done."
My face turned green instantly.
AI's default behavior is to implement from scratch, not to first search for mature solutions. It won't say, "This requirement can actually be solved with three lines of code using library XXX," because its training objective is to generate code, not to help you write less code.
Lesson: Before letting AI write code, ask it one question first—"Are there mature open-source solutions for this requirement? List the top 3 most popular ones, compare their pros and cons."
This one prompt can save you 80% of wheel-reinventing code.
Pitfall 3: Copy-pasted AI-generated environment variables, almost committed the database password to Git
This pitfall almost got me fired.
On the fifth day, while configuring deployment scripts, I asked AI to help write a Docker Compose file. AI very "thoughtfully" generated a complete .env.example for me:
DATABASE_URL=postgresql://admin:your_password_here@localhost:5432/dashboard
JWT_SECRET=your-super-secret-key-change-this
REDIS_URL=redis://localhost:6379
I was rushing the schedule, directly changed your_password_here to the real password, and continued coding.
That night, when committing code, I habitually did git add .. Luckily, I glanced at the diff before committing—the .env file was prominently listed.
If this file had been pushed to the remote, it would have contained the production database's real password.
Later I checked and found that in the AI-generated project, .gitignore indeed had .env, but it had also generated the .env file itself. The problem was, in some cases, I had manually cleared the .gitignore cache (because another file wasn't taking effect and I was troubleshooting), causing .env to be tracked by Git.
Lessons:
- Never fill in real secrets directly in AI-generated configuration file templates
- Must run
git diff --cachedto check the staging area before committing - At project initialization, the first thing is to configure
.gitignoreandgit-secretsscanning
# Install git-secrets to automatically block secret commits
git secrets --install
git secrets --register-aws
git secrets --add 'password\s*=\s*.+'
Pitfall 4: AI-written unit tests had 90% coverage, but were all "self-congratulatory" tests
On the sixth day, I thought I needed to add tests before going live. I let AI generate a full suite of unit tests for me.
After running them, coverage was 92%. Beautiful!
But looking closely at the test content, I was numb:
// AI-generated test
describe('createTicket', () => {
it('should create a ticket successfully', async () => {
const mockTicket = {
title: 'Test Ticket',
description: 'Test Description',
department: 'Engineering',
priority: 'high'
};
db.query.mockResolvedValue({ rows: [{ id: 1, ...mockTicket }] });
const result = await createTicket(mockTicket);
expect(result).toEqual({ id: 1, ...mockTicket });
expect(db.query).toHaveBeenCalledTimes(1);
});
});
See the problem?
It's testing its own mocked return value. db.query is mocked to return { id: 1, ...mockTicket }, and then it asserts the result equals { id: 1, ...mockTicket }.
This test will never fail, because it's not testing business logic, but "whether the mock framework can return the value I set normally."
What should really be tested?
- When
titleis empty, does it throw a parameter validation error? - When
priorityis passed an illegal value (like"urgent"), what is the behavior? - When the database connection fails, is the error correctly wrapped and reported?
- When creating tickets with the same title concurrently, is there idempotent handling?
AI tested none of these boundary scenarios.
Lesson: AI-generated test coverage is false prosperity. When letting AI write tests, explicitly require: "Don't test the happy path, only test boundary conditions and exception scenarios. List the 5 scenarios you think are most likely to have bugs, then write tests for each scenario."
Pitfall 5: Speed too fast = skipped design, technical debt exploded after just one week
This is the most insidious pitfall.
Because AI wrote code so fast, I started writing code directly on the first day. No architecture diagram drawn, no API contract defined, no database ER diagram designed.
I used whatever AI suggested. Frontend component props definitions, backend API route structures, database table designs—all were "defined as we went."
As a result, one week after launch, operations raised three new requirements:
- Tickets need to support a "transfer" function
- The data dashboard needs to add "YoY/MoM" comparisons
- Need to add an "approval flow"
I looked at the existing database design. The assignee in the ticket table was just a VARCHAR field storing a person's name string. To support transfer, it meant needing transfer records, transfer times, and a historical assignee chain. The entire table structure needed to be redesigned.
The approval flow was even worse—the existing status field was just an ENUM('open', 'in_progress', 'closed'). To implement an approval flow meant introducing a state machine, adding logic for approvers, approval comments, rejection and resubmission, etc.
If I had spent half a day on design initially, these extensibilities could have been reserved in advance. But AI gave me the illusion that "writing code is fast anyway," causing me to skip the most important design phase.
Lesson: AI accelerates the "writing code" phase, but the most expensive part of software development has never been writing code—it's design. Before starting, let AI help you do a design review:
prompt: "I want to develop a ticket system, the core features are XXX.
Please help me with the following designs:
1. Database ER diagram (consider possible future extensions: transfer, approval flow, tag system)
2. API contract (RESTful, list all endpoints)
3. Frontend page routing structure
4. Where do you think this system is most likely to accumulate technical debt?"
Review: Reflections After One Week
That weekend after launch, I spent two days fixing bugs + refactoring. Looking back at these 7 days, my conclusion is:
AI Indeed Helped Me
- 12,000 lines of code. If written purely by hand, it would take at least three weeks. AI helped me compress it into one week.
- A lot of boilerplate code (CRUD APIs, form validation, SQL table creation statements) AI wrote quickly and standardly.
- For unfamiliar libraries (like ECharts configuration options), AI was 10 times faster than browsing documentation.
But What AI Cannot Replace
| Capability | AI Can Do | AI Cannot Do |
|---|---|---|
| Writing Code | Generate quickly | Understand business context |
| Testing | Generate templates | Identify real boundary scenarios |
| Architecture Design | Give proposals | Judge which proposal suits your team |
| Security | Generate example configs | Guarantee you won't make rookie mistakes |
| Debug | Analyze error logs | Understand the complexity of the online environment |
My Current AI Coding Workflow (Post-Pitfall Version)
1. Requirements analysis (do it myself) → 30 minutes
2. Let AI do architecture design + review it myself → 2 hours
3. Define API contracts and data models (complete interactively with AI) → 1 hour
4. AI generates code + I review file by file → Main development time
5. I write tests for core business logic, AI supplements tests for utility functions
6. Pre-launch security checklist (manual + git-secrets)
Key principle: AI is a co-pilot, not autopilot. You can let it help you steer, but you cannot close your eyes.
Final Words
I'm not trying to persuade you not to use AI for coding. Quite the opposite, after this experience of stepping into pitfalls, I'm now even more dependent on AI.
But what I want to say is: AI makes writing code faster, but it hasn't made writing "good code" easier. Quite the opposite, because the generation speed is too fast, many steps that should have been carefully considered are skipped.
Next time you use AI to finish a week's worth of work in a day, don't rush to post about it on social media.
Ask yourself one question: Do you dare to deploy this code without reviewing it?
If the answer is "No"—then the time AI saved you should be spent on Review.
If you are also using AI to write code, feel free to comment and share the pitfalls you've encountered. Like and bookmark so you don't get lost; I will continue to share practical experiences in AI programming.
Top 7 of 22 from juejin.cn, machine-translated. The original thread is authoritative.
Pitfall #1 really resonates. Last month I shipped a Chrome extension, and AI helped me write logic that encodes the current URL into a storage key. It worked fine in testing, but one user installed it with a URL starting with %2F%2F, and the extension wouldn't open at all — spent an afternoon debugging before I found the key encoding collision. I'm stealing your 'ask AI if there's an existing solution first' tip; it's a counterintuitive but very useful habit. My current workflow: before writing any code, I ask 'what are the 3 most likely pitfalls here?' That avoids 80% of rework compared to just asking for code directly. One last thing — a sixth pitfall you might hit soon: instrument logging and monitoring from the very first line of code you write. Don't wait until after launch to add it, or you'll just stare at 47 alerts with no idea what happened in the first five minutes.
Yeah, monitoring is also a really important point [lightbulb moment]
Yeah, on monitoring I later added a layer of custom performance.mark metrics, splitting model latency into prompt cache hit / decode / TTFT three segments. After running for a while you can tell whether the prompt template is getting slower or it's network jitter. Do you have a similar metrics system on your side?
Add skills
Then recommend some good skills [mischievous grin]
superpower is pretty good, you can give it a try
Does the company reimburse AI usage costs?
Yeah haha how did you know
Otherwise you'd just be paying to work, nobody's that dumb [grin]
Review all the code AI writes yourself???
At least check the core logic, otherwise the risk is too high
Great summary. My customer service system (https://kf.shengxunwei.com/) currently also uses AI to assist with app and website integration, and it has the same reinventing-the-wheel problem, requiring manual intervention.
[lightbulb moment]
So finishing a project and launching it in 9 days, isn't that impressive
An approach similar to Sentry is the right idea; it's essentially the 'application layer → reporting channel → aggregation & analysis' pipeline. I ended up building a lightweight SDK myself, about 3 files: capture layer with try/catch + unhandledrejection, reporting layer with beacon + retry on failure, analysis layer using ClickHouse for OLAP. I wonder about your internal platform — how do you handle alert noise reduction? Is false-positive suppression still rule-and-threshold based, and do you basically manually silence alerts for the first few days after a new version release?