2 điểm bởi GN⁺ 2025-11-08 | 1 bình luận | Chia sẻ qua WhatsApp
  • Chỉ ra vấn đề sử dụng cấu trúc hệ thống phức tạp không cần thiết dù số người dùng thực tế rất ít
  • Đưa ra ví dụ về việc kết hợp bừa bãi nhiều công nghệ như Redis, MongoDB, Kubernetes, microservices
  • Nhấn mạnh rằng trong tình huống này, chỉ cần một instance Postgres và cấu hình máy chủ đơn giản là đủ
  • Nhấn mạnh rằng phức tạp không phải là phẩm chất đáng ca ngợi, và chỉ nên mở rộng khi nhu cầu đã được chứng minh
  • Nhắc lại rằng startup và các nhóm phát triển cần tuân thủ nguyên tắc thiết kế đơn giản phù hợp với quy mô

Lạm dụng stack công nghệ không cần thiết

  • Phê phán sự kết hợp công nghệ được chọn một cách ngẫu nhiên, chẳng hạn như dùng Redis và MongoDB cùng lúc
    • Đặt ra các câu hỏi như: “Tại sao Redis lại đang nói chuyện với MongoDB?”, “Tại sao lại dùng MongoDB?”
  • Chỉ ra việc áp dụng hệ thống phân tán dù số người dùng thực tế chỉ là 12 người (trong đó 6 là tài khoản thử nghiệm)
  • Nêu đây là trường hợp chọn mở rộng quá mức dù chỉ một instance Postgres là đủ

Triển khai và hạ tầng bị làm quá mức

  • Cấu hình hiện tại: 15 microservice, 8 cơ sở dữ liệu, cụm Kubernetes cho 3 môi trường, 4 hàng đợi thông điệp, service mesh, pipeline CI/CD mất 2 giờ
  • Cấu hình cần thiết chỉ là một máy chủ đơn, Postgres, và cùng lắm là Redis để caching
  • Đối chiếu rõ ràng sự phức tạp hạ tầng quá mức so với nhu cầu thực tế

Độ phức tạp hệ thống và khả năng giải thích

  • Chỉ ra rằng nếu phải dùng một sơ đồ rối như mì spaghetti để giải thích hệ thống cho một lập trình viên junior thì đó là dấu hiệu có vấn đề
  • Tóm tắt thông điệp cốt lõi bằng câu: Phức tạp không phải là phẩm chất đáng ca ngợi
  • Nhấn mạnh cần bắt đầu đơn giản, và chỉ thêm độ phức tạp khi nhu cầu đã được chứng minh

Bài học cốt lõi

  • Việc chọn công nghệ và thiết kế hệ thống cần được đơn giản hóa cho phù hợp với quy mô và mức sử dụng thực tế
  • Mở rộng bừa bãi và đưa vào stack công nghệ quá mức sẽ làm giảm khả năng bảo trì và hiệu quả
  • Điều quan trọng với startup hoặc nhóm nhỏ là giữ được “sự đơn giản phù hợp với quy mô”

