Build trên Cloudflare. Những quyết định không ai thấy. MXCrew, Phần 2.

By Lâm 10.11.26
Build trên Cloudflare. Những quyết định không ai thấy. MXCrew, Phần 2.

Khi bạn mở một hộp thư, bạn thấy gì? Một danh sách email, vài nút bấm, một ô tìm kiếm. Đơn giản đến mức vô hình.

Phần 1 của loạt này mình đã kể vì sao một người làm web đi xây email. Hôm nay, Phần 2, mình kể về phần việc mà không người dùng nào của MXCrew sẽ bao giờ nhìn thấy, nhưng chính là phần quyết định họ có còn tin sản phẩm vào một buổi sáng nào đó hay không: những quyết định hạ tầng.

Bởi vì email là một trong số ít sản phẩm mà thành công được định nghĩa bằng sự vô hình. Không ai gửi thư khen "hôm nay hộp thư của bạn chạy mượt quá". Người ta chỉ nhớ đến bạn khi thư không đến, hoặc tệ hơn, đến nhầm chỗ.

48 tờ giấy trước một dòng code

Trước hết, một con số. Dự án MXCrew, tính đến hôm nay, có 48 quyết định kiến trúc lớn được ghi thành văn bản, theo dạng tài liệu mà giới kỹ thuật gọi là ADR, Architecture Decision Record. Mỗi tờ ghi một quyết định, bối cảnh sinh ra nó, các phương án đã cân nhắc, và cái giá phải trả của lựa chọn cuối.

Con số 48 nằm trong repo của dự án, bạn có thể đếm như đếm trang sổ. Nhưng điều đáng kể không phải con số. Là thói quen đứng sau nó: trước mỗi quyết định lớn, dừng lại, viết ra các lựa chọn, rồi mới chọn. Một số tờ viết trong nửa giờ. Một số tờ, như bạn sẽ đọc dưới đây, sinh ra từ một đêm production gãy.

Với mình, đó là cách dịch chữ "trust by design" sang ngôn ngữ hạ tầng. Niềm tin không phải lời hứa ở trang landing. Niềm tin là tập hợp những quyết định mà người dùng không bao giờ biết đến, được đưa ra như thể có ai sẽ kiểm tra từng cái.

Invisible stack: phần người dùng thấy mỏng so với phần không ai thấy bên dưới

Đêm bộ test nói dối mình

Câu chuyện đầu tiên, và mình kể nó đầu tiên vì nó xé toạc sự tự tin của mình về phần mềm mình viết.

Dự án dùng D1, hệ cơ sở dữ liệu của Cloudflare, làm nơi lưu toàn bộ thư. Ở đâu có cơ sở dữ liệu, ở đó có khái niệm giao dịch: hoặc cả nhóm thao tác thành công, hoặc không gì được ghi, để dữ liệu không nằm lửng lơ nửa vời. Code mình viết dùng đúng chuẩn đó. Bộ test chạy, cả 464 ca cùng xanh. Mình build, mình deploy.

Rồi production nổ ra một cách im lặng đáng sợ: thư đến vẫn được lưu, nhưng một phần dữ liệu đi kèm, phần ghi nhận thư đó thuộc hộp nào, nằm trong giao dịch, không bao giờ được ghi xuống. Nguyên nhân được tìm ra và ghi thành quyết định số 9 của dự án: hệ cơ sở dữ liệu đó, ở môi trường chạy thật, không hỗ trợ kiểu giao dịch tương tác mà code đang gọi. Mỗi lần chạy đến đó là một lần trượt ngã, không tiếng động. Cái khiến mình càng lạnh gáy hơn: môi trường test giả lập được giao dịch, nên 464 ca test cứ xanh rờm trong khi production gãy thật.

"Bộ test đã nói dối mình. Không phải vì test viết sai, mà vì thế giới giả lập đẹp hơn thế giới thật."

Kể từ đó, dự án bỏ hẳn kiểu giao dịch tương tác, chuyển sang cách gom thao tác thành từng lô, hoặc là cả lô được ghi, hoặc là không gì được ghi. Giá phải trả là viết lại không ít chỗ code. Cái mua được là một lời đảm bảo: dữ liệu thư không bao giờ nằm lửng nữa.

Đêm bộ test nói dối: môi trường mock 464 test xanh nhưng production gãy trong im lặng

Không dựng kho thư thứ hai

