Enabling Multi-Region Data Systems at Notion
Notion · 2026 · 3. Quy mô lớn · Độ khó: Trung bình — bài gốc
Bối cảnh
- Notion ra mắt data residency cho khách EU: dữ liệu khách được xử lý và lưu trong region nơi nó sinh ra, kể cả khi index cho search, chạy analytics hay tạo embedding cho AI.
- Theo Notion, đây không phải "copy môi trường sang region mới". Hệ thống dữ liệu (search, audit log, analytics, AI) phải biết mình đang ở region nào mà không để dữ liệu chảy qua region khác.
Thay đổi chính
-
Chuẩn bị: tách hạ tầng thành các mạng riêng cô lập, mỗi mạng xử lý một lát dữ liệu ứng dụng và ít giao tiếp chéo. Mọi xử lý và lưu trữ của một workspace nằm trong cùng một mạng, nên workspace ID là khoá định tuyến và phân vùng chính, cùng khoá shard từ 2021 (Notion 2021). Theo Notion, hệ thống scale linh hoạt (nhiều mạng cô lập) thì đa region gần như "miễn phí" về mặt mẫu hình.
-
Data lake theo region: CDC bằng Debezium (trên Kubernetes) từ Postgres → Kafka → Spark → data lake của region. Search của workspace EU có cụm Elasticsearch riêng, chỉ index dữ liệu EU.
-
AI theo region: bảng ánh xạ trung tâm workspace → region quyết định onboarding chạy ở đâu; embedding lưu trong vector DB của region.
-
Điều phối tập trung, xử lý theo region: giữ một Airflow ở US vì nó không đụng dữ liệu khách, chỉ gửi việc tới cụm EMR của đúng region. DAG lặp qua các region và sinh task theo region.
-
Event logging:
- client gửi header workspace ID, worker Cloudflare định tuyến tới đúng region;
- server luôn ở đúng mạng nên ghi vào load balancer cục bộ;
- endpoint lọc dữ liệu khách → Kafka của region → bảng Snowflake của region → view gộp.
Nhân dịp này họ thay pipeline Flink tự quản (2022) bằng Snowpipe streaming connector managed.
-
Mẫu hình để dễ bảo trì:
- bảng ánh xạ workspace → region (quan trọng khi dời workspace giữa region);
- thư viện enum region và helper sinh ID DB, đường dẫn S3 theo region, thay cho hardcode;
- tài nguyên không chứa dữ liệu khách (config, định nghĩa job) để tập trung.
-
Phân tích tập trung: một Snowflake chung. Dữ liệu chỉ rời region sau khi một job Spark trong region lọc bỏ dữ liệu khách, nên query và model cũ chạy tiếp, chỉ thêm cột region.
Vì sao (theo Notion)
Yêu cầu tuân thủ và quyền riêng tư của khách EU. Mục tiêu tiếp theo: dựng data stack cho region mới trong vài ngày thay vì vài tháng (đang mở rộng sang Nhật và Hàn).
Bài học cho SWE
- Đa region vì quy định (data residency) khác đa region vì độ tin cậy: mục tiêu là dữ liệu không rời region, chứ không phải nhân bản sang region khác (Độ tin cậy và multi-region).
- Có sẵn một khoá phân vùng tốt (workspace ID) và kiến trúc "nhiều ô cô lập" thì việc thêm region chỉ là thêm ô, cùng ý với Shopify pod (Sharding và tách database).
- Tách control plane tập trung (điều phối, config) khỏi data plane theo region để vừa đơn giản vừa tuân thủ.