How Render Workflows powers our internal data pipeline

Bài tóm tắt Render 2026 1. Khởi đầu Độ khó: Dễ

Render · 2026 · 1. Khởi đầu · Độ khó: Dễ — bài gốc

Bài dùng sản phẩm của chính Render (Workflows, lúc đó đang beta). Phần kiến trúc pipeline vẫn có giá trị chung; số tiền tiết kiệm là theo Render.

Bối cảnh

  • Team dữ liệu của Render chỉ có 2 người. Họ nâng dbt-core từ 1.4 lên 1.11, thêm bảng incremental và kiến trúc nhiều lớp.
  • Một dataset quan trọng (dự báo hoá đơn trong tháng) đến muộn: do một job Go viết từ khoảng 8 năm trước tạo ra, gắn chặt vào quy trình billing nên không tách được.
  • Để đỡ, dbt chạy hai lần mỗi ngày bằng cron (sáng sớm và giữa buổi sáng); job Go hoặc công cụ extract/load (Stitch) chậm thì chạy lần ba. Tốn tiền BigQuery, phải kiểm tra tay, và 7–8 bước của pipeline chỉ được ngăn cách bằng khoảng thời gian chứ không phụ thuộc thật vào nhau. Log rải ở nhiều nơi.
  • Dấu hiệu: CEO vào kênh thông báo pipeline hỏi "có cần chạy lại dbt không?" vì thanh tiến độ trên Metabase đứng ở 44%.

Thay đổi chính

  • Chia model dbt thành hai nhóm: phụ thuộc và không phụ thuộc dữ liệu dự báo. Chạy nhóm độc lập trước, chờ dữ liệu dự báo rồi chạy nhóm còn lại; nếu dữ liệu đã sẵn thì chạy cả project một lần.
  • Cần một bộ điều phối có: chờ việc bên ngoài xong, rẽ nhánh, chạy lại từng task, truyền dữ liệu nhỏ giữa task. Đã cân nhắc Prefect, Dagster (cần hợp đồng trả phí mới đáng), Airflow (quá nặng cho 2 người và một project dbt). Chọn Render Workflows.
  • Sentinel thay cho đoán giờ: job Go nay ghi một dòng vào bảng reports trên BigQuery (giờ bắt đầu, giờ xong, số profile thành công). Workflow chờ dòng đó rồi kiểm tra dữ liệu đã thật sự vào BigQuery. Việc chờ dùng cơ chế retry của nền tảng (số lần retry, thời gian chờ, backoff phẳng) thay vì vòng while not ready: sleep, nên không tốn compute khi chờ. (Stitch không có API báo xong theo bảng, nên không dùng webhook được.)
  • dbt chạy trong subprocess, log đổ theo dòng vào log của task; artefact của dbt ghi lên GCS; mỗi task xong ghi một event vào bảng workflow_run_events, dùng cho lịch sử và dự đoán giờ dữ liệu sẵn sàng.
  • Sau dbt, các task chạy song song: đồng bộ tài liệu, giám sát chi phí, làm mới và hâm nóng cache Metabase. Mỗi task báo trạng thái riêng; cạm bẫy: gom kết quả song song mà không ghi rõ lỗi của từng task thì lỗi nằm im trong danh sách kết quả.
  • Ba chế độ chạy: prod (cron hằng đêm), dry run (sau mỗi deploy, đọc thật nhưng gần như không ghi, bắt lỗi cấu hình), simulate (trong CI, không gọi mạng, mọi task trả kết quả giả, kiểm tra nhánh và cơ chế retry). SDK của nền tảng chỉ nằm trong một file đăng ký task, phần còn lại test được mà không cần SDK, để sau này dời sang hệ khác dễ.
  • Task phụ: phát hiện lệch giữa SQL của reverse ETL (Hightouch) và SQL trong repo (chỉ báo, chờ người quyết); chạy tay có sáu bước kiểm tra an toàn (không job song song, không đang deploy).

Kết quả (theo Render, sau khoảng 30 ngày)

  • Bớt các lần chạy dbt thừa ước tiết kiệm 30 nghìn USD/năm; cache Metabase ước tiết kiệm 70 nghìn USD/năm. Dashboard tải nhanh hơn.

Bài học cho SWE

  • Pipeline xếp theo khoảng cách thời gian thay vì phụ thuộc thật sẽ vừa chạy thừa vừa khó gỡ lỗi; một sentinel từ bước trước là thay đổi nhỏ nhất có giá trị nhất (Pipeline dữ liệu và analytics).
  • Chạy lại cả pipeline "cho chắc" là chi phí ẩn của việc không biết dữ liệu đã sẵn chưa (Chi phí hạ tầng và build vs buy).
  • Chọn bộ điều phối theo cỡ team: Airflow hợp với hàng trăm DAG (Shopify 2022), quá nặng cho hai người.
  • Câu hỏi "dữ liệu xong chưa?" của người dùng là tín hiệu về độ tươi chưa được đo; ghi event mỗi task cho phép trả lời bằng dữ liệu.
  • Tách lõi logic khỏi SDK của nền tảng điều phối giữ đường lui khi phải đổi công cụ.

Liên quan