0

Stack Backend của tôi chỉ gồm TypeScript + Postgres. Và như thế là đủ

Hầu hết mọi người thường suy nghĩ quá nhiều về backend ngay từ đầu. Bạn bắt đầu xây dựng một sản phẩm mới và ngay lập tức lao vào tìm hiểu Kafka, Redis, các worker nền, hàng đợi thông điệp, pipeline phân tích dữ liệu, lớp caching và năm dịch vụ vi mô. Nhưng nếu thẳng thắn mà nói, có lẽ bạn không cần đến hầu hết những thứ đó.

Với rất nhiều sản phẩm SaaS – đặc biệt là trong giai đoạn đầu – một stack đơn giản sẽ giúp bạn tiến xa hơn, nhanh hơn. Toàn bộ stack backend của tôi chỉ có TypeScript và Postgres – và như thế là quá đủ.

TypeScript: Một ngôn ngữ “thống trị” toàn bộ stack

Sử dụng TypeScript ở mọi nơi giúp tôi không phải chuyển ngữ cảnh liên tục. Tôi không cần nhảy qua Python cho service này, Go cho service kia và JavaScript cho frontend. Chỉ một ngôn ngữ xử lý tất cả – từ viết logic API, xác thực dữ liệu, đến định hình kiểu dữ liệu xuyên suốt ứng dụng.

Ở backend, TypeScript hoạt động rất tốt một cách bất ngờ. Với các công cụ như tRPC và Zod, bạn có thể xây dựng API vừa nhanh vừa an toàn về mặt kiểu dữ liệu mà không cần viết schema riêng hay hợp đồng REST. Bạn chỉ cần xác thực đầu vào một lần, sau đó suy ra kiểu dữ liệu xuyên suốt ứng dụng và giữ mọi thứ đồng bộ.

Ngoài ra, việc onboarding cho người mới cũng dễ dàng hơn nhiều. Nếu họ đã biết frontend TypeScript thì họ sẽ tiếp cận backend rất nhanh. Không cần phải dạy thêm 2-3 ngôn ngữ hay framework khác nhau.

Postgres: Cơ sở dữ liệu mạnh mẽ có thể làm mọi thứ

Nhiều người thích làm phức tạp hệ thống dữ liệu của mình. Nhưng thực tế, Postgres là một "quái vật". Nó lưu trữ dữ liệu quan hệ cực kỳ tốt, hỗ trợ JSON nếu bạn cần linh hoạt, có tìm kiếm toàn văn (full-text search), và hỗ trợ rất tốt các chỉ mục và ràng buộc.

Cần chạy background job? Bạn có thể dùng LISTEN/NOTIFY, triggers theo lịch, hoặc đơn giản là polling một bảng bằng một worker riêng biệt. Cần lưu lại sự kiện ứng dụng, log audit, hoặc analytics? Postgres vẫn lo được.

Phần cứng hiện đại càng khiến nó mạnh hơn nữa. Một instance Postgres được scale dọc trên hạ tầng đám mây hiện nay có thể có 64+ vCPU và 256+ GB RAM – quá đủ cho phần lớn sản phẩm SaaS. Thực tế, 99% ứng dụng sẽ không bao giờ dùng hết tài nguyên như vậy.

Điều quan trọng là: số người dùng hoạt động hàng tháng (MAU) không đồng nghĩa với số người dùng đồng thời. Nếu bạn có 100.000 MAU, không có nghĩa là bạn xử lý 100.000 request cùng lúc. Phần lớn người dùng chỉ đăng nhập vài phút mỗi ngày, có khi còn ít hơn. Độ đồng thời thực tế chỉ là một phần nhỏ.

Và nếu bạn thực sự đạt tới mức giới hạn đó – thì đó là một vấn đề "đáng mừng". Lúc đó bạn sẽ có đủ tài nguyên và thời gian để mở rộng một cách đúng đắn. Việc mở rộng sớm không chỉ là không cần thiết mà còn thường dẫn đến những quyết định sai lầm và hệ thống dễ gãy.

Ít thành phần hơn = Tập trung hơn

Càng ít công cụ thì bạn càng ít phải bảo trì. Mỗi dịch vụ mới đều thêm chi phí: file cấu hình, triển khai, xử lý edge case, giám sát, khôi phục lỗi... Nếu có sự cố xảy ra, bạn sẽ muốn biết chỗ cần kiểm tra. Khi stack của bạn chỉ có hai thứ, việc debug dễ dàng hơn nhiều.

Môi trường phát triển local cũng đơn giản hơn. Không cần Docker Compose chạy 12 container. Không cần các service riêng cho job nền, caching hay truyền thông giữa các service. Chỉ cần khởi động Node server và một container Postgres là xong.

