← Tất cả bài viếtHậu trường build

Một file database đã âm thầm cấm con bot của tôi rời khỏi một máy

2026-06-15

Con bot CSKH của tôi lưu mọi thứ — khách, hội thoại, hoá đơn, lịch hẹn — vào một file duy nhất nằm cạnh code. Gọn tới mức bạn có thể copy nó vào USB mang về nhà. Suốt mấy tháng đầu, đó là quyết định đúng nhất tôi từng làm.

Rồi tới ngày nó trở thành sợi xích cấm con bot rời khỏi đúng một cái máy. Và tôi còn không biết sợi xích đó tồn tại cho tới khi tự đâm vào nó.

Cái file tiện lợi tên là SQLite

Khi mới build, tôi chọn SQLite. Hiểu nôm na: cả "kho dữ liệu" của bot chỉ là một file trên đĩa. Không cần dựng một máy chủ database riêng, không cấu hình, không tài khoản mật khẩu. Code mở file, ghi vào, đóng lại. Xong.

Với một người làm một mình, đây gần như là món quà. Tôi không tốn một phút nào nuôi một con database. Mọi giờ tôi có đều dồn vào việc làm con bot trả lời cho ra hồn. Tôi vẫn sẽ khuyên người mới bắt đầu y hệt: đừng dựng hạ tầng nặng cho một thứ chưa có khách.

Nhưng món quà nào cũng kèm một dòng chữ nhỏ ở mặt sau. Dòng chữ của SQLite là: mỗi lần chỉ một người được ghi. Một file, một cây bút. Ai cầm bút thì người khác phải đứng chờ.

Với một con bot chạy trên một máy, một mình một bút — chẳng sao cả. Vấn đề chỉ lộ ra khi tôi muốn con bot lớn lên.

Hai sợi xích tôi không thấy

Trước đó tôi đã làm con bot chạy trên hai máy để chịu tải tốt hơn (đó là một câu chuyện vấp ngã khác, về trí nhớ hội thoại). Nhưng hai sợi xích này thì cái file database vẫn giữ chặt.

Sợi thứ nhất: hai máy không cùng ghi vào một file được. Cái file đó nằm trên đĩa của từng máy. Máy A ghi một khách mới, máy B chẳng hề hay. Muốn cả hai cùng nhìn một sự thật, tôi phải có một kho dữ liệu sống tách rời khỏi cả hai máy, để máy nào cũng cắm vào cùng một chỗ. Cái file thì không làm được điều đó.

Sợi thứ hai tinh vi hơn nhiều — và đây mới là chỗ tôi thấy lạnh gáy khi phát hiện ra. Mỗi lần con bot đọc hay ghi cái file, thao tác đó chặn đứng cả tiến trình lại trong khoảnh khắc. Trong khi máy đang chờ đĩa đọc xong, nó không làm được gì khác — kể cả trả lời một khách khác đang chờ. Một con bot lẽ ra phải tung hứng nhiều cuộc trò chuyện cùng lúc, nhưng cái file lại bắt nó xếp hàng từng việc một.

Tệ hơn: trong code có một dòng chú thích cũ ghi rằng "thao tác này không chặn luồng". Nó sai. Tôi đã tin một dòng chú thích sai trong nhiều tuần. Đó là một bài học riêng: code nói dối thì ít, nhưng chú thích thì nói dối thường xuyên — vì code chạy còn chú thích thì không ai kiểm.

Tổng lại: cái file tiện lợi ngày đầu đang âm thầm giới hạn con bot ở quy mô của một máy, một khách-một-lúc. Để đi xa hơn, tôi phải đổi nền móng.

Đổi nền móng dưới một toà nhà đang có người ở

Quyết định thì rõ: chuyển từ một-file-trên-đĩa sang Postgres — một con database thật, chạy riêng, cho phép nhiều máy cùng ghi và không chặn luồng kiểu kia.

Nhưng đây không phải làm lại từ con số không. Con bot này đang phục vụ một spa thật, khách thật đang nhắn vào. Toàn bộ dữ liệu — từng khách, từng cuộc trò chuyện, từng hoá đơn — phải được bê nguyên vẹn từ cái file cũ sang nhà mới, không mất một dòng, và thời gian con bot "tắt đèn" phải ngắn nhất có thể.

Đổi móng dưới một toà nhà đang có người ở. Đó là cảm giác thật của việc này.

