Xây dựng workflow bền vững trên Postgres mà không cần orchestrator bên ngoài
Postgres có thể đảm nhận vai trò lưu trữ trạng thái bền vững và lớp điều phối cho các workflow, giúp loại bỏ nhu cầu dùng orchestrator bên ngoài. Cơ chế SKIP LOCKED cho phép xử lý công việc đồng thời, checkpoint theo khóa chính đảm bảo tính idempotent, còn lease hỗ trợ phục hồi sau sự cố. Các bước tạm dừng và phê duyệt thủ công cũng được lưu trong database và tồn tại qua các lần khởi động lại.
Postgres không chỉ là một cơ sở dữ liệu quan hệ đơn thuần. Với những tính năng mạnh mẽ như SKIP LOCKED, khóa chính và cơ chế lease, nó hoàn toàn có thể đảm nhận vai trò lưu trữ trạng thái bền vững kiêm lớp điều phối cho các workflow phức tạp — mà không cần đến một orchestrator bên ngoài như Temporal, Airflow hay Cadence.
Bài viết của Raman Varma trên InfoQ mang đến một góc nhìn thực tiễn: với nhiều hệ thống vừa và nhỏ, việc thêm một orchestrator riêng đồng nghĩa với việc phải vận hành thêm một hạ tầng phức tạp, trong khi Postgres — vốn đã hiện diện trong hầu hết hệ thống backend — có thể giải quyết bài toán này một cách gọn gàng hơn.
Vì sao nên dùng Postgres làm lớp điều phối workflow?
Hầu hết ứng dụng backend đều đã có sẵn Postgres. Việc tận dụng chính database này để lưu trạng thái workflow giúp:
- Giảm độ phức tạp vận hành: không cần thêm một hệ thống riêng để cài đặt, giám sát và nâng cấp
- Đảm bảo tính nhất quán giao dịch: trạng thái workflow và dữ liệu nghiệp vụ nằm chung một transaction
- Tận dụng hạ tầng sẵn có: backup, replication, monitoring của Postgres đều áp dụng được
- Dễ debug: chỉ cần một câu truy vấn SQL là có thể kiểm tra toàn bộ trạng thái workflow
Điểm mấu chốt nằm ở chỗ: workflow bền vững không đòi hỏi một engine phức tạp, mà chỉ cần một nơi lưu trạng thái đáng tin cậy và các cơ chế đồng bộ phù hợp.
SKIP LOCKED: Xử lý công việc đồng thời không tranh chấp
Tính năng SELECT ... FOR UPDATE SKIP LOCKED của Postgres là nền tảng cho việc xử lý công việc song song. Thay vì để nhiều worker cùng tranh nhau một bản ghi rồi phải chờ đợi, mỗi worker sẽ tự động bỏ qua các hàng đang bị khóa và nhặt hàng còn trống.
Cách tiếp cận này mang lại lợi ích rõ rệt:
- Nhiều worker có thể chạy song song mà không cần cơ chế phân phối tác vụ phức tạp
- Không có hiện tượng hai worker xử lý cùng một công việc
- Throughput tăng tuyến tính theo số lượng worker (cho đến khi chạm giới hạn của database)
Đây chính là mô hình mà nhiều thư viện hàng đợi dựa trên Postgres như pgmq hay Graphile Worker đang sử dụng.
Checkpoint theo khóa chính để đảm bảo idempotent
Trong môi trường phân tán, việc một bước trong workflow bị chạy lại là điều khó tránh khỏi — do timeout, do retry, hoặc do worker bị crash. Giải pháp là dùng khóa chính làm checkpoint: mỗi bước hoàn thành sẽ ghi một bản ghi với khóa duy nhất. Nếu bước đó bị thực thi lại, lệnh INSERT sẽ thất bại do trùng khóa, và hệ thống biết rằng công việc đã được xử lý trước đó.
Idempotent không phải là tính năng có thể thêm vào sau — nó phải được thiết kế ngay từ đầu trong mô hình dữ liệu.
Cách làm này đơn giản nhưng cực kỳ hiệu quả: thay vì phải xây dựng logic phức tạp để phát hiện trùng lặp, ta để chính ràng buộc của database đảm nhiệm vai trò đó.
Lease và phục hồi sau sự cố
Khi một worker nhận công việc rồi đột ngột dừng lại — do mất điện, do deploy, hay do lỗi phần cứng — công việc đó không được phép "treo" vĩnh viễn. Cơ chế lease giải quyết vấn đề này bằng cách gán cho mỗi công việc một thời hạn.
Nếu worker không hoàn thành và gia hạn lease trước khi hết hạn, công việc sẽ tự động được trả về hàng đợi để một worker khác tiếp nhận. Cách tiếp cận này:
- Tự động phát hiện worker "chết" mà không cần heartbeat phức tạp
- Đảm bảo không có công việc nào bị bỏ quên
- Kết hợp hoàn hảo với checkpoint idempotent để tránh xử lý trùng
Tạm dừng và phê duyệt thủ công cũng là trạng thái
Một trong những điểm thú vị nhất của mô hình này là các bước "ngủ" (sleep) hoặc chờ con người phê duyệt cũng được lưu như trạng thái trong database. Điều đó có nghĩa là:
- Workflow có thể tạm dừng hàng giờ, hàng ngày, thậm chí hàng tuần mà không tiêu tốn tài nguyên
- Khi hệ thống khởi động lại, các workflow đang chờ vẫn tiếp tục đúng tiến trình
- Việc phê duyệt thủ công trở thành một trạng thái bình thường, có thể truy vấn và kiểm toán
Đây là lợi thế lớn so với các giải pháp dùng sleep trong bộ nhớ, vốn sẽ mất trạng thái hoàn toàn khi tiến trình bị dừng.
Ý nghĩa với lập trình viên Việt Nam
Với các đội phát triển tại Việt Nam — đặc biệt là các startup và doanh nghiệp vừa — việc dựng thêm một cụm Temporal hay Airflow thường là khoản đầu tư hạ tầng không hề nhỏ. Trong khi đó, gần như mọi hệ thống backend đều đã có Postgres chạy ổn định.
Việc tận dụng Postgres làm orchestrator cho phép:
- Giảm chi phí vận hành và nhân lực cần thiết
- Rút ngắn thời gian phát triển tính năng mới
- Dễ dàng mở rộng khi quy mô còn vừa phải
- Chỉ chuyển sang orchestrator chuyên dụng khi thực sự cần thiết
Tất nhiên, cách tiếp cận này không phù hợp với mọi trường hợp. Khi số lượng workflow lên tới hàng triệu, hoặc khi cần các tính năng nâng cao như versioning phức tạp, visual debugging hay đa ngôn ngữ, một orchestrator chuyên dụng vẫn là lựa chọn hợp lý hơn.
Nhưng thông điệp cốt lõi vẫn rất đáng suy ngẫm: trước khi thêm một hệ thống mới vào kiến trúc, hãy xem liệu công cụ bạn đang có đã đủ dùng hay chưa. Với Postgres, câu trả lời thường là có.