1 bình luận

 
GN⁺ 2025-11-08
Ý kiến trên Hacker News
  • Đôi khi kiểu hành động này đơn giản giống như trì hoãn (procrastination)
    Vì không muốn nói chuyện với khách hàng, nhà đầu tư hay đội pháp lý nên thay vào đó lại làm những việc “thú vị” dưới góc nhìn kỹ sư
    Bề ngoài trông có vẻ năng suất nhưng thực ra chỉ đang giậm chân tại chỗ

    • Cuối cùng nó giống như một quá trình tiến hóa thành nghiện cảm giác vui thích
      Nếu mỗi ngày không cố tình làm một vài việc khó chịu thì con người sẽ dần thụt lùi, và về sau sẽ phải đối mặt với những vấn đề lớn lẽ ra có thể tránh được
      Điều này không chỉ đúng với phần mềm mà còn đúng với cuộc sống nói chung
    • Bản thân tôi cũng từng như vậy trong khoảng 5 năm đầu bootstrapping
      Tôi đã học được rằng muốn kiếm tiền thì phải làm đúng việc theo ưu tiên, chứ không phải việc thú vị
    • Liệu chuyện này có thật sự là vì “niềm vui” không?
      Hay là để thỏa mãn tham vọng về kiến trúc lý tưởng của những CTO hay VPE xa rời thực tế?
      Tôi nhớ trước đây từng có những màn đấu trí trong phỏng vấn thiết kế hệ thống quanh chuyện monolithic vs microservices
      Cuối cùng thì người có quyền lực thường đã rất rõ họ muốn đi theo hướng nào, và chống lại điều đó là đốt vốn chính trị của bản thân
    • Có người dùng chuyện này để khoe bản thân
      Kiểu như liệt kê đầy tự hào: “Tôi đã nối ABC với XYZ”
  • Cũng có động cơ muốn làm cho CV trông hoành tráng hơn
    Thực ra phần lớn dự án hoàn toàn có thể làm được bằng công nghệ từ thập niên 1990, nhưng chỉ cần có những từ như hệ thống phân tán thì nghe sẽ “ngầu” hơn rất nhiều
    Vì văn hóa tuyển dụng lệch lạc của ngành, đầu bếp không được công nhận vì dùng dao giỏi mà phải dùng “đúng thương hiệu dao” mới được đánh giá cao

    • Công ty tốt sẽ không ép những yêu cầu kinh nghiệm ngôn ngữ kiểu này
      Ví dụ DuckDuckGo chỉ yêu cầu thuật toán và cấu trúc dữ liệu, rồi chỉ nói thêm “nhân tiện chúng tôi dùng Perl”
      Stream cung cấp khóa học 10 tuần cho ứng viên chưa biết Go, và Jane Street cũng không yêu cầu kinh nghiệm với OCaml
      bevuta IT GmbH nơi tôi làm việc cũng cho phép nhân viên học Clojure sau khi vào công ty
      Cách tiếp cận này hoàn toàn khác với những tin tuyển dụng lỗi thời kiểu “10 năm kinh nghiệm Ruby on Rails”
    • Tôi cũng thành thật mà nói là từng thiết kế kiến trúc phức tạp không cần thiết
      Chỉ vì tôi muốn thử cái mới và muốn đem ra so sánh
    • Nếu trong phỏng vấn bạn dành thời gian bảo vệ một giải pháp đơn giản dựa trên Postgres, thì bạn sẽ không còn cơ hội nói về hệ thống phân tán như điều người phỏng vấn đang mong đợi
      Cuối cùng thực tế của ngành lại là ngồi bàn về sự phức tạp không cần thiết chỉ để phục vụ vài trăm người dùng
  • Câu “cache bằng Redis” xuất hiện quá thường xuyên, nhưng thật ra Postgres cũng đã đủ tốt
    Việc cứ nhất quyết dùng Redis có vẻ cho thấy chính tác giả cũng không cưỡng lại được ham muốn overengineering

    • Cá nhân tôi không muốn đưa caching vào Postgres
      Khi quy mô còn nhỏ thì chưa cần cache, còn dữ liệu tạm thời thì đặt ở một hệ thống riêng sẽ hấp dẫn hơn
      Phần lớn lớp trừu tượng cache trong framework cũng được thiết kế với Redis trong đầu
      Tốt nhất là bắt đầu bằng cache in-memory, rồi khi cần hãy thêm Redis
    • Ngay cả ở quy mô nhỏ, cache đôi khi vẫn hữu ích
      Nhưng Redis/Valkey thì quá tay. memcached đơn giản và thực tế hơn nhiều
      Vì nó không lưu trạng thái như Redis nên tránh được những mẫu thiết kế tệ phụ thuộc vào tính nhất quán của cache
      Cache trong DB thì chậm vì phải đi qua file system
    • Redis phù hợp để làm lớp đệm tạm thời khi Postgres bắt đầu chậm đi
      Việc viết query cho hiệu quả lại là một vấn đề hoàn toàn khác
      Khi làm cho Postgres nhanh trở lại thì có thể bỏ Redis đi, nhưng thường người ta cứ để nguyên
    • Cũng có thắc mắc liệu Postgres có cache in-memory eventually consistent hay không
    • Redis thực sự tạo ra khác biệt khi quy mô tăng lên
      Trong một web app chạy trên AWS Lambda, khi xử lý 1000 request mỗi giây thì Postgres khá vất vả còn Redis thì rất ổn
      Nhờ sự đơn giản nên trong những trường hợp như vậy nó đáng để dùng
  • Điều thú vị là tác giả nói về “sự đơn giản” nhưng lại dựng trang bằng Tailwind + JS framework + bundler
    Trong khi lẽ ra có thể làm bằng HTML thuần

    • Tôi cũng đồng cảm với triết lý của tác giả
      Vì vậy tôi xin giới thiệu framework web đơn giản mà bạn có thể tự xây: MastroJS
    • Dù vậy Tailwind cũng không phải là framework khổng lồ
      Thực tế nó chỉ tạo ra CSS cho những utility class được dùng
    • React, Tailwind, bundler, Google Font… con người đúng là sinh vật đầy mâu thuẫn
  • Tweet gốc bắt nguồn từ tweet năm 2013 của Jeff Atwood

    • Vì vậy nên thêm (2013) vào tiêu đề bài viết
  • Hiện tại tôi cũng đang cân nhắc một quyết định tương tự
    Nếu là sản phẩm chưa được thị trường kiểm chứng thì nên bắt đầu nhỏ và nhanh để tạo ra một MVP có thể pivot
    Ngược lại, nếu cần cho nhà đầu tư hay doanh nghiệp lớn thấy năng lực thiết kế có thể mở rộng, thì nên chọn cấu trúc có khả năng scale ngay từ đầu
    Nếu mô hình kinh doanh chỉ có thể tồn tại khi tăng trưởng đến mức một DB đơn lẻ không gánh nổi, thì về lâu dài sẽ có lợi hơn nếu đi theo kiến trúc có khả năng mở rộng ngay từ đầu

  • Với người đang làm việc giữa những cơn ác mộng về hạ tầng, “sự đơn giản” có thể nghe rất viển vông
    Nhưng rất nhiều sự phức tạp tồn tại không hẳn vì kỹ thuật mà để giải quyết vấn đề tổ chức
    Tự động hóa triển khai, dự phòng cho sự cố, CI pipeline, quản lý secret, caching... đều là những chốt an toàn để bảo vệ đội ngũ
    Bỏ qua những thứ này sẽ rất rủi ro khi làm việc theo nhóm

    • Thực ra những yêu cầu như vậy hoàn toàn có thể đáp ứng bằng máy chủ monolithic + Postgres
    • Những thứ như CI hay quản lý secret là chuyện tách biệt với độ phức tạp của kiến trúc
      SQLite cũng hoàn toàn dùng được trong production, nhưng định kiến “chỉ để test” vẫn lan rộng
      Thiết lập mặc định của nhiều PaaS cũng phức tạp một cách không cần thiết
    • Không cần dựng CI pipeline hoành tráng ngay từ đầu
      Hãy bắt đầu bằng quy trình build dựa trên checklist, rồi khi nó ổn định thì mở rộng sang tự động hóa
    • Những bài toán khó của khoa học máy tính như cache invalidation vẫn luôn tồn tại
      Tôi muốn thấy những trường hợp microservices thực sự cần thiết ở các dịch vụ không phải tầm FAANG
    • Cuối cùng thì định luật Conway vẫn cho thấy cấu trúc tổ chức sẽ phản chiếu vào thiết kế hệ thống
  • Mọi người bám theo tech stack tiêu chuẩn chỉ vì sợ phải tự suy nghĩ
    Vấn đề là dùng Kafka, Mongo, Redis một cách không phê phán
    Thực ra tự triển khai đúng những tính năng mình cần còn tốt hơn, và khả năng chọn ra tập thành phần tối thiểu mới là cốt lõi của một kỹ sư
    Những thứ như Kafka nhiều khi chỉ là tiêu tiền vô ích

    • Câu “giữa những đồng nghiệp không suy nghĩ thì chẳng ai chỉ trích cả” thật sự rất ấn tượng
  • Câu “chỉ thêm độ phức tạp khi thực sự cần” là đúng, nhưng cũng có những trường hợp về sau rất khó bổ sung
    Nếu thiết kế ban đầu sai thì có thể phải viết lại toàn bộ
    Vì vậy trong thực tế cần những phương án dung hòa kiểu cấu hình k8s đơn giản

  • Gần đây trong một cuộc phỏng vấn tôi cũng có trải nghiệm tương tự
    Trong 10 năm qua tôi tập trung vào việc đạt được PMF (Product-Market Fit) chứ không ám ảnh với khả năng mở rộng ngay từ đầu
    Nếu sản phẩm phù hợp với thị trường thì có thể dùng tiền để giải quyết vấn đề scale
    Nhưng trong phỏng vấn họ hỏi “làm sao scale một dịch vụ Django lên 10 triệu request mỗi ngày”
    Tôi trả lời rằng “chỉ cần nâng cấu hình máy chủ lên”, và có vẻ họ không thấy thỏa mãn