Quyết định lớn thứ hai nằm ở chỗ ít ai ngờ: MXCrew không tự dựng toàn bộ máy chủ thư.

Email, ở tầng protocol, là một cỗ máy đã vận hành hàng chục năm: IMAP để nhận, SMTP để gửi. Cách dễ nhất là dựng một bộ máy thư truyền thống, tự quản. Cách MXCrew chọn, ghi ở quyết định số 2: phần nhận và gửi protocol chạy trên một chương trình nhỏ gọn, không lưu trữ gì lâu dài; còn nguồn sự thật về mọi lá thư nằm trọn trong hạ tầng Cloudflare, nơi cả ứng dụng đang sống.

Nghe kỹ thuật, nhưng nguyên lý của nó ai cũng hiểu: đừng giữ hai bản chép của một sự thật. Khi có hai nơi cùng lưu một thứ, sớm muộn cũng đến ngày hai bản chép cãi nhau, và người trả giá là người dùng, bằng một lá thư hiện diện ở nơi này mà biến mất ở nơi kia. Cả dự án tự ràng buộc: chỉ một nguồn sự thật. Mọi thứ khác chỉ là cửa sổ nhìn vào nó.

Quyết định nói "không" bằng chính luật chơi

Hai câu chuyện tiếp theo không phải về kỹ thuật. Là về giá trị.

Khi có thư bị hệ thống nghi ngờ và cách ly, ai được xem nó để quyết trả về hay xóa? Quyết định số 42 chốt: người quản lý được xem phong bì và tiêu đề thư, không bao giờ được xem nội dung. Một ngoại lệ có tên, có giới hạn, cho một tình huống cụ thể. Còn lại, nội dung thư của người này không ai được đọc, kể cả người quản trị hệ thống.

Khi một doanh nghiệp hết hạn gói dịch vụ, chuyện gì xảy ra với thư của họ? Quyết định số 43 chốt điều mà mình coi là đạo đức của cả sản phẩm: hết tiền thì ngừng gửi đi, nhưng không bao giờ ngừng nhận vào. Thư đến vẫn được lưu, dữ liệu vẫn có thể xuất ra. Vì mất thư đến là hậu quả tồi tệ nhất một sản phẩm email có thể gây cho một doanh nghiệp: bạn không biết mình đã bỏ lỡ ai.

Và khi đến lượt AI bước vào sản phẩm, trước khi viết dòng code AI đầu tiên, dự án chốt nguyên tắc ở quyết định số 21, ngắn đến mức bạn có thể đọc thành một câu thoại: AI đề xuất, người chốt. Không gì do AI sinh ra được gửi thư, xóa thư, hay gọi ra thế giới bên ngoài nếu không có một con người bấm duyệt. Trong một thị trường đang bán "AI làm hộ mọi thứ", đó là một lời từ chối có chủ đích.

Năm quyết định, một bản chất chung: mỗi tờ giấy là một câu "không" nói trước cho người dùng, một luật chơi ràng buộc chính người viết sản phẩm khi áp lực xảy ra chuyện.

Luật chơi: ba quyết định nói không ghi thành ADR-21, ADR-42, ADR-43

Ba giờ sáng của người dùng bạn

Có một cách để kết thúc bài này, mình nghĩ nó đúng hơn mọi kết luận.

Sẽ có một buổi sáng nào đó, người dùng của MXCrew mở điện thoại và nhận ra một thư quan trọng đã đến đúng chỗ, không mất, không trễ, không rơi vào hòm rác. Họ sẽ không biết rằng thư đó tồn tại nhờ một đêm mình mò nguyên nhân bộ test nói dối. Nhờ một quyết định cấm lưu hai bản chép của sự thật. Nhờ một luật viết rằng nội dung thư không ai được xem, và một luật viết rằng mất tiền không được dẫn đến mất thư.

Họ sẽ không biết. Và đó chính là điểm. Sản phẩm hạ tầng làm đúng nghĩa là sản phẩm mà người dùng không bao giờ phải nghĩ về nó. Ba giờ sáng của họ được dành cho việc khác, còn ba giờ sáng của người làm sản phẩm là để đảm bảo điều đó.

Bài tiếp theo, Phần 3, mình sẽ mở sổ sách ra: kết quả thật của 80 ngày build, những con số kiểm chứng được, và những gì không hoạt động, kể cả chuyện chọn nhầm đối tác thanh toán và phải đổi giữa đường.

Decisions by craft. Proof by shipping.