Phần web (Next.js) và file tĩnh chuyển sang Cloudflare; API, Postgres, Redis, Temporal và NATS giữ trên AWS. exam.flyer.us là ứng dụng đầu tiên, chuyển dần theo tỉ lệ khách truy cập.
site exam.flyer.us hiện tại, có chạy 100% trên Cloudflare được không? Chi phí sever có tốt hơn trên AWS không? Anh thấy chi phí sever trên AWS đang 3000$/tháng
build cho anh infrastructure để anh move qua Cloudflare
đẩy Runbook và Overall plan lên roadmap.flyer.vn/prd nhé
Tài liệu do trợ lý AI soạn trong một phiên làm việc. Nguồn: mã nguồn các repo trên Gitea (flyer/webs, exam, flyer-rs, flyer-go-*, backend-v1, upload); header HTTP của từng tên miền ngày 22/10/2026; bảng giá công khai của Cloudflare (Workers, Containers, R2); kết quả build và kiểm thử trên preview. Mã của giai đoạn 1 nằm ở nhánh infra/cloudflare của flyer/webs, chưa đẩy lên Gitea.
Giới hạn: không có quyền truy cập AWS (Cost Explorer, EKS, RDS), nên phần tiết kiệm trên AWS chưa tính được và bảng phân bổ 3.000 USD chưa có. Thời gian phản hồi đo trên preview gần như không có lưu lượng, nên tỉ lệ khởi động lạnh cao hơn thực tế. Giá Cloudflare Containers lấy từ trang giá khi sản phẩm còn beta. Kết quả kiểm thử đo trên bản preview exam-cf.flyer.us (v1.39.6), đã gỡ ngày 22/10/2026; phongthiao.com chạy cùng bản build Cloudflare, kèm tính năng Bingo, trên bản v1.39.4.
Chuyển 100% không khả thi trong ngắn hạn: Cloudflare không có Postgres, Redis, Temporal hay NATS, và chạy API Go/Rust phải dùng Containers (còn beta).
| Thành phần | Trên Cloudflare | Kết luận |
|---|---|---|
| Web Next.js (exam, teacher, study, ielts, ranking…) | Workers | Chuyển |
| File tĩnh, audio, video (statics, stream) | R2 | Chuyển |
| API Go/Rust (exam-v2, flyer-rs, flyer-go) | Containers (beta) | Giữ AWS |
| Redis Sentinel, Temporal, NATS | Không có dịch vụ tương đương | Giữ AWS |
| Postgres (~270 GB) | Không có Postgres; D1 là SQLite, tối đa 10 GB | Giữ AWS (RDS) |
| Đường đi | Tên miền |
|---|---|
| Cloudflare proxy → AWS | exam.flyer.us, login.flyer.us (cùng bản build với exam), signup.flyer.us, statics.flyer.vn |
| CloudFront → AWS | teacher.flyer.us, teacher.teado.ai, parent, study, ranking, speaking, games, statics.flyer.us, stream.flyer.us |
| Thẳng vào AWS | api, upload, admin, partner, ielts |
Mọi tên miền trên đều nằm trong tài khoản Cloudflare của FLYER, nên chuyển web chỉ cần thêm route cho Worker, không phải đổi nameserver.
| Giai đoạn | Nội dung | Trạng thái |
|---|---|---|
| 1. exam web | exam.flyer.us, login.flyer.us → Worker; chia dần lưu lượng 5 → 25 → 50 → 100% | Đã kiểm thử, chờ duyệt 5% |
| 2. File tĩnh | statics.flyer.vn, statics.flyer.us → R2 flyer-statics, đọc xuyên từ S3 bằng Sippy | Đã tạo bucket, chờ khóa AWS |
| 2b. Upload | Dịch vụ upload ghi thẳng vào R2 qua API S3 | Chưa làm |
| 3. Các web còn lại | teacher (partner-web v3.39.9), study (webs-study v1.39.7), ranking, ielts, signup, speaking | Chưa làm |
| 4. Thu nhỏ AWS | Bỏ pod web trên EKS và CloudFront; Savings Plan/RI cho RDS và node còn lại | Sau giai đoạn 1–3 |
| Dịch vụ Cloudflare | Giá |
|---|---|
| Workers Paid | 5 USD/tháng, gồm 10 triệu request và 30 triệu ms CPU; sau đó 0,30 USD/triệu request, 0,02 USD/triệu ms CPU |
| R2 | 0,015 USD/GB/tháng; băng thông ra miễn phí |
| Containers (beta) | ~0,072 USD/vCPU-giờ (chỉ tính khi CPU chạy), ~0,009 USD/GiB-giờ bộ nhớ |
Rút ra khi chuyển exam; áp dụng lại cho từng repo ở giai đoạn 3.
@opennextjs/cloudflare và wrangler; nâng Next.js lên bản OpenNext yêu cầu..env.cloudflare: thay địa chỉ nội bộ cluster bằng địa chỉ công khai.bundlePagesRouterDependencies), tránh hai bản React/Router.next/error, googleapis.X-Forwarded-Host để api.flyer.us đặt cookie phiên đúng tên miền.CF_SHARE.| Việc | Người làm | Mở khóa |
|---|---|---|
| Duyệt bật 5% cho exam.flyer.us | Chủ dự án | Giai đoạn 1 |
Đẩy nhánh infra/cloudflare, thêm secret CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID trên Gitea | Đội hạ tầng | CI tự deploy Worker theo tag |
Khóa IAM chỉ đọc bucket statics.flyer.vn; R2 API token | Đội hạ tầng | Giai đoạn 2 |
| Bản xuất Cost Explorer 3 tháng theo Service | Kế toán / hạ tầng | Tính phần tiết kiệm |
CF_SHARE% khách: Next.js render trong Worker. Phần còn lại: chuyển nguyên request về AWS.IS_CLOUDFLARE của next.config.mjs và src/lib/cloudflare/; bản build cho pod không đổi.cf_side giữ mỗi khách ở một phía, để trang và file JS luôn cùng một bản build.cd apps/exam
pnpm install
pnpm cf:build # .env = .env.prod + .env.cloudflare → codegen → next build → OpenNext
pnpm cf:preview # chạy Worker trên máy (workerd), dữ liệu production
.env.cloudflare chỉ thay địa chỉ nội bộ cluster (exam-v2:4000, flyer-backend-rust:3000, student-api:8081) bằng https://api.flyer.us; các giá trị khác lấy từ .env.prod.
Tỉ lệ khách do Worker phục vụ là CF_SHARE trong wrangler.jsonc (môi trường production). Đổi tỉ lệ bằng cách sửa giá trị này và commit; lần deploy sau ghi đè giá trị đặt tay.
| Bước | Việc | Ghi chú |
|---|---|---|
| 0. CI | Gitea › flyer/webs › Settings: secret CLOUDFLARE_API_TOKEN, CLOUDFLARE_ACCOUNT_ID; biến CF_EXAM_PRODUCTION=true | Mỗi tag v*.*.* deploy cả pod lẫn Worker |
| 1. Bật 5% | pnpm cf:deploy --env production | Tạo route exam.flyer.us/*, login.flyer.us/*; không đổi DNS |
| 2. Theo dõi 1–2 ngày | Cloudflare › Workers › flyer-exam-web-production › Observability; Sentry | So lỗi 5xx và thời gian phản hồi với AWS |
| 3. Tăng dần | CF_SHARE 25 → 50 → 100 | Mỗi mức ít nhất 1 ngày |
| 4. Hoàn tất | 100% trong 1 tuần | Sau đó mới thu nhỏ exam-web trên EKS |
scripts/cloudflare-rollback.sh # CF_SHARE=0: mọi request về AWS sau vài giây
scripts/cloudflare-rollback.sh --remove # xoá Worker production và route
Sau khi chạy lệnh đầu, sửa CF_SHARE trong wrangler.jsonc cho khớp để lần deploy sau không bật lại.
Đăng nhập, cookie flyerId; Domain=flyer.us, /home, /check-point, /edit-profile, /history, /ranking và /api/tts hoạt động như bản trên AWS.
| Thời gian phản hồi (byte đầu tiên) | Cloudflare | AWS |
|---|---|---|
| Worker đang chạy | 0,2–0,6 giây | 0,2–0,25 giây |
| Khởi động lạnh | 1,5–3,5 giây | — |
/api/google/* dùng bản OAuth2 tối giản thay cho googleapis (20 MB).