Tôi đã từng xây dựng những hệ thống phức tạp – cụm Kafka, pipeline analytics với ClickHouse, hàng đợi job với Redis. Chúng có giá trị riêng, nhưng cũng có chi phí. Và ở giai đoạn đầu của sản phẩm, chúng gần như luôn không cần thiết.

Phần mềm đơn giản dễ scale hơn

Nghe có vẻ ngược đời, nhưng càng đơn giản, bạn càng dễ scale về sau. Nhiều người nghĩ cần tối ưu sớm để tránh giới hạn sau này – nhưng thực tế thường ngược lại. Tối ưu sớm sẽ “khóa cứng” bạn vào những quyết định khó thay đổi, làm tăng độ phức tạp và khiến việc scale khó hơn, chứ không dễ hơn.

Scale một app đơn giản dựa trên Postgres và TypeScript dễ hơn rất nhiều so với một Frankenstein đầy service được thêm vào “cho chắc”. Cách tốt nhất để chuẩn bị cho việc mở rộng là giữ mọi thứ gọn gàng cho đến khi biết chính xác thứ gì cần scale.

Bạn không phải Google. Scale chưa phải là vấn đề (ít nhất là hiện tại)

Phần lớn app không cần scale ngay. Thứ chúng cần là sống sót đủ lâu để có người dùng. Dễ bị lừa là bạn đang xây dựng cho “scale”, nhưng thực ra là bạn đang lãng phí thời gian giải quyết những vấn đề chưa tồn tại.

Postgres xử lý hàng ngàn ghi mỗi giây. Nó lưu hàng triệu dòng mà không chảy mồ hôi. Scale dọc có thể giúp bạn đi rất xa – một instance Postgres mạnh là đủ cho các nhu cầu mở rộng ban đầu. Và khi bạn thực sự gặp giới hạn, bạn sẽ biết chính xác mình cần cải thiện gì.

Tối ưu sớm là một hình thức trì hoãn. Bạn có thể ship tính năng hoặc tốn hai tuần xây hệ thống cache Redis cho trang chủ chẳng ai ghé. Tôi đã từng làm cả hai. Và cái đầu tiên luôn thắng.

Tập trung = Nhanh hơn = Sản phẩm tốt hơn

Điều tuyệt nhất của stack đơn giản là tốc độ. Bạn không cần mất thời gian tích hợp service hay đọc 20 trang tài liệu về công cụ bạn còn chưa hiểu rõ. Bạn chỉ cần xây dựng.

CI/CD dễ hơn. Test nhanh hơn. Ít thư viện cần cập nhật. Khi có sự cố production, ít chỗ cần kiểm tra hơn. Tất cả gộp lại thành nhiều thời gian hơn để cải tiến sản phẩm.

Với lập trình viên solo hoặc nhóm nhỏ, điều này là một lợi thế lớn. Làm được nhiều hơn với ít code hơn, ít bug hơn và không phải đổi ngữ cảnh liên tục. Bạn không tốn năng lượng để quản lý độ phức tạp – bạn tập trung xây tính năng mà người dùng quan tâm.

Thế còn job nền, cache, analytics thì sao?

Luôn có những trường hợp cần đến công cụ phức tạp hơn. Nhưng kể cả lúc đó, TypeScript và Postgres vẫn thường xử lý được khá tốt.

  • Job nền? Dùng một cron worker kiểm tra bảng trong DB và đánh dấu hoàn thành.
  • Phản ứng với sự kiện? Dùng LISTEN/NOTIFY cùng một event dispatcher đơn giản trong backend.
  • Caching? Dùng cache trong bộ nhớ cho endpoint cụ thể hoặc tận dụng cache ở cấp độ HTTP.
  • Analytics? Log sự kiện vào bảng Postgres, tổng hợp theo lịch, hiển thị bằng dashboard. Trừ khi bạn cần real-time với khối lượng lớn, như vậy là đủ.

Thực tế là: bạn luôn có thể thêm vào sau. Nhưng việc loại bỏ một công cụ đã ăn sâu vào kiến trúc thì rất khó.

Kết luận

Tôi đã xây dựng các dự án, công cụ chỉ với stack này: TypeScript + Postgres. Nó xử lý đăng ký, gửi phản hồi, tìm kiếm toàn văn, API, cron jobs, background workers, giới hạn tốc độ, và hơn thế nữa – mà không cần thêm service nào khác.

Nếu bạn đang xây một sản phẩm SaaS hoặc công cụ nội bộ, đừng phức tạp hóa mọi thứ. Stack không cần hào nhoáng. Nó chỉ cần đáng tin cậy và dễ phát triển. TypeScript và Postgres có thể đưa bạn đi xa hơn bạn nghĩ rất nhiều.

Giữ mọi thứ đơn giản. Di chuyển nhanh. Và khi đến lúc scale, bạn sẽ thấy mình đã bắt đầu đúng cách.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí