Debug giỏi không phải là gõ
console.lognhanh hơn người khác — mà là biết đặt câu hỏi đúng, và AI chỉ thực sự hữu ích khi bạn buộc nó trả lời bằng bằng chứng chứ không phải phỏng đoán.
Phương pháp debug kiểu khoa học
Phần lớn kỹ sư debug theo bản năng: đọc code, đoán chỗ sai, sửa, chạy lại, lặp lại đến khi hết lỗi. Cách này hoạt động ổn với bug đơn giản, nhưng với bug khó — race condition, memory leak, lỗi chỉ xảy ra ở production với tải cao — nó biến thành một vòng lặp đoán mò vô tận, tốn hàng giờ mà không tiến thêm bước nào.
Debug có hệ thống mượn nguyên tắc của phương pháp khoa học, gồm bốn bước lặp lại:
- Quan sát (Observe) — Thu thập triệu chứng: log, stack trace, số liệu, các bước tái hiện. Không suy diễn, chỉ ghi nhận sự thật.
- Đặt giả thuyết (Hypothesize) — Dựa trên quan sát, liệt kê các nguyên nhân có thể gây ra hiện tượng này. Quan trọng: nhiều hơn một giả thuyết, không chốt ngay giả thuyết đầu tiên nghe hợp lý.
- Kiểm định (Test) — Với mỗi giả thuyết, thiết kế một thực nghiệm tối thiểu để xác nhận hoặc bác bỏ nó — thêm log có mục tiêu, viết test tái hiện, dùng debugger để breakpoint đúng chỗ nghi ngờ.
- Loại trừ (Eliminate) — Bác bỏ giả thuyết sai bằng bằng chứng cụ thể, giữ lại giả thuyết còn sống, lặp lại cho đến khi chỉ còn một nguyên nhân đứng vững trước mọi bằng chứng.
Đây chính là root cause analysis (RCA - phân tích nguyên nhân gốc rễ) thu nhỏ ở cấp độ một bug đơn lẻ, thay vì một buổi postmortem (báo cáo sau sự cố) sau sự cố lớn.
AI thay đổi cuộc chơi ở chỗ nó có thể tăng tốc bước 2 (sinh giả thuyết) và bước 3 (thiết kế thực nghiệm) một cách đáng kể — miễn là bạn cho nó đủ ngữ cảnh (context) và không để nó nhảy thẳng sang bước 4 mà bỏ qua kiểm định. Cái bẫy phổ biến nhất khi dùng Copilot, Cursor hay Claude Code để debug là: AI đưa ra một "giải thích nghe rất hợp lý" ngay lập tức, và vì nó tự tin, viết mạch lạc, kỹ sư tin luôn mà không kiểm định — rồi patch sai chỗ, bug vẫn còn nguyên nhưng ẩn sâu hơn.
Nguyên tắc vàng: AI được phép đề xuất giả thuyết không giới hạn, nhưng mỗi giả thuyết phải được gắn với một cách kiểm định cụ thể trước khi bạn viết fix. Nếu AI nói "có thể do X gây ra", câu hỏi tiếp theo luôn là "Vậy log/test nào sẽ xác nhận hoặc loại bỏ X?"
Mẹo: Trước khi mở AI assistant, dành 2 phút viết ra giấy (hoặc trong file
debug-notes.md) đúng 3 dòng: triệu chứng quan sát được, điều kiện tái hiện, và điều bạn KHÔNG chắc chắn. Ba dòng này chính là context chất lượng cao nhất bạn có thể đưa cho AI — tốt hơn nhiều so với việc paste nguyên stack trace và hỏi "sao lỗi vậy?".
Viết prompt "Help Me Debug This" hiệu quả
Chất lượng câu trả lời của AI khi debug tỷ lệ thuận với chất lượng context bạn cung cấp. Một prompt kiểu "app bị crash, sửa giúp mình" gần như vô dụng — AI sẽ đoán mò y hệt một kỹ sư junior không có thông tin gì.
Một prompt debug tốt cần có đủ 5 thành phần:
- Triệu chứng chính xác: thông báo lỗi/stack trace nguyên văn, không diễn giải lại.
- Điều kiện tái hiện: xảy ra luôn hay ngẫu nhiên? Bao nhiêu % request bị ảnh hưởng? Có pattern theo thời gian, tải, hay input cụ thể không?
- Ngữ cảnh code liên quan: không phải cả repo, mà đúng những file/hàm nằm trên đường đi của luồng lỗi.
- Những gì đã thử: để AI không đề xuất lại thứ bạn đã loại trừ.
- Kỳ vọng đầu ra: bạn muốn giả thuyết, muốn code fix, hay muốn một kế hoạch kiểm định?
Ví dụ một prompt yếu:
My API is returning 500 sometimes. Can you fix it?
Và một prompt tốt, đúng chất "help me debug this":
I'm seeing intermittent 500 errors on POST /api/orders, roughly 2-3%
of requests during peak traffic (9-11am), never during low traffic.
Stack trace from Sentry:
psycopg2.errors.SerializationFailure: could not serialize access
due to concurrent update
at app/services/order_service.py:142 in reserve_inventory()
at app/api/orders.py:58 in create_order()
Relevant code (order_service.py, lines 120-150):
[paste the actual function here]
What I've already ruled out:
- Not a connection pool exhaustion issue (pool metrics look healthy)
- Not related to a specific customer or SKU
I want you to:
1. List possible root causes ranked by likelihood given this is a
Postgres serialization failure under concurrent writes.
2. For each, tell me exactly what log statement, query, or test I
should add to confirm or rule it out — don't just give me a fix yet.
Khác biệt cốt lõi: prompt tốt biến AI từ "máy đoán" thành "cộng sự tư duy có kỷ luật", vì bạn đã tự giới hạn không gian giả thuyết bằng dữ liệu thật, và bạn yêu cầu rõ ràng bước kiểm định trước khi có fix.
Một mẹo hay khi dùng agentic tool như Claude Code hoặc Cursor: yêu cầu AI tự đọc code thay vì bạn paste tay. Ví dụ: "Read app/services/order_service.py and app/api/orders.py, trace the call path for POST /api/orders, then list hypotheses..." — điều này tận dụng khả năng agent tự explore codebase, thường phát hiện những đoạn code liên quan mà bạn quên đề cập.
Mẹo: Luôn dán stack trace/log NGUYÊN VĂN, không tóm tắt bằng lời của bạn. AI đọc số dòng, tên exception, và thứ tự call stack tốt hơn nhiều so với việc bạn diễn giải "nó lỗi ở đâu đó trong service tạo đơn hàng".
Dùng AI để sinh danh sách giả thuyết có xếp hạng
Một trong những ứng dụng mạnh nhất của AI trong debug không phải là "tìm fix", mà là "mở rộng không gian giả thuyết" — nhất là khi bạn đã bí, chỉ nghĩ ra 1-2 khả năng và cả hai đều sai.
Kỹ thuật hiệu quả: yêu cầu AI liệt kê ít nhất 5-8 giả thuyết, xếp hạng theo xác suất, kèm lý do và cách kiểm định. Ép số lượng tối thiểu buộc mô hình phải suy nghĩ ra ngoài "câu trả lời hiển nhiên đầu tiên" — thứ mà con người cũng dễ mắc kẹt vào (thiên kiến xác nhận, confirmation bias).
Ví dụ prompt:
Given this bug: our WebSocket connections silently drop after
~10-15 minutes under load, only in production (never in staging),
and only for clients on mobile networks (confirmed via analytics).
Generate 6 ranked hypotheses for the root cause. For each one:
- Likelihood (high/medium/low) and why
- What evidence would confirm it (specific log line, metric, or command)
- What evidence would rule it out
Consider: infra/load balancer config, client-side network behavior,
server-side timeout settings, and application-level bugs separately.
Kết quả thường trả về sẽ trải rộng nhiều tầng: timeout của load balancer (ALB idle timeout mặc định 60s, ping/pong interval của WebSocket không khớp), NAT timeout trên mạng di động, thiếu heartbeat ở tầng ứng dụng, hay giới hạn concurrent connections ở reverse proxy. Đây chính xác là kiểu danh sách một kỹ sư senior giàu kinh nghiệm về hạ tầng sẽ liệt kê — và AI tổng hợp nhanh hơn vì nó "nhớ" hàng nghìn case tương tự từ dữ liệu huấn luyện.
Điều quan trọng: xếp hạng của AI không phải chân lý. Nó xếp theo tần suất gặp trong dữ liệu huấn luyện, không phải theo xác suất thực tế trong hệ thống của bạn. Một giả thuyết AI xếp hạng thấp có thể chính là nguyên nhân thật nếu kiến trúc của bạn có đặc thù riêng (ví dụ dùng custom load balancer, hay một thư viện ít phổ biến). Vai trò của bạn là dùng kiến thức về hệ thống cụ thể để tái xếp hạng, không phải nhắm mắt làm theo thứ tự AI đưa ra.
Một kỹ thuật nâng cao: yêu cầu AI đóng vai "devil's advocate" — phản biện lại giả thuyết đang được ưa thích nhất của chính bạn:
My leading hypothesis is that the ALB idle timeout (60s) is closing
connections before our app-level ping interval (90s) fires. Play
devil's advocate: what evidence would contradict this hypothesis,
and what else could produce the exact same symptom (disconnect at
10-15 min mark, mobile only)?
Kỹ thuật này chống lại xu hướng cả người lẫn AI đều dễ "chốt hạ quá sớm" (anchoring) vào giả thuyết đầu tiên nghe hợp lý.
Mẹo: Khi AI liệt kê giả thuyết, luôn hỏi thêm "which of these have you seen most often in real production incidents, and which are more theoretical?" — câu trả lời giúp bạn phân biệt giữa lý thuyết sách vở và kinh nghiệm thực chiến được mã hóa trong dữ liệu huấn luyện.
Nâng cấp kỹ thuật "rubber duck debugging"
Rubber duck debugging — giải thích bug cho một con vịt cao su (hoặc đồng nghiệp không biết gì về code) để tự mình nhận ra vấn đề — hoạt động vì hành động diễn đạt thành lời buộc não bạn kiểm tra lại các giả định ngầm mà bạn đã bỏ qua khi đọc lướt code trong đầu.
AI nâng cấp kỹ thuật này theo hai hướng mà con vịt cao su không làm được:
1. AI phản hồi lại, con vịt thì không. Khi bạn giải thích luồng logic cho Claude hay ChatGPT, nó có thể ngắt lời hỏi "Wait, but what happens if userId is null at this point?" — đúng khoảnh khắc bạn đang lướt qua một giả định chưa kiểm chứng. Đây là điểm khác biệt lớn nhất: con vịt thụ động, AI chủ động chất vấn.
2. AI có thể đọc code thật, không chỉ nghe bạn mô tả. Với agentic tool, bạn có thể yêu cầu: "Explain back to me, step by step, what this function does and what assumptions it's making about its inputs" — buộc AI tường thuật lại logic bằng lời của chính nó. Nếu phần tường thuật đó khác với những gì bạn nghĩ code làm, khoảng cách đó chính là nơi bug đang ẩn náu.
Prompt mẫu cho kỹ thuật "rubber duck nâng cấp":
I'm going to explain what I think this function does. After I'm
done, read the actual code in payment_processor.py lines 80-130 and
tell me everywhere my explanation doesn't match the real behavior —
especially edge cases I might be glossing over.
My explanation: When a payment webhook arrives, we look up the order
by external_id, mark it as paid, then trigger fulfillment. If the
order isn't found, we log a warning and return 200 so the webhook
provider doesn't retry.
Cách dùng này lật ngược vai trò thông thường: thay vì hỏi AI "code này có bug gì", bạn buộc chính mình trình bày hiểu biết trước, rồi để AI làm trọng tài đối chiếu với code thật. Kỹ thuật này đặc biệt hiệu quả với bug logic tinh vi (off-by-one, điều kiện biên, thứ tự thực thi async) — những lỗi mà đọc lướt code không phát hiện ra vì não tự động "vá" chỗ thiếu logic bằng giả định sai.
Một biến thể khác: yêu cầu AI đóng vai người mới vào team, hỏi những câu "ngu ngơ":
Pretend you're a new engineer seeing this codebase for the first
time. Ask me 5 clarifying questions about how `reserve_inventory()`
handles concurrent access that a careful reviewer would ask before
approving this code.
Nhiều lần, chính việc trả lời những câu hỏi "ngu ngơ" đó khiến bạn tự phát hiện ra lỗ hổng logic mà bản thân không nhận ra vì đã quá quen với code.
Mẹo: Nếu bạn thấy mình giải thích code trôi chảy, không vấp váp chỗ nào — hãy nghi ngờ. Bug thường ẩn ở đúng chỗ bạn giải thích "mượt" nhất, vì đó là chỗ bạn đang dựa vào giả định chưa kiểm chứng chứ không phải sự thật đã xác minh.
Khi nào gợi ý debug của AI hữu ích, khi nào khiến bạn đi vòng vòng
Hiểu rõ giới hạn của AI khi debug quan trọng không kém việc biết cách prompt tốt. Có ba loại bug với đặc điểm rất khác nhau về việc AI có giúp được hay không.
AI hữu ích khi:
- Bug có pattern phổ biến, đã xuất hiện nhiều trong dữ liệu huấn luyện — lỗi cấu hình framework quen thuộc, off-by-one, null pointer/undefined, race condition kinh điển kiểu check-then-act, N+1 query. AI đã "thấy" hàng chục nghìn case tương tự.
- Bug cần đọc lượng lớn code/log nhanh — agentic tool có thể grep, trace call path, đối chiếu hàng trăm dòng log nhanh hơn con người rất nhiều. Đây là chỗ AI tiết kiệm thời gian rõ rệt nhất.
- Bug cần liệt kê đầy đủ khả năng — như đã nói ở phần trên, sinh danh sách giả thuyết toàn diện.
- Bug về cú pháp/API ít dùng — bạn quên tham số nào đó của một thư viện, hành vi edge case của một API cụ thể.
AI dẫn bạn đi vòng vòng khi:
- Bug phụ thuộc vào trạng thái/hành vi runtime đặc thù của hệ thống bạn — AI không thấy được số liệu Datadog thực tế, không thấy traffic pattern thật, không biết đội bạn có custom infra gì. Nếu bạn không cung cấp dữ liệu đó, AI sẽ generate ra giả thuyết "nghe hợp lý về mặt lý thuyết" nhưng sai hoàn toàn với thực tế hệ thống.
- Bug hiếm, đặc thù, ít xuất hiện trong dữ liệu huấn luyện — ví dụ tương tác lạ giữa hai thư viện phiên bản cụ thể, bug trong chính codebase nội bộ của công ty. AI có xu hướng "confabulate" — tự tin đưa ra giải thích nghe rất mạch lạc nhưng hoàn toàn bịa, vì mô hình được huấn luyện để luôn tạo câu trả lời trôi chảy chứ không phải để nói "tôi không biết".
- Khi bạn đã cho sai bằng chứng hoặc thiếu bằng chứng — garbage in, garbage out. Nếu context bạn đưa (stack trace cũ, log không đúng lần lỗi, mô tả sai điều kiện tái hiện) sai lệch, AI sẽ xây cả chuỗi suy luận trên nền sai đó, càng đi càng xa sự thật.
- Vòng lặp "sửa rồi vẫn lỗi, hỏi lại, sửa tiếp" — dấu hiệu cảnh báo rõ nhất của việc đi vòng vòng: bạn hỏi AI 3-4 lần liên tiếp, mỗi lần nó đưa một fix khác, bug vẫn còn. Đây là lúc PHẢI dừng lại, quay về bước "Observe" — thu thập thêm bằng chứng thực tế — thay vì tiếp tục hỏi AI đoán thêm lần nữa.
Dấu hiệu để nhận biết bạn đang bị dẫn đi vòng vòng: AI liên tục đề xuất fix dựa trên suy đoán ("có thể do...", "thử thêm...") mà không có bằng chứng cụ thể xác nhận trước, và mỗi fix chỉ giải quyết triệu chứng bề mặt (thêm try/catch, thêm retry, thêm null check) mà không chạm vào nguyên nhân gốc. Nếu bạn nhận thấy mình đang "thử fix và xem có hết lỗi không" hơn ba lần liên tiếp, hãy dừng, quay lại bước thu thập bằng chứng thay vì tiếp tục xin thêm gợi ý.
Mẹo: Đặt giới hạn cứng cho bản thân: tối đa 2 vòng "hỏi AI - thử fix" cho một bug. Nếu sau 2 vòng vẫn chưa ra, chuyển hẳn sang thu thập bằng chứng mới (thêm log, viết test tái hiện, dùng debugger) trước khi hỏi AI vòng thứ 3 — đừng để AI đoán trên chính những giả thuyết đã sai của nó.
Thực hành: Debug một race condition với sự hỗ trợ của AI
Hãy đi qua một tình huống thực tế, đầy đủ từ triệu chứng đến fix đã xác minh.
Bối cảnh: Team vận hành một dịch vụ đặt vé sự kiện. Từ tuần trước, support nhận được khiếu nại: một số khách hàng bị trừ tiền hai lần cho cùng một vé, hoặc hai khách khác nhau cùng nhận được vé cho cùng một chỗ ngồi. Tần suất thấp — khoảng 8-12 case/ngày trên tổng ~40,000 giao dịch — nhưng đủ nghiêm trọng để escalate thành P1.
Bước 1 — Quan sát, thu thập bằng chứng thô. Trước khi mở AI, kỹ sư phụ trách kéo log của 5 giao dịch bị lỗi gần nhất từ Datadog, lọc theo seat_id bị trùng:
2026-07-08T09:14:22.001Z [worker-3] reserve_seat(seat_id=A12, event=451) - checking availability... available
2026-07-08T09:14:22.014Z [worker-7] reserve_seat(seat_id=A12, event=451) - checking availability... available
2026-07-08T09:14:22.032Z [worker-3] reserve_seat(seat_id=A12, event=451) - marked as reserved, order_id=88213
2026-07-08T09:14:22.041Z [worker-7] reserve_seat(seat_id=A12, event=451) - marked as reserved, order_id=88214
Bằng chứng rất rõ: hai worker (worker-3 và worker-7, tức hai request xử lý song song trên hai thread/process khác nhau) cùng check "available" trong khoảng 13ms trước khi worker-3 kịp ghi trạng thái "reserved". Đây là dấu hiệu kinh điển của race condition kiểu check-then-act (TOCTOU — time-of-check to time-of-use).
Bước 2 — Đưa bằng chứng cho AI, yêu cầu giả thuyết có xếp hạng, không xin fix ngay.
We have a double-booking bug in a seat reservation service. Evidence
(logs from two concurrent workers, same seat_id, 13ms apart):
[paste the 4 log lines above]
Relevant code, reserve_seat() in booking_service.py:
[paste the actual function — roughly 30 lines: a SELECT to check
seat status, then an UPDATE to mark it reserved, no explicit locking]
This is clearly a check-then-act race condition. Given this specific
code, list the possible root causes ranked by likelihood (e.g.
missing row-level lock, wrong isolation level, missing unique
constraint, application-level cache serving stale availability data).
For each, tell me what to check in the database/config to confirm it.
AI trả về (điển hình) một danh sách như: (1) thiếu SELECT ... FOR UPDATE hoặc tương đương → không khóa hàng khi check; (2) isolation level của transaction đang là READ COMMITTED mặc định, không đủ để chặn race này; (3) thiếu unique constraint ở tầng database trên cặp (event_id, seat_id, status='reserved') — vốn là lưới an toàn cuối cùng; (4) có thể có tầng cache (Redis) trả về trạng thái "available" đã cũ.
Bước 3 — Kiểm định từng giả thuyết bằng bằng chứng thật, không đoán:
- Check code: xác nhận không có
FOR UPDATE, không có lock nào — giả thuyết (1) được củng cố. - Check DB config:
SHOW default_transaction_isolation;→read committed— giả thuyết (2) được củng cố. - Check schema:
\d seatstrên Postgres → không có unique constraint nào ràng buộc trạng thái reserved theo seat — giả thuyết (3) đúng, đây chính là lưới an toàn bị thiếu. - Check Redis: không có tầng cache nào can thiệp vào luồng này — giả thuyết (4) bị loại.
Ba giả thuyết đầu đều đúng và cộng hưởng với nhau — đây là kiểu root cause "nhiều lớp" rất thường gặp: thiếu lock ở tầng ứng dụng, VÀ thiếu ràng buộc an toàn ở tầng dữ liệu.
Bước 4 — Yêu cầu AI đề xuất fix, nhưng yêu cầu rõ phải giải quyết tận gốc, không chỉ vá triệu chứng:
Confirmed root causes:
1. No row lock during check-then-act in reserve_seat()
2. Transaction isolation is READ COMMITTED
3. No unique constraint enforcing one active reservation per seat
Propose a fix with two layers of defense:
- Application layer: use SELECT ... FOR UPDATE to lock the seat row
during the check-then-act sequence
- Database layer: add a unique constraint as a last-resort safety net
even if the application logic has a future bug
Show me the migration for the constraint and the updated
reserve_seat() function. Also tell me how to handle the case where
the UPDATE now fails due to the constraint — what should the API
return to the client?
AI đề xuất: dùng SELECT ... FOR UPDATE trong transaction để khóa hàng seat trong lúc check, kết hợp thêm một unique partial index kiểu CREATE UNIQUE INDEX ON seats (event_id, seat_id) WHERE status = 'reserved' làm lưới an toàn tầng database — nếu vì lý do gì đó (bug tương lai, deploy race, v.v.) mà tầng ứng dụng vẫn để lọt race condition, database sẽ tự chặn bằng constraint violation thay vì âm thầm cho phép double-booking.
Bước 5 — Xác minh fix bằng test tái hiện race condition, không chỉ tin lời AI:
Write a test that spins up 20 concurrent requests trying to reserve
the same seat_id, and asserts exactly 1 succeeds and 19 receive a
clear "seat no longer available" error — not a raw database
exception leaking to the client.
Chạy test này TRƯỚC khi fix để xác nhận nó tái hiện được bug (nhiều hơn 1 request thành công) — nếu test không tái hiện được bug, test đó vô giá trị. Sau đó áp fix, chạy lại, xác nhận đúng 1 request thành công. Chỉ khi có bằng chứng thực nghiệm này (không phải vì "AI nói fix đúng rồi") mới được coi là đã xác minh xong.
Bước 6 — Deploy có giám sát. Vì đây là bug production, thêm alert trên Datadog theo dõi tần suất constraint-violation error trong 48 giờ sau deploy — nếu số lượng giảm về 0 nhưng vẫn có một vài lần constraint bắt được race hiếm, đó là bằng chứng cho thấy lớp bảo vệ thứ hai (database constraint) đang hoạt động đúng như thiết kế, không phải dấu hiệu fix chưa xong.
Toàn bộ quy trình trên mất khoảng 90 phút từ lúc nhận báo cáo đến lúc deploy fix đã xác minh — nhanh hơn nhiều so với cách debug mò truyền thống, nhưng tốc độ đến từ việc kỷ luật thu thập bằng chứng trước, để AI hỗ trợ sinh giả thuyết và code, chứ không phải từ việc AI "đoán ra bug" ngay lập tức.
Mẹo: Với mọi race condition nghi ngờ, luôn viết test concurrent-request TRƯỚC khi tin rằng đã hiểu root cause. Nếu bạn không tái hiện được bug bằng test, bạn chưa thực sự hiểu nó — dù AI hay chính bạn có giải thích nghe hợp lý đến đâu.
Những điểm chính
- Debug có hệ thống là vòng lặp Observe → Hypothesize → Test → Eliminate; AI tăng tốc bước sinh giả thuyết và thiết kế thực nghiệm, nhưng không thay thế bước kiểm định bằng bằng chứng thật.
- Prompt debug tốt cần: triệu chứng nguyên văn (stack trace/log thật), điều kiện tái hiện cụ thể, code liên quan, những gì đã loại trừ, và kỳ vọng đầu ra rõ ràng.
- Ép AI liệt kê nhiều giả thuyết có xếp hạng (5-8 cái) thay vì chấp nhận câu trả lời đầu tiên — nhưng tự tái xếp hạng dựa trên kiến thức thực tế về hệ thống của bạn.
- Rubber duck debugging nâng cấp: để AI phản biện, chất vấn, hoặc đóng vai người mới hỏi câu "ngu ngơ" — thường lộ ra giả định sai mà bạn không nhận ra.
- AI hữu ích nhất với bug có pattern phổ biến hoặc cần đọc/đối chiếu lượng lớn code-log; kém hữu ích với bug đặc thù hệ thống, dữ liệu runtime riêng, hoặc khi context bạn cung cấp sai/thiếu.
- Đặt giới hạn cứng cho vòng lặp "hỏi AI - thử fix" (tối đa 2 lần) để tránh bị dẫn đi vòng vòng; nếu vượt quá, quay lại thu thập bằng chứng mới.
- Với race condition, luôn xác minh fix bằng test tái hiện được concurrency thật (nhiều request đồng thời), không chỉ tin vào giải thích logic của AI hay của chính mình.
- Với bug nghiêm trọng, cân nhắc phòng thủ nhiều lớp (ví dụ: lock ở tầng ứng dụng + constraint ở tầng database) thay vì chỉ vá một điểm duy nhất.