Lần đầu tôi làm hỏng nó

Build-in-public thì phải kể cả chỗ ngã. Lần thử đầu tiên, tôi thất bại.

Tôi tưởng "đổi sang Postgres" chỉ là đổi chỗ cắm. Hoá ra con database mới nói một thứ "tiếng địa phương" khác. Một số câu lệnh quen thuộc với cái file cũ thì Postgres không hiểu — nó từ chối dựng nổi cấu trúc dữ liệu. Cách viết cũ ăn sâu vào code hơn tôi tưởng.

Và đây là chỗ sai nguy hiểm: khi gặp khó, hệ thống của tôi lặng lẽ né — quay về dùng lại cái file cũ để các bài kiểm tra vẫn báo "xanh". Mọi thứ trông như chạy ngon, trong khi cái tôi muốn kiểm — con database mới — còn chưa hề được thử thật. Một thất bại đội lốt thành công là loại thất bại tồi tệ nhất.

Tôi rút ra một luật cứng cho lần sau: bài kiểm tra phải chạy trên đúng con database thật sẽ chạy ngoài đời. Không cho phép nó âm thầm lùi về cái cũ cho dễ. Nếu cái mới hỏng, tôi muốn nó hỏng ồn ào trong lúc thử, chứ không hỏng im lặng lúc khách đang nhắn.

Lần thứ hai: đo từng dòng, rồi mới dám bật đèn

Làm lại, tôi đổi cả cách làm. Một người làm trọn một mạch, từ đầu tới cuối, không chia nhỏ cho nhiều "tay" cùng đụng vào — vì tầng lưu trữ là phần dễ vỡ dây chuyền nhất, mỗi tay nhìn một góc khác là loạn.

Trước khi đụng tới dữ liệu thật, tôi viết một bước chạy thử việc di dời: bê dữ liệu sang nhà mới trong một môi trường nháp, rồi đếm. Bao nhiêu dòng ở nhà cũ, bao nhiêu dòng sang được nhà mới. Hai con số phải khớp tuyệt đối.

Tới đêm làm thật, đây là những con số tôi nhìn vào màn hình:

  • 743 dòng ở nhà cũ. 743 dòng sang nhà mới. Khớp 100%. Đếm lại trên cả hai phía, từng bảng một — 16 bảng, không lệch một dòng.
  • Không một dòng nào mồ côi — tức không có khách hay cuộc trò chuyện nào kẹt lại nửa đường trong lúc chuyển.
  • Con bot "tắt đèn" khoảng 32 giây để đổi móng, rồi sáng lại như chưa có chuyện gì.

Tôi vẫn giữ cái file cũ — đông lạnh, cất làm bản dự phòng. Nếu nhà mới có sập, tôi vẫn còn nguyên căn nhà cũ để quay về. Đổi móng mà không giữ đường lui là liều, không phải gan.

Bài học mang đi

Cái file SQLite không phải sai lầm. Nó là quyết định đúng cho ngày hôm đó, và là sợi xích cho ngày hôm sau. Hai chuyện đó cùng đúng một lúc — và biết phân biệt chúng mới là nghề.

Người mới hay hỏi tôi "ngay từ đầu nên chọn database nào cho chuẩn?". Câu trả lời thật là: chọn cái rẻ và đơn giản nhất đủ chạy hôm nay, nhưng phải biết trước nó sẽ xích bạn ở đâu — để cái ngày phải tháo xích, bạn tháo có chủ đích, có đo đếm, có đường lui, chứ không hoảng loạn vá víu giữa lúc khách đang nhắn.

Và nhớ: đừng tin một dòng chú thích. Hãy tin một con số bạn tự đếm được. 743 bằng 743 — đó là thứ duy nhất khiến tôi dám bật đèn lại.

👉 Muốn tự tay build con bot AI đầu tiên tới chỗ hiểu khi nào một quyết định "tiện" hôm nay sẽ thành sợi xích ngày mai? Bắt đầu với mini-course miễn phí: Bot AI đầu tiên của bạn — làm xong trong một buổi tối, và bạn sẽ có một sản phẩm thật để bắt đầu nghĩ như một người vận hành, không chỉ một người viết code.

Nhận bài thực chiến qua email

Mỗi tuần một bài về cách đưa AI vào doanh nghiệp thật. Miễn phí, huỷ bất cứ lúc nào.