Phần 0 · Chương 0.1
Từ ứng dụng đến hạ tầng — đi tìm sản phẩm đích thực
Bạn sẽ tạo ra: Một bản tuyên ngôn định vị; một danh sách non-goals · khoảng 90 phút, bao gồm bài tập
Tài liệu gốc: Tầm nhìn sản phẩm (tiếng Anh)
Chúng ta sẽ mở màn series này bằng chính cách mà đa số các sản phẩm thực tế ra đời: khởi đầu với một ý tưởng chưa thực sự đúng đắn.
Quan sát hết nhóm làm sản phẩm này đến nhóm khác loay hoay thêm tính năng nhắn tin vào ứng dụng — hết CSKH lại đến trò chuyện giữa người mua với người bán — và chứng kiến mọi thứ đổ vỡ, chúng ta quyết định sẽ tự làm một app chat gọn gàng, mượt mà và chỉn chu. Ý tưởng đó tưởng chừng rất tuyệt, nhưng cũng chỉ kéo dài được chừng một ngày. Cuối chương này, chúng ta sẽ cố tình gác nó lại để đón nhận một giải pháp đột phá hơn. Và chính bước lùi ấy lại mang về hai nền móng cốt lõi mà bất kỳ dự án nghiêm túc nào cũng cần chuẩn bị trước khi đặt tay vào bàn phím: bản tuyên ngôn định vị sản phẩm và những mục tiêu cần gạt bỏ (non-goals).
Tính năng hai tuần
Mỗi nhà phát triển mà chúng ta hướng tới bán sản phẩm chắc chắn đều từng trải qua cuộc
hội thoại này: Quản lý sản phẩm (PM) thông báo rằng khách hàng đang đòi hỏi tính năng
nhắn tin. Một kỹ sư nhìn vào bài toán và chỉ thấy đơn giản là một server WebSocket cùng
một bảng messages. Hai tuần, cùng lắm là ba tuần. Và điều kinh ngạc là vị kỹ sư đó
hoàn toàn đúng — phiên bản dựng sơ khai quả thực chạy rất ổn. Trong môi trường phát triển
(development). Và trong một khoảng thời gian ngắn.
Thế rồi, nó chạm mặt thực tế, và từng cụm từ tưởng chừng ngây thơ trong bản ước tính chi phí dần bung xõa thành cả một hệ thống phức tạp. Hãy cùng bóc tách sự phát triển đó, bởi khoảng trống giữa những cụm từ đơn giản và một hệ thống hoàn chỉnh chính là nơi sản phẩm của chúng ta đang ẩn giấu.
"Chỉ cần mở một WebSocket." Một server, một socket, không vấn đề gì. Nhưng ngay khoảnh khắc chúng ta chạy hai instance sau một load balancer, kết nối của người gửi nằm ở một server còn người nhận lại ở một server khác. Lúc này, chúng ta buộc phải chia sẻ trạng thái kết nối giữa các instance, áp dụng sticky routing hoặc một hạ tầng pub/sub trung gian. Và — vì điện thoại di động sẽ có lúc đi qua đường hầm — chúng ta phải xử lý kết nối lại kèm bù đắp dữ liệu (reconnection with backfill), để một client vừa rớt mạng có thể hỏi "tôi đã bỏ lỡ những gì?" và nhận về câu trả lời chính xác.
"Lưu trữ tin nhắn." Một bảng messages dư sức lưu tin nhắn. Nhưng bản thân nó không thể
tự bảo đảm thứ tự tin nhắn khi có nhiều luồng gửi đồng thời (concurrent sends), không thể biến
các thao tác ghi thành đẳng xâm (idempotent) để một request gửi lại không làm nhân đôi tin nhắn,
không thể phân trang một bảng dữ liệu nóng bằng cursor thay vì dùng offset dễ gây sụp đổ hệ thống,
cũng chẳng thể thực thi chính sách lưu trữ khi bộ phận pháp lý hỏi chúng ta giữ cuộc trò chuyện
của khách hàng trong bao lâu.
"Hiện ai đang online." Trạng thái hiển thị (presence) nhìn qua tưởng chỉ là một giá trị đúng/sai (boolean). Nhưng thực chất, đó là một chuỗi nhịp đập heartbeat, một khoảng thời gian sống (TTL), và một kịch bản ứng phó khi mạng bị phân mảnh — bởi vì "chấm xanh nói dối" còn tồi tệ hơn là không có chấm xanh nào.
"Gửi thông báo." Đằng sau một cái thông báo đơn thuần là cả một cỗ máy trạng thái phân phối (delivery state machine): đẩy tin (fan-out) tới những người dùng đang offline, cơ chế thử lại (retry) cho những ai chưa chạm tới được, và khử trùng lặp (deduplication) để các lượt thử lại không biến thành những thông báo trùng lặp.
"Cho bên support xem luồng tin nhắn." Khi có yêu cầu từ kiểm duyệt viên, chúng ta phải cung cấp cho họ công cụ kiểm duyệt, nhật ký vết (audit trail), khả năng xuất dữ liệu và xóa theo yêu cầu — toàn bộ mảng tuân thủ pháp lý (compliance) mà trước đó chẳng ai đưa vào scope.
"Tốn kém thế này hết bao nhiêu tiền?" Bộ phận tài chính rồi cũng sẽ gõ cửa để hỏi chi phí sử dụng của từng khách hàng. Để trả lời, chúng ta phải đo lường hàng triệu event cho từng tenant, và cái cơ sở dữ liệu vận hành — chính cái đang gánh luồng chat live — lại là nơi tồi tệ nhất để chạy những câu truy vấn đó.
Vậy là, một tính năng dự tính làm trong hai tuần đã biến thành một hệ thống ngốn mất sáu tháng. Nhưng đây mới là quan sát quan trọng hơn cả, và cũng là khoảng trầm cảm xúc của cả chương này: Chi phí đắt đỏ nhất không nằm ở phiên bản đầu tiên. Nó nằm ở năm thứ hai. Giờ đây, phải có người túc trực 24/7 để kiểm tra tin nhắn sự cố cho một hệ thống vốn chẳng phải là sản phẩm cốt lõi của công ty. Một kỹ sư nào đó giờ đây phải gánh gồng tính năng nhắn tin này vĩnh viễn. Mọi đội ngũ tự build hệ thống chat nội bộ đều đang tự đặt bút ký vào khoản thuế đó, chỉ là phần lớn trong số họ vẫn chưa nhận ra mà thôi.
Ai đã từng giải bài toán này — và khoảng trống họ bỏ lại
Chúng ta không phải những người đầu tiên nhìn ra vấn đề. Vậy nên trước khi đặt viên gạch nào, hãy dạo một vòng xem một đội ngũ đang mắc kẹt trong cuộc hội thoại kia có thể gõ những cánh cửa nào. Có đúng ba cánh cửa.
Cánh cửa thứ nhất: cứ thế tự xây. Toàn quyền kiểm soát, vừa vặn từng nhu cầu — đổi lại là khoản thuế bảo trì vĩnh viễn vừa kể trên, trả cho một tính năng chẳng hề giúp sản phẩm trở nên khác biệt. Với đa số các đội, đây là lối đi mặc định chứ không phải một quyết định thực thụ.
Cánh cửa thứ hai: những nền tảng kỳ cựu. Stream, Sendbird, PubNub, Ably. Đây đều là những sản phẩm thực lực, và chúng ta nên thẳng thắn thừa nhận điều đó — lao vào so kè độ rộng tính năng với họ sẽ là dại dột. Nhưng họ được định giá và đóng khung cho những triển khai cỡ lớn; bề mặt sản phẩm rộng tới mức phải đầu tư thời gian thật sự mới học nổi; còn báo cáo mức sử dụng thì mờ mịt đến độ dự đoán hóa đơn quý sau trở thành một bài toán khó. Một đội mười lăm kỹ sư ngồi đánh giá họ sẽ có cảm giác như đang sắm nguyên một chiếc máy bay chở khách chỉ để băng qua một con sông.
Cánh cửa thứ ba: hạ tầng thời-gian-thực thuần túy. Pusher, Supabase Realtime, hay Redis pub/sub trần trụi. Chúng trao cho ta một tầng vận chuyển — các byte lao vun vút từ điểm này sang điểm kia. Nhưng tầng vận chuyển đâu phải là chat: channel, membership, lịch sử tin nhắn, trạng thái đã-đọc — tất cả vẫn nằm nguyên trên vai chúng ta. Cánh cửa thứ ba, suy cho cùng, chính là cánh cửa thứ nhất với phần dễ nhất được đem đi thuê ngoài.
Giờ hãy ngắm kỹ hình hài của thứ còn thiếu. Giữa "một tầng vận chuyển mù tịt về chat" và "một nền tảng quá đồ sộ để ôm trọn trong đầu" là một khoảng trống: một mô hình miền chat đúng nghĩa — channel, membership, lịch sử, giao nhận, trạng thái đã-đọc — với bề mặt đủ gọn để lĩnh hội trọn vẹn trong một buổi chiều. Khoảng trống ấy chính là một sản phẩm.
Sản phẩm ẩn mình trong thất bại
Và đến đây, ý tưởng ban đầu của chúng ta lặng lẽ trút hơi thở cuối cùng. Hãy nhìn lại những gì ta vừa miêu tả suốt từ đầu chương: không phải màn hình giao diện, không phải bộ chọn emoji, càng không phải một khung threads bóng bẩy — mà là lớp vải kết nối, những bảo đảm về thứ tự, cỗ máy trạng thái giao nhận, đường ống đo đếm. Thứ khó nhằn và đáng giá trong không gian này không phải là thêm-một-ứng-dụng-chat-nữa. Nó là phần hạ tầng âm thầm nằm dưới mọi tính năng chat: phần mà đội nào cũng xây lại một cách chật vật, và cũng là phần mà không một khách hàng nào của họ nhìn thấy.
Thế là chúng ta quay xe: chúng ta không làm ứng dụng chat nữa. Chúng ta xây hạ tầng chat để các đội sản phẩm nhúng thẳng vào ứng dụng của họ — một API và một SDK, theo đúng cái cách Stripe là API của thanh toán và Twilio là API của SMS. Năm năm nữa, chúng ta muốn bất kỳ đội ngũ nào cần tính năng hội thoại trong ứng dụng đều có thể ship nó trong một tuần thay vì một quý — với sự tự tin ở đẳng cấp Stripe.
Đó là bài học tư duy sản phẩm đầu tiên của chương này, và nó đúng ở mọi nơi: sản phẩm thật thường nằm sâu hơn ý tưởng bề nổi đúng một tầng. Ý tưởng bề nổi là thứ người dùng kể ra được. Sản phẩm là thứ những người xây dựng cứ mãi loay hoay xây hỏng.
Không phải tất cả mọi người. Một ai đó thật cụ thể.
"Hạ tầng chat cho tất cả những ai cần chat" cũng chưa phải một sản phẩm — đó là một lời cầu nguyện. Một sản phẩm cần một mũi nêm (wedge): nhóm khách hàng cụ thể mà với họ, lựa chọn này hiển nhiên đúng và cấp bách ngay lúc này. Tài liệu tầm nhìn đã đặt cược vào một mũi nêm như thế.
Mũi nêm ấy là các sản phẩm B2B SaaS sở hữu bề mặt cộng tác. Công cụ quản lý dự án. Nền tảng điều phối y tế. Dashboard logistics. Marketplace dịch vụ chuyên nghiệp. Những đội ngũ tầm năm đến năm mươi kỹ sư, không có nhóm hạ tầng chuyên trách.
Vì sao lại là họ? Vì họ cùng chia sẻ ba đặc điểm, và mỗi đặc điểm đều gánh một vai thực thụ trong lập luận:
- Chat đứng cạnh giá trị cốt lõi của họ, chứ không phải chính giá trị cốt lõi. Họ sẽ chẳng bao giờ lập hẳn một đội nhắn tin; tự xây là một mối phân tâm mà họ chỉ mong có cớ để khước từ.
- Người dùng của họ đã được định danh và xác thực từ trước. Chúng ta không bao giờ phải hóa thân thành nhà cung cấp danh tính — backend của họ tự đứng ra bảo chứng ai là ai.
- Lưu lượng của họ đáng kể, nhưng chưa chạm quy mô Internet. Tải thật, doanh thu thật — mà không kèm mớ bài toán trăm-triệu-kết-nối vốn thuộc về các mạng xã hội.
Các phân khúc hạng hai — marketplace cần hội thoại người mua–người bán kèm kiểm duyệt và nhật ký vết (audit trail), ứng dụng tiêu dùng giai đoạn sớm nơi tốc độ ra thị trường quan trọng hơn chi phí đơn vị, hay các đội nền tảng nội bộ muốn chuẩn hóa mảng nhắn tin — đều khớp chung một khuôn hình. Và có những vị khách chúng ta điểm mặt gọi tên chỉ để từ chối cho đàng hoàng: mạng xã hội với hàng trăm triệu kết nối, những triển khai chịu quản chế đòi hỏi mã hóa đầu-cuối hay cài đặt on-premise, và những đội thực lòng muốn một Slack hoàn chỉnh chứ chẳng phải hạ tầng.
Gói gọn trong một câu
Đến lúc mọi thứ phía trên phải nén lại thành một hình hài mà chúng ta dám để người khác phán xét dựa trên nó. Mẫu tuyên ngôn định vị kinh điển ép từng lựa chọn khó nhằn vào vỏn vẹn một hơi thở:
Dành cho [đối tượng] đang [nhu cầu], [sản phẩm] là một [hạng mục] mang lại [lợi ích]. Khác với [phương án thay thế], sản phẩm của chúng tôi [điểm khác biệt].
Và đây là phiên bản của Relay, đã điền trọn vẹn — hãy đọc thật chậm, bởi mỗi vế câu là nguyên một mục của chương này được nén thành một cụm từ:
Dành cho các đội kỹ sư sản phẩm tại những công ty phần mềm B2B và marketplace đang cần nhắn tin trong ứng dụng nhưng không thể biện minh cho việc tự xây và tự vận hành nó, Relay là một nền tảng hạ tầng chat mang lại nhắn tin thời gian thực dưới dạng API được host sẵn, kèm SDK phía client, webhook, và phân tích mức sử dụng theo từng tenant. Khác với việc tự xây trên WebSocket trần hay ôm về một nền tảng kỳ cựu nặng nề, Relay đặt API lên hàng đầu, minh bạch về giao nhận lẫn mức sử dụng, và đủ nhỏ gọn để lĩnh hội trong một buổi chiều.
Mẫu câu này xứng đáng với từng giọt công sức bởi chính những gì nó thẳng thừng từ chối. "Dành cho tất cả mọi người" không tài nào nhét vừa ô đầu tiên. Việc gọi tên phương án thay thế một cách sòng phẳng — kể cả những nền tảng kỳ cựu mà ta nể trọng — buộc điểm khác biệt phải là hàng thật: không phải "chat xịn hơn", mà là API lên hàng đầu, minh bạch về mức sử dụng, đủ nhỏ để học trong một buổi chiều. Một điểm khác biệt không sống sót nổi khi được đọc to trước khách hàng của chính đối thủ được nêu tên? Gạch bỏ không thương tiếc.
Non-goals là cam kết, không phải gợi ý
Tuyên ngôn định vị nói lên chúng ta là ai. Người anh em trong gương của nó nói lên chúng ta không là ai — và theo trải nghiệm của chính chúng ta, tấm gương ấy mới là bên gánh nhiều việc hơn. Phình phạm vi (scope creep) chẳng bao giờ gõ cửa dưới dạng một ý tưởng tồi; nó luôn xuất hiện như một ý tưởng hay — chỉ tiếc không phải của chúng ta. Phòng tuyến duy nhất là một danh sách thành văn những ý tưởng hay bị khước từ, mỗi mục đính kèm một lý do. Danh sách của Relay:
- Không phải một ứng dụng chat. Không có sản phẩm đầu-cuối host sẵn, gắn nhãn thương hiệu tùy chỉnh. Chính là ý tưởng mở màn chương này — nay được an táng một cách trang trọng.
- Không mã hóa đầu-cuối (E2E) trong v1. Không phải vì nó lỗi mốt — mà vì nó xung khắc tận gốc với kiểm duyệt phía server và lịch sử hội thoại mà thị trường mũi nêm của chúng ta đòi hỏi, trong khi thị trường ấy còn chưa lên tiếng đòi E2E. Một non-goal có cơ chế chống lưng thì khó bị lật kèo hơn nhiều so với một sở thích cảm tính.
- Không phải nhà cung cấp danh tính. Khách hàng sở hữu danh bạ người dùng của họ; backend của họ bảo chứng cho người dùng của họ. Khước từ mảnh scope này chính là điều giữ cho câu chuyện bảo mật của chúng ta luôn đơn giản.
- Không có cuộc gọi thoại hay video. A/V thời gian thực là một bài toán vận chuyển khác, một cấu trúc kinh tế khác — nói thẳng ra là nguyên một công ty khác. Còn tệp media — ảnh, âm thanh, video đính kèm — thì có mặt: Relay lưu trữ chúng, quét an toàn cho chúng, và đo đếm dung lượng của chúng. Ranh giới được vạch ở luồng streaming, chứ không phải ở những byte dữ liệu.
- Không tính năng AI copilot, ngoài phân loại nội dung tùy chọn. Sức cám dỗ rất lớn — và đó chính xác là lý do nó phải nằm trong danh sách.
- Không SDK mobile native trong v1. Một SDK JavaScript được chăm chút tử tế, chạy mượt trên trình duyệt, Node lẫn React Native, ăn đứt bốn chiếc SDK dang dở.
Để ý khuôn mẫu chung: mỗi dòng đều điểm mặt một sản phẩm có thật mà sớm muộn sẽ có người mời gọi chúng ta trở thành, kèm lý do vì sao chúng ta lắc đầu. Cái lý do ấy chính là linh hồn của bản danh sách. Một năm sau, câu hỏi "hay là mình thêm threads nhỉ?" sẽ không còn là một cuộc tranh luận — nó chỉ còn là một lần tra cứu.
Và những cái lý do ấy còn mua về cho chúng ta một thứ nữa: một con đường chính danh để đổi ý. Điều khoản tệp media phía trên chính là một cú quay đầu — bản nháp trước đây từng loại trừ thẳng thừng việc lưu trữ file, với những lý do rành mạch: chi phí lưu trữ, quét virus, nỗi lo CDN. Rồi một bản thiết kế trả lời được từng lý do một — upload đi thẳng lên kho lưu trữ mà không chạm vào server của Relay, quét virus vận hành như một pipeline bất đồng bộ — và chính thị trường mũi nêm trao cho ta động cơ: một tin nhắn thoại của bác tài hay tấm ảnh kiện hàng móp méo — bản thân nó chính là tin nhắn. Thế là non-goal ấy được đảo ngược một cách công khai, lý do đi trước. Một non-goal không có lý do thì chỉ có thể cố thủ hoặc buông xuôi; một non-goal có lý do thì luôn có thể được đem ra tái thẩm một cách sòng phẳng.
Đến lượt bạn
Giờ là lúc tự tay tạo ra các tài liệu của chương — cho ý tưởng dự án của chính bạn, không phải của chúng ta. Nếu trong túi chưa sẵn ý tưởng nào, cứ mượn tạm: một công cụ đặt lịch cho các phòng khám thú y đang rục rịch bổ sung tính năng nhắc hẹn và cổng thông tin khách hàng. Hai mươi phút lao động trung thực đáng giá hơn hai tiếng đồng hồ ngồi đánh bóng.
Bài tập 1 — bản tuyên ngôn định vị. Lấy mẫu câu:
Dành cho [đối tượng] đang [nhu cầu], [sản phẩm] là một [hạng mục] mang lại [lợi ích]. Khác với [phương án thay thế], sản phẩm của chúng tôi [điểm khác biệt].
Điền cho sản phẩm của bạn, rồi soi qua các câu tự kiểm sau. Mỗi câu đều trả lời được dứt khoát bằng có hoặc không:
- Đối tượng đã đủ cụ thể để bạn kể tên ba công ty thật khớp với nó — và một công ty cố tình không khớp?
- Nhu cầu có đang mô tả nỗi đau của khách hàng, thay vì tính năng của bạn?
- Người dùng của chính phương án thay thế được nêu tên liệu có gật đầu công nhận mô tả của bạn về nó là công bằng?
- Điểm khác biệt của bạn có trụ vững khi được đọc to trước một trong những người dùng ấy?
- Hạng mục của bạn có phải thứ mà ngân sách các công ty đã dành sẵn một dòng chi?
Nếu câu 1 trượt, ô đầu tiên của bạn đang viết "tất cả mọi người" dưới một lớp ngụy trang. Nếu câu 3 hoặc 4 trượt, điểm khác biệt của bạn mới là marketing chứ chưa phải định vị. Cứ viết lại đến khi cả năm câu cùng đạt; hai ba vòng là chuyện thường tình. Bản của chúng ta còn ngốn nhiều vòng hơn thế.
Bài tập 2 — danh sách non-goals. Viết tối thiểu ba non-goal cho sản phẩm của bạn. Thước đo cho từng mục:
- Nó có điểm mặt một sản phẩm hay năng lực có thật mà sẽ có người thật lòng yêu cầu không? ("Chúng tôi sẽ không chậm" không phải một non-goal; "không có chế độ offline" thì đúng chuẩn.)
- Nó có nêu rõ lý do — một cơ chế hay một khoản chi phí, chứ không phải một tâm trạng?
- Nếu gạch mục này đi, kiến trúc, quy mô đội ngũ hay thị trường của bạn có xoay chuyển không? (Nếu chẳng có gì xoay chuyển, nó không đáng một dòng mực.)
Hãy cất cả hai tài liệu ngay trong repository bạn định khởi công dự án, đừng đem gửi trên wiki. Chúng đã là những tài liệu kỹ thuật thực thụ, và tới chương 0.4, chúng sẽ nảy mầm thành một bản đặc tả yêu cầu hoàn chỉnh.
Những điều đọng lại
Nếu bạn không đọc thêm bất cứ điều gì khác trong Phần 0, hãy mang theo những điều này:
- Chat là một bài toán hệ thống khoác lên mình bộ cánh tính năng. Thứ tự tin nhắn, tính đẳng xâm (idempotency), kết nối lại, presence, kiểm duyệt, đo đếm — bản ước tính trượt vì mọi phần khó đều tàng hình trong một bản demo.
- Chi phí thật của việc tự xây nằm ở năm thứ hai, trả bằng những ca trực on-call và một kỹ sư gánh gồng mảng nhắn tin mãi mãi.
- Khoảng trống thị trường rất rõ nét: một mô hình miền chat đúng nghĩa với bề mặt đủ gọn để ôm trọn trong đầu — nằm lọt giữa các tầng vận chuyển trần trụi và những nền tảng đồ sộ.
- Mũi nêm của Relay là B2B SaaS có bề mặt cộng tác: những đội năm-đến-năm-mươi kỹ sư, người dùng đã được xác thực sẵn, và chat đứng cạnh giá trị cốt lõi của họ.
- Tuyên ngôn định vị và non-goals là tài liệu kỹ thuật. Một bên nén mọi lựa chọn sản phẩm vào một câu có thể kiểm chứng; bên kia biến những cuộc tranh cãi phạm vi trong tương lai thành các lần tra cứu chớp nhoáng. Cả hai là bản hợp đồng cho toàn bộ phần còn lại của series.