Chương 86 — Hộp thư thứ hai
Tiếng Minh gõ phím vọng từ bàn góc, đều và dứt khoát. Hoàng đã nhận ra cách Minh gõ khác mình — mình gõ theo cụm, ngắt nghỉ giữa từng ý, còn Minh gõ như chảy, hàng loạt ký tự trút ra không có khoảng dừng. Đó là cách gõ của người đang viết thứ đã nghĩ xong từ trước.
Mấy ngày sau cuộc họp stack, văn phòng Tô Hiến Thành đã bắt đầu có nhịp. Minh ngồi góc trong, headphones lớn phủ tai, màn hình luôn mở hai cửa sổ: bên trái là repo Node.js mới, bên phải là documentation. Trâm thường đến sau giờ học, kéo ghế ngồi cạnh Khoa ở bàn ngoài, gọi điện cho khách và ghi sổ. Phương Anh không luôn luôn ở — cô đến hai buổi một tuần, mỗi lần ngồi ba tiếng liền với tài liệu pháp lý, không nói nhiều. Anh Tuấn thỉnh thoảng ghé, không lịch sự gọi trước, ngồi năm phút hỏi tiến độ rồi đi.
Hoàng ngồi ở bàn giữa. Laptop mở sẵn, dashboard NỢ SỔ ở góc màn hình bên phải, email công ty chiếm phần còn lại. Việc kiểm tra email là thói quen buổi sáng — anh mở nó như người mở cửa văn phòng: kiểm tra xem đêm qua có gì vào không, có khách nào báo lỗi không, có gì cần xử lý gấp không.
Hộp thư hôm nay không đông. Mấy email từ aggregator thanh toán, một tin nhắn tự động từ server monitoring báo uptime 99.8%, một email từ Khoa gửi Trâm cc anh về danh sách khách cần gọi lại. Anh lướt qua từng dòng, xóa vài email rác, đánh dấu một email cần trả lời.
Rồi anh thấy nó.
Thread nằm thứ năm từ trên xuống, không nổi bật. Subject line: Re: Event-driven architecture considerations for debt sync module. Người gửi: Raj Krishnan. Người nhận: Trịnh Nguyễn Minh. CC: hello@nosos.vn.
Hoàng nhìn dòng CC đó. Hộp thư công ty chung. Không phải email riêng. Minh không giấu — anh cc vào email công ty. Nhưng Hoàng cũng không nhớ Minh báo có trao đổi kỹ thuật với Raj ngoài cuộc đàm phán ở Singapore.
Anh mở thread.
Năm email, trải dài gần hai tuần. Cái đầu tiên từ Raj, gửi tám ngày trước:
“Minh, following up on our discussion in Singapore — I’ve been thinking about the debt sync challenge you mentioned. The issue isn’t just about offline queuing, it’s about how you handle event ordering when multiple clients write concurrently. Have you considered an event-sourcing approach? Store events, not state. Rebuild state from event log when needed.”
Minh trả lời sau một ngày:
“Raj, yes — I’ve been sketching this. The current PHP monolith stores state directly. Every write overwrites the previous record. There’s no history, no replay capability. If we move to event-driven, we can: 1) append events instead of overwrite, 2) rebuild state by replaying the log, 3) add new consumers (notifications, audit, reporting) without touching the core write path. Attaching a quick diagram.”
Có một link file đính kèm. Hoàng click. Mở ra — sơ đồ vẽ tay, chụp ảnh, hơi nghiêng. Minh vẽ trên giấy kẻ ô, bút xanh. Hình cho thấy một hàng event được append vào log theo thứ tự thời gian, bên trên có các consumer đọc từ log và xử lý độc lập. Chữ ghi tay: append-only event log → consumers replay. Góc dưới có một ghi chú nhỏ, ghi vội: Check CQRS — separate read/write models?
Hoàng nhìn ghi chú đó. CQRS — Command Query Responsibility Segregation. Anh biết pattern này. Anh cũng biết Raj không gợi ý điều đó cho người mới — đó là kiến trúc nâng cao, đòi hỏi kinh nghiệm thực chiến về hệ thống phân tán.
Anh đọc tiếp.
Raj trả lời sau hai ngày, email dài hơn:
“Good thinking on event sourcing. A few things to consider: 1) Event schema versioning — your events will outlive your code. Plan for backward compatibility from day one. 2) Idempotency — consumers must handle duplicate events gracefully, especially in unreliable networks (which you mentioned about Vietnam 3G). 3) Snapshotting — replaying months of events is slow. Take periodic snapshots of aggregate state and replay from the latest snapshot. I’d recommend looking at how Kafka handles log compaction.”
Minh trả lời ngay trong ngày:
“Raj, this is exactly what I needed. The 3G reliability issue is real — we have merchants losing connection mid-transaction, then retrying and creating duplicate records. Event sourcing with idempotent consumers would solve this at the architecture level instead of patching in PHP. I’m prototyping this in the new Node.js service. Will share when I have something runnable.”
Raj:
“Sounds good. One more thing — be careful about mixing event-driven and request-response in the same service boundary. It gets messy fast. Better to have clean separation: the new event-driven service handles sync, the existing system continues as-is, and you bridge them with a simple adapter. Don’t try to refactor the old system into event-driven. That’s a trap.”
Minh:
“Agreed. The old PHP code stays as-is. I’m building the new service clean from scratch with event-driven core. The adapter will translate between old state and new events during the transition period.”
Thread kết thúc ở đó. Email cuối từ Minh, ba ngày trước.
Hoàng ngồi nhìn màn hình.
Năm email. Hai tuần. Raj không hỏi thăm — anh gợi ý kiến trúc cụ thể, chia sẻ kinh nghiệm thực chiến về event versioning, idempotency, snapshotting, Kafka log compaction. Minh không báo cáo — anh vẽ diagram, đặt câu hỏi kỹ thuật sâu, đề cập vấn đề 3G và duplicate records mà chưa từng nói với Hoàng.
Hoàng nhớ lại. Khi Minh về từ Singapore, anh nói: “Raj hỏi về architecture, em trả lời.” Một câu. Không đề cập event sourcing, không đề cập CQRS, không đề cập rằng Raj đang hướng kiến trúc mới theo một hướng mà Minh chưa chính thức trình bày với team.
Anh nhìn lại subject line: Re: Event-driven architecture considerations for debt sync module.
“Considerations.” Từ đó nghe nhẹ. Nhưng nội dung năm email không nhẹ. Đó là một cuộc bàn luận kiến trúc nghiêm túc giữa hai người hiểu sâu, đi vào từng chi tiết implementation — schema versioning, idempotency, log compaction — những thứ vượt xa “hỏi architecture.”
Hoàng kéo chuột lên đầu thread, nhìn ngày tháng. Email đầu tiên từ Raj gửi tám ngày trước. Ngày đó, Minh vừa bắt đầu branch Node.js. Ngày đó, Hoàng còn nghĩ cuộc tranh luận stack đã chốt — Node cho phần mới, PHP cho phần cũ, song song, có tiêu chí.
Anh không biết “phần mới” mà Minh đang viết đã được Raj thiết kế theo event-driven từ gốc.
Anh không biết “phần cũ” mà Hoàng giữ — PHP monolith — sẽ trở thành adapter trong kiến trúc Raj vẽ ra.
Anh cũng không biết Minh đã vẽ diagram gửi Raj, và Raj đã gật đầu.
Hoàng tạm rời màn hình, nhìn ra cửa sổ. Đường Tô Hiến Thành trưa nay ít xe, nắng gắt trên mặt đường nhựa. Bóng người đi bộ xiên qua vỉa hè, đầu đội nón lá, tay xách túi. Bên góc, Minh vẫn gõ phím. Tai bịt bởi headphones. Không biết anh đang viết cái gì — có thể đang implement chính event sourcing mà Raj hướng dẫn.
Câu hỏi đầu tiên trong đầu Hoàng không phải “Minh giấu mình.” Minh cc vào email công ty. Anh không giấu. Câu hỏi đầu tiên là: tại sao Minh không nói?
Anh cân nhắc. Có thể Minh thấy đây là chi tiết kỹ thuật, không cần báo CEO. Có thể Minh nghĩ cuộc đàm phán stack đã chốt, phần implementation thuộc về anh. Có thể Minh đúng — Hoàng cũng không muốn Minh báo từng email gửi cố vấn kỹ thuật của quỹ.
Nhưng Raj không chỉ là cố vấn kỹ thuật. Raj đại diện quỹ đầu tư. Raj có quyền vote trong board meeting. Raj đọc codebase NỢ SỔ, hiểu điểm mạnh điểm yếu, và đang hướng kiến trúc theo ý mình — qua Minh, không qua Hoàng.
Hoàng nghĩ đến câu hỏi mình sẽ hỏi nếu mở lời. “Minh, mày trao đổi với Raj về kiến trúc rồi hả?” — câu đó nghe rất bình thường. Rất CEO hỏi nhân viên. Nhưng Minh sẽ hiểu câu hỏi đó nghĩa là gì. Nghĩa là: tao thấy mày nói chuyện riêng với người của quỹ mà không báo tao. Và từ đó, mỗi lần Minh email Raj, anh sẽ nghĩ: Hoàng đang xem.
Hoàng không muốn điều đó. Anh vừa mới cho Minh quyền viết branch mới, vừa mới nói “từ nay phần mới là của mày.” Nếu hôm sau anh đã hỏi “mày nói chuyện với ai trong phần đó” — thì quyền trao buổi hôm qua còn giá trị gì?
Nhưng nếu anh im.
Anh nhìn lại thread, đọc dòng Raj viết: The old PHP code stays as-is. Don’t try to refactor the old system into event-driven. That’s a trap.
Raj gọi code của Hoàng là trap.
Không. Raj gọi việc refactor code cũ thành event-driven là trap. Đó là lời khuyên kỹ thuật hợp lý. Hoàng đọc nó bằng con mắt kỹ sư và thấy Raj đúng — mixing event-driven với request-response trong cùng service boundary là sai lầm phổ biến. Nhưng anh cũng đọc nó bằng con mắt CEO và thấy: Raj đang định nghĩa ranh giới giữa code cũ và code mới. Raj đang vẽ đường — bên này của Hoàng, bên kia của Minh.
Và Minh đang theo đường đó.
Tiếng ghế kéo. Khoa đứng dậy từ bàn ngoài, đi ngang qua Hoàng trên đường ra cửa. Anh dừng lại, tay cầm điện thoại, liếc sang màn hình Hoàng — chỉ kịp thấy hộp thư trước khi Hoàng chuyển tab.
“Sao mặt mày?” Khoa hỏi.
Hoàng nhìn lên. Khoa đứng dựa tường, áo thun xám cũ, tay cầm điện thoại đang mở danh bạ — sắp gọi khách.
“Không có gì,” Hoàng nói.
Khoa nhìn anh nửa giây. Ánh mắt đó Hoàng quen — Khoa không tin, nhưng không ép. Anh biết Hoàng có những thứ không nói. Lâu rồi Khoa không hỏi thêm khi Hoàng trả lời “không có gì.” Đó là thỏa hiệp ngầm giữa hai người: Khoa không ép, Hoàng tự biết khi nào cần nói.
Nhưng thỏa hiệp đó có giới hạn. Khoa hỏi “sao mặt mày” nghĩa là anh đã thấy. Anh không hỏi thêm không phải vì không quan tâm. Vì hỏi thêm sẽ chạm vào vùng Hoàng sẽ nói “tao tự xử” — và Khoa biết vùng đó mỗi lần rộng thêm một chút.
“Đi gặp chị Bảy à?” Hoàng hỏi, chuyển chủ đề.
“Ừ,” Khoa nói. “Lần này dẫn Trâm đi một mình.”
“Lần đầu?”
“Lần đầu.” Khoa gật. “Em bảo em tự được. Tao đứng ngoài nhìn.”
Khoa đi ra cửa. Tiếng bước chân lan ra hành lang, xa dần. Hoàng nhìn theo cánh cửa đóng lại.
Anh quay về màn hình.
Thread email vẫn mở. Năm email, xếp gọn. Hoàng đọc lại lần thứ ba. Lần này anh đọc bằng con mắt khác — không phải tìm xem Minh giấu gì, mà tìm xem Minh không nói gì.
Minh không nói với Raj về rủi ro khách hàng. Không đề cập chị Bảy, không đề cập Trâm, không đề cập việc khách quen ghi nợ bằng biệt danh. Minh nói với Raj về duplicate records, về 3G, về idempotency — nhưng không nói về con người dùng app. Raj thấy kiến trúc. Raj không thấy tiệm.
Điều đó khiến Hoàng thấy nhẹ hơn một chút. Minh chưa bị Raj cuốn đến mức quên khách hàng. Anh vẫn đang xây sản phẩm cho tiệm nhỏ. Chỉ là anh đang xây nó theo cách mà Hoàng không tham gia vào quyết định kiến trúc.
Và đó chính là điều Hoàng đã đồng ý.
Anh nhớ lại câu của mình: “Phần nào ảnh hưởng tương lai, thì em.” Anh nói câu đó. Anh cho phép Minh quyết định kiến trúc phần mới. Và Minh đang quyết định — với Raj, không với Hoàng.
Nhưng Raj là người của quỹ. Minh nói chuyện với người của quỹ về kiến trúc sản phẩm mà Hoàng là CEO. Dù cc email công ty, dù nội dung không bí mật, dù Raj khuyên đúng — kênh đó nằm ngoài tổ chức. Nó không qua review. Không qua họp. Không qua Phương Anh. Nó là hai người nói chuyện chuyên môn, sâu, đều đặn, và không ai trong công ty biết nó sâu đến đâu.
Trừ Hoàng. Và Hoàng vừa quyết định không hỏi.
Anh đóng email. Tay đặt lên touchpad, ngón giữa chạm nhẹ, tắt tab. Màn hình chỉ còn dashboard NỢ SỔ — dải xanh quen thuộc, số người dùng nhấp nháy, server uptime 99.8%. Tất cả bình thường. Không có gì thay đổi.
Nhưng có thứ đã thay đổi. Nó thay đổi từ tám ngày trước, khi Raj gửi email đầu tiên, và Hoàng không biết. Tám ngày kiến trúc mới đã được bàn bạc, vẽ diagram, định hướng — mà Hoàng, người sáng lập, người viết dòng code đầu tiên, người CEO công khai, chỉ mới đọc hôm nay.
Rồi anh mở Hệ thống.
Giao diện quen thuộc hiện ra. Độ bền tổ chức Lv.2. Thanh không đổi. Khu vực cảnh báo, nơi thường trống hoặc chỉ có những dòng nhắc nhỏ, hôm nay có một dòng mới. Chữ trắng trên nền đỏ nhạt.
KÊNH THÔNG TIN NGOÀI TỔ CHỨC — CẤP ĐỘ: CAO
Hoàng nhìn dòng chữ đó. Cấp độ CAO. Lần trước ở Singapore, cảnh báo tương tự chỉ ghi “đang tăng.” Bây giờ nó leo lên CAO. Hệ thống không giải thích thêm. Không gợi ý. Không cho câu hỏi mẫu. Nó chỉ đặt dòng chữ đỏ ở đó và chờ.
Anh nhìn xuống chỉ số Độ bền tổ chức. Lv.2. Không giảm. Không tăng. Hệ thống ghi nhận kênh ngoài tổ chức đang sâu, nhưng không phạt — vì Hoàng chưa làm gì sai. Anh đọc email công ty, không đọc email riêng. Minh cc, không giấu. Không có hành vi nào đáng trừ điểm.
Nhưng dòng đỏ ở đó.
Hoàng tắt Hệ thống. Anh không chia sẻ cảnh báo này với ai — giống như anh không chia sẻ cảnh báo đầu tiên ở Singapore. Lúc đó anh cũng tắt, cũng im. Lúc đó anh nghĩ: có thể mình đang quá muốn kiểm soát.
Bây giờ anh nghĩ: có thể mình đang quá sợ mất kiểm soát.
Hai câu đó khác nhau. Nhưng kết quả giống nhau: anh không hỏi.
Bên góc, Minh kéo headphone ra một bên tai, ngáp, rồi kéo lại. Màn hình anh vẫn sáng — code Node.js chạy dọc, có thể là event sourcing module. Hoàng nhìn tấm lưng Minh, chiếc áo sơ mi nhăn, gáy hơi gù vì cúi. Minh không biết Hoàng vừa đọc năm email của anh với Raj. Minh không biết Hệ thống vừa chuyển cảnh báo lên CAO. Minh đang viết code, và code đó đang đi theo hướng Raj vẽ, không theo hướng Hoàng nào cả.
Hoàng nhớ ở Singapore. Tầng 28. Kính một chiều. Minh và Raj đứng hành lang, nói chuyện. Hoàng nhìn qua kính, không nghe được. Body language của hai người — nghiêng người vào nhau, gật đầu, cười nhẹ. Chuyên môn. Tự nhiên. Không bí mật.
Lần đó anh không hỏi.
Bây giờ kênh sâu hơn. Không phải hành lang, không phải body language qua kính. Là năm email. Là diagram vẽ tay. Là CQRS, event sourcing, Kafka log compaction — kiến trúc cụ thể, implementation-level, đang định hình codebase mà Hoàng là CEO.
Vẫn chưa hỏi.
Anh đứng dậy, đi pha cà phê. Máy pha cũ ở góc tủ, bình nước còn một nửa. Anh đổ bột vào phễu lọc, nước sôi rót chậm, mùi cà phê bốc lên cay và quen. Tiếng nước chảy qua lọc đều đặn, lọt vào ly đá kêu lách cách.
Khi cà phê xong, anh cầm ly về bàn. Qua góc, Minh vẫn gõ. Hoàng ngồi xuống, đặt ly, mở lại email.
Thread vẫn ở đó. Năm email. Sắp xếp gọn.
Anh nhìn nó, rồi nhìn về phía Minh. Rồi nhìn lại.
Anh có thể đi qua, kéo ghế ngồi cạnh, hỏi: “Minh, mày đang viết event sourcing à? Cho tao xem.” Đó là câu hỏi của người đồng nghiệp kỹ thuật. Đó là câu hỏi mà Minh sẽ vui trả lời — vì Minh muốn người hỏi. Minh muốn người đủ giỏi để hiểu diagram anh vẽ, đủ sâu để tranh luận CQRS với anh. Và Hoàng là người đó. Anh hiểu event sourcing. Anh biết CQRS là gì.
Nhưng câu hỏi tiếp theo sẽ là: “Mày bàn với ai về hướng này?”
Và Minh sẽ biết Hoàng đã đọc email. Và từ đó, mỗi khi Minh nhận email từ Raj, anh sẽ nghĩ: Hoàng đang theo dõi.
Hoàng uống cà phê. Nó đã loãng vì đá tan. Vị nhạt, nhưng mùi vẫn còn.
Anh không đi qua.
Anh đóng laptop lại, đứng dậy, lấy chìa khoá xe.
“Ra ngoài chút,” anh nói, đủ to để Minh nghe.
Minh kéo headphone ra.
“Hả?”
“Ra ngoài chút. Có gì gọi tao.”
Minh gật, kéo headphone lại, tiếp tục gõ.
Hoàng mở cửa văn phòng, bước ra hành lang. Cửa đóng sau lưng, tiếng khóa kêu nhẹ. Bên ngoài, cầu thang tối, bóng đèn huỳnh quang nhấp nháy. Anh đi xuống, mỗi bước vang trên mặt gạch lạnh.
Trên xe máy, gió chiều thổi qua mặt. Anh chạy không định hướng — qua ngã tư, rẽ trái, chạy thêm hai khúc, đậu lại bên vệ đường. Tắt máy. Ngồi.
Anh nghĩ về Singapore. Kính một chiều. Minh và Raj. Lần đó cảnh báo mới là “đang tăng.”
Anh nghĩ về hôm nay. Năm email. Diagram. CQRS. Cảnh báo “CAO.”
Mỗi lần anh không hỏi, kênh sâu thêm. Lần đầu là hành lang. Lần hai là email. Lần ba sẽ là gì?
Hoàng không biết. Anh chỉ biết: lần nào anh cũng nghĩ “chưa phải lúc.” Lần nào anh cũng tìm được lý do để im. Và kênh thì luôn sâu hơn sau lần im đó.
Anh mở điện thoại. Mở Hệ thống. Dòng đỏ vẫn ở đó:
KÊNH THÔNG TIN NGOÀI TỔ CHỨC — CẤP ĐỘ: CAO
Hoàng đọc nó lần nữa. Rồi tắt màn hình, nhét điện thoại vào túi.
Chiều Sài Gòn đang nhạt dần. Nắng xiên qua tòa nhà đối diện, đổ bóng dài xuống mặt đường. Xe máy chạy ngang, tiếng bíp bíp của xe tải nhỏ nhường đường. Mùi cơm trưa từ quán ven đường — cá kho, rau luộc, canh chua — bay qua mũi anh rồi mất.
Anh nổ máy, quay đầu xe về phía văn phòng.
Khi anh mở cửa bước vào, Minh vẫn ngồi góc, gõ phím không ngừng. Màn hình vẫn sáng. Trâm đã đến, đang gọi điện ở bàn ngoài, giọng nhỏ nhẹ: “Dạ, chị Bảy hả? Em Trâm đây…” Khoa chưa về.
Hoàng ngồi xuống bàn. Mở laptop. Dashboard NỢ SỔ quen thuộc. Email công ty — thread Minh–Raj vẫn nằm đó, thứ năm từ trên xuống, không nổi bật.
Anh nhìn nó. Không mở.
Trong đầu anh, một câu hỏi lặp lại, không phải câu hỏi mới — anh đã hỏi nó từ Singapore, từ lần đầu nhìn qua kính:
Minh đang nói chuyện với người của quỹ. Người của quỹ đang vẽ kiến trúc. Kiến trúc đó đang trở thành code. Code đó sẽ chạy sản phẩm mà tao là CEO. Tao có nên lo không?
Câu trả lời đầu tiên: Không. Minh giỏi. Raj khuyên đúng. Event sourcing là hướng tốt.
Câu trả lời thứ hai: Nhưng tao không biết. Tao đọc hôm nay. Nó bắt đầu tám ngày trước. Tám ngày tao không biết kiến trúc sản phẩm mình đang đi về đâu.
Câu trả lời thứ ba, câu mà anh không muốn nghĩ tới: Nếu tao hỏi, Minh sẽ thấy tao giám sát. Nếu tao không hỏi, kênh sâu thêm. Lựa chọn nào cũng sai. Vậy lựa chọn nào ít sai hơn?
Hoàng không có câu trả lời.
Anh tắt email, mở codebase PHP cũ — phần mà Minh gọi là trap, mà Raj gọi là “old system,” mà anh gọi là 18 tháng thức khuya. Dòng code quen thuộc hiện ra, con trỏ nhấp nháy trên function ghi nợ mà anh viết đêm đầu tiên. Anh nhìn nó. Mùi ký ức trào lên — bàn học nhà Bình Thạnh, ba ngáy phòng bên, tiếng quạt trần rè rè, mùi dầu gió xanh từ phòng mẹ.
Code đó đang chạy. Đang ghi nợ cho chị Bảy, cho chị Ba Muối, cho hơn tám trăm khách hàng mà không ai trong số họ biết hoặc quan tâm nó viết bằng PHP hay Node.js. Họ chỉ cần sáng mở lên, số nợ vẫn còn.
Hoàng đặt tay lên bàn phím, ngón tay chạm phím quen thuộc.
Anh chưa gõ gì.
Bên góc, Minh tắt headphones, ngáp dài, vươn vai. Lưng kêu lộc cộc. Anh quay lại nhìn Hoàng.
“Anh về chưa?” Minh hỏi.
“Chưa.”
“Em xong module đầu tiên,” Minh nói. “Event log. Test trên staging rồi. Chạy tốt.”
Hoàng nhìn anh. Module đầu tiên. Event log. Test trên staging. Chạy tốt.
“Cho tao xem,” anh nói.
Minh gật, kéo ghế qua. Anh mở màn hình, chỉ vào code mới — TypeScript, sạch, comment đầy đủ. Function ghi event log, validate schema, append vào log file. Minh giải thích nhanh: mỗi transaction tạo một event, event đó được append vào log, consumer đọc log và cập nhật state.
Hoàng nhìn code. Sạch. Đúng logic. Anh có thể review được.
Nhưng anh cũng thấy: kiến trúc này không phải của Minh. Nó là của Raj. Mỗi function, mỗi comment, mỗi decision đều mang dấu của cuộc bàn luận trong năm email — event sourcing, idempotency, schema versioning. Minh viết code, nhưng hình dáng của code do hai người quyết định.
Hoàng không nói điều đó. Anh chỉ gật.
“Tốt,” anh nói. “Nhưng chưa deploy production.”
“Em biết,” Minh nói. “Staging. Chưa đụng data thật.”
“Có quy trình review chưa?”
“Chưa.” Minh nhìn anh. “Anh muốn quy trình nào?”
Hoàng nhìn lại code trên màn hình. Rồi nhìn Minh.
“Sẽ có,” anh nói. “Tao đang nghĩ.”
Minh gật, kéo ghế về bàn mình, đeo headphone lại.
Hoàng ngồi lại trước màn hình Minh vừa mở. Code Node.js vẫn hiện trên đó — sạch, gọn, đúng. Anh nhìn nó lâu hơn cần thiết. Không phải vì không hiểu. Anh hiểu. Anh hiểu từng dòng.
Nhưng anh không hiểu tại sao mình không hỏi.
Anh tắt màn hình Minh, mở lại màn hình mình. Dashboard NỢ SỔ. Dải xanh. Số người dùng. Uptime 99.8%.
Bình thường.
Tất cả bình thường.
Anh mở Hệ thống. Dòng đỏ vẫn nhấp nháy ở góc:
KÊNH THÔNG TIN NGOÀI TỔ CHỨC — CẤP ĐỘ: CAO
Hoàng nhìn nó. Anh nhớ lần đầu tiên thấy dòng tương tự ở Singapore — “đang tăng.” Lần đó anh nghĩ: có thể mình đang quá muốn kiểm soát. Lần đó anh tắt đi.
Bây giờ anh nghĩ: mỗi lần không hỏi, nó sâu thêm. Email tiếp theo từ Raj sẽ đến — tuần sau, hay tuần sau nữa — và Minh sẽ trả lời, và diagram sẽ chi tiết hơn, và kiến trúc sẽ rõ hơn, và Hoàng sẽ lại ngồi đọc nó qua CC trên hộp thư chung, và lại không hỏi.
Anh tắt Hệ thống.
Trâm đặt điện thoại xuống, quay sang Khoa — vừa về, mồ hôi lấm tấm trán.
“Chị Bảy bảo app chạy tốt,” Trâm nói, giọng hơi proud. “Bà kêu lần này in báo cáo nhanh hơn hồi trước.”
Khoa cười, lau trán bằng tay.
“Good,” anh nói. “Cứ giữ bà vui. Bà mà vui là cả hẻm theo.”
Hoàng nghe câu đó. Cả hẻm theo. Chị Bảy vui, cả hẻm theo. Đó là cách NỢ SỔ lớn lên — không qua kiến trúc, không qua event sourcing, không qua CQRS. Qua chị Bảy gọi, cả hẻm nghe, một tiệm giới thiệu một tiệm.
Code thì chạy.
Kiến trúc thì đổi.
Nhưng khách vẫn ghi nợ bằng tên thánh, vẫn tìm theo biệt danh, vẫn gọi Trâm khi app chậm.
Hoàng đứng dậy. Bên ngoài trời đã tối hẳn — đèn đường vàng hắt qua cửa sổ, lọt vào sàn văn phòng. Minh vẫn ngồi góc, gõ tiếp. Trâm thu dọn sổ, chuẩn bị về. Khoa mở tủ lạnh lấy nước, rót hai ly — một ly để cạnh Hoàng.
“Uống đi,” Khoa nói. “Mặt mày xanh lè.”
Hoàng cầm ly, uống. Nước lạnh chảy xuống cổ, rõ ràng.
“Cảm ơn,” anh nói.
Khoa nhìn anh, rồi nhìn màn hình Hoàng — chỉ thấy dashboard xanh, không thấy gì khác.
“Có gì nói tao,” Khoa nói, giọng nhẹ nhưng không phải xã giao.
Hoàng gật.
Khoa đi về bàn, ngồi, mở điện thoại gọi khách tiếp. Trâm chào đi về, tiếng dép lẹp trên sàn gạch. Minh kéo headphone, bass nhỏ phát ra.
Văn phòng trở về nhịp quen. Tiếng gõ phím. Tiếng máy lạnh. Tiếng nước trong ly Hoàng — đá đã tan hết, ly chỉ còn nước lọc nhạt.
Anh ngồi trong nhịp đó, một tay cầm ly không, tay kia đặt trên bàn phím. Mắt nhìn màn hình, nhưng không thấy gì. Trong đầu anh, năm email xếp thành hàng. Raj gợi ý. Minh vẽ diagram. CQRS. Event sourcing. Log compaction. Mỗi email là một viên gạch, và chúng đang xây một thứ mà Hoàng chưa nhìn thấy hình dáng.
Anh nghĩ về câu hỏi mà anh sẽ không hỏi tối nay.
Và về câu hỏi mà anh sẽ không hỏi ngày mai.
Và về việc mỗi ngày anh không hỏi, kênh sâu thêm một lớp — như mạch nước ngầm dưới nền nhà, âm thầm đào sâu, không ai nghe thấy tiếng, cho đến khi mặt sàn nứt.