AI có khả năng xâu chuỗi câu từ rất thuyết phục, tạo cảm giác về một quy trình phân tích bài bản. Nhưng thứ khiến các giải pháp do AI đề xuất bị đổ vỡ khi đưa vào môi trường vận hành thực tế luôn là sự đứt gãy trong chuỗi suy luận. Dưới đây là 5 case đứt gãy điển hình đúc kết từ hơn 1 năm làm việc cùng AI và kinh nghiệm thực chiến giúp các product builder giảm thiểu lỗi.
Vibe coding với AI: 5 cái bẫy khiến sản phẩm đổ vỡ khi lên production
Trong suốt hơn một năm làm việc cùng các mô hình AI qua rất nhiều dự án và công việc — từ phân tích nghiệp vụ, thiết kế kiến trúc cho tới kiểm thử phần mềm — đội ngũ mình đã ghi nhận lại hàng trăm bài học thực tế trong hệ thống quản lý context của team (lob-brain, mình sẽ chia sẻ tool này vào 1 bài khác hen).
Khi nhìn lại kho dữ liệu này, một sự thật rõ ràng hiện lên: khi làm việc với AI, câu trả lời hay code nó sinh ra nhìn qua rất trơn tru, format bài bản. Nhưng thứ khiến các giải pháp do AI đề xuất bị đổ vỡ khi đưa vào môi trường vận hành thực tế luôn là sự đứt gãy trong chuỗi suy luận.
AI có khả năng xâu chuỗi câu từ rất thuyết phục, tạo cho người đọc cảm giác về một quy trình phân tích bài bản. Nhưng nếu chỉ nhìn vào các hiện tượng bề nổi như test pass nhưng tính năng vẫn hỏng, hay giao diện hiện cảnh báo nhưng dữ liệu rác vẫn lọt vào cơ sở dữ liệu, chúng ta mới chỉ thấy được các triệu chứng bên ngoài.
Để giúp các bạn product builder giảm thiểu khả năng lỗi trong quá trình làm việc, mình có một vài kinh nghiệm chia sẻ như sau:
Case 1: Tự dựng bằng chứng giả để kết luận xong việc
AI luôn bị chi phối bởi xu hướng tối ưu hóa việc trả lời xong tác vụ hơn là tính chân thực của quy trình kiểm chứng. Khi gặp khoảng trống về dữ liệu hoặc đối mặt với các bài test phức tạp, AI thường tự tạo ra các dữ liệu trung gian hoặc dựng lên các kịch bản test giả định để tự hợp thức hóa kết luận của mình.
Khi mình làm, có vài case kiểu như:
- AI viết một hàm validate mới toanh rồi tự viết unit test gọi thẳng vào hàm đó. Test chạy pass hết. Nhưng thực tế ở backend, API của hệ thống lại đang chạy một hàm native cũ ghi đè lên luồng đó. Cái hàm mà AI vừa viết và tự hào là test đã pass thực chất nằm ở một nhánh chết, chưa từng được hệ thống gọi tới một lần nào khi người dùng thao tác thật.
- Khi làm test tự động cho giao diện (ví dụ test E2E bằng Playwright), AI tạo ra hàng chục test case nhưng assert chỉ kiểm tra xem class của nút có đổi màu không, hoặc click vào một thẻ container bao ngoài (
.container) là coi như pass, trong khi dữ liệu người dùng gõ vào form có thực sự submit thành công hay không thì bị bỏ qua. - Khi thiếu dữ liệu kết nối đến các dịch vụ bên ngoài, AI âm thầm bật cờ dữ liệu giả lập (mock data) hoặc tự suy diễn ra các danh sách công việc, mốc thời gian ảo mà không hề có căn cứ thực tế.
Bản chất ở đây là AI dùng chính kết quả do mình tự quy định để chứng minh cho độ chính xác của giải pháp mình vừa đưa ra.
Kinh nghiệm xử lý của mình: Không bao giờ chấp nhận các kết quả test phụ thuộc vào dữ liệu mock do chính AI tự tạo ra. Nếu hệ thống đã chạy, bài test bắt buộc phải đi qua đúng cổng API/RPC thực tế. Nếu hệ thống mới tinh chưa đưa vào vận hành, bạn cần chủ động chuẩn bị bộ seed data sát với thực tế, giả lập các bài toán hoặc các kịch bản ngoại lệ để thử nghiệm luồng chạy thật sự của dữ liệu.
Case 2: Đánh đồng kết quả phản hồi bề nổi với trạng thái dữ liệu
Khác với mục 1 (test được viết sai nên không bắt được lỗi), ở mục này AI không cần viết test nào. Nó tự nhìn phản hồi bề mặt rồi kết luận xong việc.
Khi các bạn chuyên vibe code hoặc dùng AI coding agent (như Cursor, Claude Code) đưa prompt yêu cầu test một tính năng, AI thường làm bằng cách đọc HTML, inspect DOM hoặc chạy lệnh curl gọi API. Khi thấy API trả về status 200 OK, hoặc thấy component hiển thị đúng thẻ HTML mong muốn, AI thường kết luận ngay là tính năng đã hoàn thành.
Thực tế thì phản hồi bề mặt này hoàn toàn khác với việc dữ liệu đã được lưu trữ an toàn:
- API trả về status 200 OK không đồng nghĩa với việc transaction đã được commit thành công vào cơ sở dữ liệu. Nhiều trường hợp backend bắt lỗi nhưng nuốt luôn (silent fail), hoặc trả về
{ success: false }bên trong gói tin nhưng mã HTTP vẫn là 200. AI chỉ soi mã 200 là vội báo xong việc. - Người dùng gõ số liệu vào ô nhập liệu, giao diện hiển thị số bình thường. Nhưng state đó không hề được bind vào payload gửi lên server, hoặc server nhận được nhưng không map vào câu lệnh UPDATE database. Kết quả là tải lại trang một cái là toàn bộ dữ liệu biến mất sạch sẽ.
- Có ô số do hệ thống tự tính, người dùng gõ đè một số khác lên. Giao diện hiện đúng số vừa gõ, nhưng hệ thống không ghi lại là ô này đã bị người dùng sửa tay. Lần đọc sau nó tính lại và đè ngược số của người dùng, không báo lỗi gì. Một báo cáo khác thì đọc dữ liệu qua đường thô nên hoàn toàn không thấy số từ hệ thống bên cạnh: màn hình vẫn hiện con số, chỉ là con số thiếu.
AI dễ bị đánh lừa bởi phản hồi bề mặt (UI rendering hoặc HTTP code) mà bỏ qua sự biến đổi trạng thái cốt lõi của dữ liệu bên dưới.
Kinh nghiệm xử lý của mình: Tiêu chí nghiệm thu phải được đo lường trực tiếp ở tầng dữ liệu (database state). Một thao tác chỉ được xem là xong khi bạn truy vấn trực tiếp vào cơ sở dữ liệu và thấy số lượng bản ghi cũng như giá trị các trường cốt lõi phản ánh chính xác nghiệp vụ.
Case 3: Tư duy cục bộ — Vá một điểm, ảnh hưởng toàn bộ hệ thống
Khi nhận được yêu cầu xử lý một lỗi cụ thể, AI thường chỉ tập trung vào đúng phạm vi hẹp của prompt mà quên mất bức tranh tổng thể của hệ thống.
Sự thiếu vắng góc nhìn tổng thể này rất dễ dẫn đến lỗi dây chuyền:
- Phân quyền theo kiểu "che mắt": Khi bạn yêu cầu phân quyền để nhân viên không xem được dữ liệu nhạy cảm (như bảng lương, doanh thu hay báo cáo tài chính), AI thường chỉ làm đúng một thao tác đơn giản là ẩn cái nút menu trên thanh sidebar điều hướng. Nhưng người dùng chỉ cần gõ thẳng URL, hoặc click vào các tab con bên trong trang chi tiết là dữ liệu vẫn hiện ra mồn một vì các tab con và các endpoint API bên dưới hoàn toàn không có chốt chặn kiểm tra quyền.
- Ghép dữ liệu theo tên thay vì theo mã định danh: Ở một báo cáo lãi lỗ, tên dòng được dùng làm một phần của khóa ghép. Chỉ cần đổi tên một dòng là mọi chỗ đang trỏ tới dòng đó (kế hoạch, nguồn số liệu) bị đứt âm thầm, không báo lỗi gì. Cách sửa là tách danh tính của dòng ra khỏi tên và khỏi năm, mọi nơi trỏ bằng mã định danh. Kéo theo một hệ quả phải cân nhắc: từ lúc đó, đổi tên một dòng sẽ áp cho mọi năm.
- Đứt tầng chuyển đổi dữ liệu trung gian: Khi cho phép khai báo thêm trường tuỳ biến, bảng dữ liệu và form đều đã sẵn sàng, nhưng tầng trung gian chuẩn bị dữ liệu cho màn hình lại trả về danh sách trường rỗng cứng. Kết quả là khai báo trường xong mà form không hiện ô nào. Một biến thể nặng hơn: khi giao diện nạp dữ liệu hỏng rồi gửi lên một danh sách rỗng, hệ thống hiểu là người dùng muốn xóa hết, và xóa sạch nhãn, cấu hình của cả công ty. Vì vậy mình chốt luật: lô ghi kiểu gửi toàn bộ danh sách mà rỗng thì bị từ chối.
AI thiếu nhận thức về phạm vi ảnh hưởng (blast radius). Nó giải quyết rất nhanh việc trước mắt bằng cách làm biến dạng các cấu trúc dữ liệu nền tảng mà các phần khác đang phụ thuộc vào.
Kinh nghiệm xử lý của mình: Trước khi cho phép AI sửa đổi bất kỳ cấu trúc dữ liệu hay logic nghiệp vụ nào, bắt buộc phải yêu cầu AI làm impact analysis trước: Cấu trúc này đang được những thành phần nào khác sử dụng, và việc thay đổi có làm sai lệch dữ liệu ở các chiều không gian hoặc thời gian khác hay không?
Case 4: Dùng lý thuyết để né tránh bài toán thực tế
AI được huấn luyện trên khối lượng dữ liệu khổng lồ từ giáo trình và các bài viết. Do đó, khi đối mặt với những yêu cầu nghiệp vụ thực tế có tính đặc thù, AI rất hay đưa ra các giải pháp lý thuyết hóa.
Khi mình làm việc cùng AI, tình trạng này xuất hiện khá rõ:
- Khi được yêu cầu soạn tài liệu quy trình hay giáo trình nghiệp vụ, AI thường tự vẽ ra các ma trận phân loại nhiều bước, các công thức giả định nghe rất kêu nhưng hoàn toàn không thể đưa vào áp dụng thực tế. Đọc qua thì thấy nhiều chữ, nhưng thực chất chỉ là nói về chủ đề chứ không giải quyết được việc.
- Khi được hỏi hệ thống đã có một chức năng nào đó chưa, AI nhiều lần kết luận "chưa có" theo khuôn quen thuộc, trong khi bản đang chạy đã có. Chỉ là bản mới chưa chuyển hết sang và màn hình im lặng bỏ qua lỗi nên trông như chưa có gì. Ba lần liên tiếp kết luận sai kiểu này, mỗi lần đều khiến người làm phải lật lại từ đầu.
- Khi gặp lỗi cấu hình trong một công cụ cụ thể, AI đoán mò và thử đi thử lại hàng chục cách chắp vá thay vì chịu khó đọc kỹ tài liệu kỹ thuật gốc của công cụ đó.
AI lấy sự phức tạp về mặt hình thức để khỏa lấp sự thiếu hiểu biết sâu sắc về bối cảnh vận hành thực tế của dự án. Nhưng một phần lớn khác, nó cũng xuất phát từ tâm lý "cho xong việc" giống như ở mục 1: thay vì đào sâu vào context hoặc hỏi lại bạn cho rõ ràng, AI chọn con đường dễ nhất là lôi các mô hình lý thuyết có sẵn ra để tạo thành một câu trả lời dài và bài bản nhằm khép lại lượt chat thật nhanh.
Kinh nghiệm xử lý của mình: Gạt bỏ ngay những giải pháp mang nặng tính giáo điều hoặc các đề xuất kiến trúc quá tầm quy mô. Yêu cầu AI đưa ra các step có thể kiểm thử được, các dữ liệu mock có thể chứng minh được hoặc giả lập bài toán cụ thể để thử nghiệm trước khi quyết định áp dụng.
Case 5: Giả định thuận chiều trong môi trường lý tưởng
Chuỗi suy luận của AI thường được xây dựng trong một môi trường lý tưởng — nơi mạng không bao giờ rớt, máy chủ không bao giờ cạn tài nguyên và dữ liệu luôn đi theo luồng thuận (happy path).
Điều này khiến hệ thống gặp vấn đề khi triển khai, thậm chí ngay từ bước test luồng vận hành thực tế. Như mấy case mình gặp dưới đây:
- Chẳng hạn vụ tích hợp thanh toán: khách chuyển khoản đúng số tiền, đúng nội dung, nhưng đơn vẫn ở trạng thái chờ. Hệ thống có sẵn job đối soát chạy định kỳ, nên vấn đề không nằm ở chỗ thiếu job. Ở lần xử lý đầu, giao dịch gặp lỗi tạm nên bị ghi là chưa khớp. Sau đó, cơ chế chống trùng lặp (dựa trên mã giao dịch và cặp nội dung với số tiền) khiến mọi lần đối soát sau đều bỏ qua giao dịch này. Giao dịch kẹt vĩnh viễn dù đơn đã có sẵn trong hệ thống. Code ban đầu chỉ tính đến luồng thuận là giao dịch được xử lý đúng ngay lần đầu, nên không có đường nào thử lại. Cách mình xử lý: thêm bước khớp lại ngay trong vòng đối soát, và thêm nút ghép tay trong trang quản trị cho những ca khách chuyển sai nội dung.
- Khi đưa hệ thống lên máy chủ thật, code chạy rất mượt ở máy cá nhân nhưng máy chủ có tài nguyên và cấu hình khác: ổ cứng nhỏ nhanh đầy vì log và bộ nhớ đệm, phải dọn mới còn chỗ; cổng 80/443 có thể đã bị dịch vụ khác chiếm, nên bộ cài phải tự dò và bỏ qua cổng đó thay vì cố chiếm.
- Sửa một quy ước mặc định tưởng là xong, nhưng dữ liệu cũ không tự đổi theo. Chẳng hạn khi bỏ luật ngầm "tài khoản chưa gán vai trò thì có toàn quyền", phải chạy một đợt chuyển dữ liệu để gán vai trò rõ ràng cho mọi tài khoản cũ trước, rồi mới bỏ luật. Đảo thứ tự là mọi tài khoản cũ mất quyền ngay. Hơn một trăm chỗ trong các test cũ cũng đang dựa vào luật cũ nên phải sửa theo.
Bản chất ở đây là AI hoàn toàn không có cảm nhận về các điều kiện biên và ma sát hạ tầng trong quá trình vận hành liên tục.
Kinh nghiệm xử lý của mình: Mọi thiết kế luồng do AI đề xuất đều phải đi kèm kịch bản xử lý ngoại lệ: Điều gì xảy ra khi webhook không về, khi mạng bị đứt giữa chừng, hoặc khi tài nguyên máy chủ chạm ngưỡng giới hạn? Bên cạnh các ca lỗi kỹ thuật đó còn có các ca ngoại lệ nghiệp vụ: khách bấm thanh toán hai lần, đơn bị hủy giữa chừng, hay hai người cùng duyệt một đơn. Mỗi loại cần có test riêng.
Lời kết
Làm việc với AI để build sản phẩm không phải là giao hết việc cho nó rồi mong chờ một kết quả hoàn hảo.
Giá trị cốt lõi của một product builder hoặc vibe coder nằm ở năng lực nhìn ra những điểm đứt gãy trong chuỗi suy luận của máy móc. Hy vọng kinh nghiệm của mình giúp bạn hoặc giúp sản phẩm của bạn vận hành ổn định và đúng với thực tế nghiệp vụ hơn trong tương lai. Happy reading.


