Skip to content

Rà chi phí hạ tầng ​

Cách rà: skill /cost-audit (.claude/skills/cost-audit/SKILL.md, nằm ngoài gốc VitePress nên ghi bằng đường dẫn chứ không bằng link). Trang này chỉ giữ số đo, để mỗi đợt sau là một phép trừ chứ không phải một cuộc điều tra lại từ đầu.

Vì sao trang này tồn tại ​

Tài khoản Cloudflare dac2205@gmail.com và tài khoản GitHub cùng tên nuôi chung 13 dự án, trong đó Nemo12 là dự án duy nhất còn đang phát triển. 12 dự án còn lại đã ngừng nhưng worker, cron và database của chúng vẫn chạy. Không có trang này thì mỗi lần hoá đơn tăng, việc đầu tiên người ta làm là mở ci.yml của Nemo12 ra tối ưu — tức là bào 30 giây khỏi khoản $9 trong khi khoản $144 nằm ở chỗ khác.

Đợt 2026-09-16 (đợt đầu, SRC-745) ​

Tổng ​

Cả tài khoảnPhần Nemo12
Cloudflare, dự phóng chu kỳ 3/9 - 2/10$232.24~$5
Cloudflare, đã dùng tới 16/9 (14/30 ngày)$108.38
GitHub Actions, tháng 9$33.20$9.26

Cloudflare — chỉ 4 khoản vượt hạn mức, 3 trong số đó là D1 ​

KhoảnĐã dùngTính tiềnTiền
D1 dòng đọc (gồm sẵn 25 tỷ)91,96 tỷ66,96 tỷ$66.96
Workers AI neuron, tên hiển thị "Regular Twitch Neurons"3,17M2,86M$31.42
D1 dòng ghi (gồm sẵn 50 triệu)59,78M9,78M$10.00
Tất cả phần còn lạitrong hạn mức0$0.00

"Tất cả phần còn lại" gồm: Workers request (578k/10M), Workers CPU (8,84M/30M ms), R2 dung lượng (0,29/10 GB) và mọi thao tác R2, KV, Queues, Durable Objects, Vectorize, Email, Images, Worker Build Minutes. Không có gì để tiết kiệm ở đó — đừng tốn thời gian.

Đã thi hành 16/9: tắt 2 cron Workflow trên chuyenchon-mori-quality ​

WorkflowCronTình trạng trước khi tắt
mori-learning-experience-quality-v2*/3 * * * *5.696 lượt xong, 8.704 lượt lỗi
mori-quality-continuous-audit17 * * * *4/4 lượt gần nhất đều lỗi

Tắt bằng dashboard: Workflows → workflow → Settings → Schedules → xoá lịch. Lùi lại được bằng nút "+ Add" ngay chỗ đó (hộp thoại xác nhận của Cloudflare cũng ghi "You can add it again at any time"). Không xoá worker, không xoá database, không đụng 10 workflow mori còn lại (chúng đã nằm im từ 15-17/8, lượt cuối đều do binding chứ không phải cron).

Xác nhận bằng API sau khi xoá: lượt cron cuối cùng là 02:30 UTC; hai mốc kế tiếp (02:33, 02:36) không sinh instance nào. wrangler tail cũng bắt đúng hai lượt cuối 02:27 và 02:30 rồi im.

Đã tắt tiếp 3 cron Workflow chuyenchon (16/9, đợt hai) ​

Bước quét Workflows mới thêm vào cost-audit.mjs tìm ra ba cái nữa mà cách kiểm cũ bỏ sót sạch. Chủ dự án quyết tắt cả ba sau khi đã nghe lưu ý ở dưới.

WorkflowWorkerCron cũ (để bật lại)Lượt/tháng
chuyenchon-update-reviewchuyenchon-admin-service*/15 * * * *2.880
chuyenchon-learning-integritychuyenchon-admin-service7 * * * *720
chuyenchon-school-refreshchuyenchon-school-data0 0,3,5,7,10,12,15,17,19,22 * * *300

Khác mori ở một điểm quan trọng: ba cái này đang chạy THÀNH CÔNG, không phải hỏng. Lưu ý đã nêu trước khi tắt: chúng thuộc chuyenchon-admin-service và chuyenchon-school-data, có thể còn phục vụ site chuyenchon đang chạy — nên nếu có gì đó ở chuyenchon ngừng tự cập nhật, đây là chỗ nhìn đầu tiên. Bảng cron ở trên đủ để dựng lại nguyên trạng bằng nút "+ Add".

Chúng không đọc mori-learning-library nên không nằm trong khoản $144; phần tiết kiệm nằm ở Workers AI và CPU, chưa đo tách được.

Hai dấu hiệu khác trong danh sách truy vấn đắt ​

Truy vấnSố đoNghĩa là
UPDATE quality_runs SET status='failed', error_message='Workflow lease expired' ...47.466 lần/30 ngàyWorkflow hết hạn lease liên tục. Khớp với 8.704 lượt lỗi ở trên: nó hỏng suốt nhưng vẫn chạy lại mỗi 3 phút.
DELETE FROM quality_assurance_findings WHERE rowid<=...234.750.001 dòng trong MỘT lần, hai lần như vậyCó người từng thử dọn bảng bằng tay và mỗi lệnh ngốn ~235 triệu dòng đọc.

Xác nhận cả 5 cron đã ngừng (03:19 UTC 16/9) ​

Cách kiểm: đợi qua ít nhất một mốc cron rồi hỏi API instance. Không lượt nào được sinh thêm.

WorkflowLượt cuốiMốc đáng lẽ đã chạy
mori-learning-experience-quality-v202:3002:33 → 03:06, 13 mốc
mori-quality-continuous-audit02:1703:17
chuyenchon-update-review02:3002:45, 03:00, 03:15
chuyenchon-learning-integrity02:0703:07
chuyenchon-school-refresh00:0003:00

Dòng đọc D1 của mori-learning-library ngay sau đó:

text
12/9  10,24 tỷ   5.741 truy vấn
13/9  11,07 tỷ   5.642
14/9  11,88 tỷ   5.535
15/9  13,06 tỷ   5.600      ← ngày cuối còn cron
16/9   1,50 tỷ     634      ← cron tắt lúc 02:30, số này là của 2,5 giờ đầu ngày

Con số 16/9 mới là phần tích trước khi tắt, chưa phải bằng chứng đủ. Đợt kiểm sau phải nhìn ngày 17/9: nếu đúng thì nó phải gần 0. Ghi lại đây để lần sau không tự khen sớm.

Thủ phạm: MỘT worker, chuyenchon-mori-quality ​

Bản đầu của trang này (16/9, sáng) ghi "7 worker chuyenchon-mori-*, tắt cron là xong". Sai ở cả hai vế và sai theo kiểu dễ lặp lại, nên ghi rõ lại đây: lúc đó tôi trộn danh sách "worker có binding tới D1 mori" với danh sách "worker có cron trigger". Hai tập đó rời nhau — không worker mori nào có cron. Bài học: hai truy vấn khác nhau cho ra hai danh sách khác nhau, đừng nối chúng bằng trí nhớ.

Đo lại 16/9 với 7 ngày gần nhất, chỉ một trong 7 worker thật sự chạy:

WorkerRequest 7 ngàyGhi chú
chuyenchon-mori-quality3.7362.671 thành công, 1.023 ném exception (27%), 42 rớt
6 worker mori còn lại0không một lượt nào

chuyenchon-mori-quality nhận đều đặn ~520 lượt/ngày (dao động 486-558 suốt hai tuần). Đều như vậy là máy gọi, không phải người dùng. Mỗi lượt sinh ~11 truy vấn D1, mỗi truy vấn quét ~2,3 triệu dòng.

Nó không có route, không có custom domain, và không worker nào service-binding tới nó.

Về cron thì tôi đã kết luận sai lần thứ hai, và đây là bài học đắt nhất của đợt rà: API workers/scripts/<name>/schedules báo "không có cron", nhưng thật ra có hai Cloudflare Workflow chạy theo cron trên chính worker này. Worker cron trigger và Workflow cron là hai hệ thống khác nhau, hỏi một bên không trả lời được cho bên kia. Chỉ wrangler tail mới lộ ra:

json
"tailAttributes": { "workflowName": "mori-learning-experience-quality-v2",
                    "instanceId": "*/3 * * * *-1789525620000" }

instanceId của một lượt cron mang chính biểu thức cron ở đầu — đó là cách đọc được lịch khi API schedules của Workflows chưa mở. scripts/cost-audit.mjs nay hỏi cả Workflows, không chỉ Worker.

Nguyên nhân gốc: một khoá ngoại thiếu index ​

Truy vấn đắt nhất trên mori-learning-library, đo 3 ngày: 36,96 tỷ dòng đọc / 4.671 lần = 7,9 triệu dòng cho MỘT câu lệnh ghi. Mọi truy vấn còn lại cộng lại chỉ ~40 triệu dòng.

sql
INSERT OR REPLACE INTO quality_loop_runs(id,run_id,loop_code,phase,status,started_at) VALUES(...)

Vì sao một câu INSERT lại ĐỌC 7,9 triệu dòng: INSERT OR REPLACE gặp xung đột trên UNIQUE(run_id,loop_code,phase) thì xoá dòng cũ trước khi chèn. Bảng con quality_artifact_test_results khai loop_run_id ... REFERENCES quality_loop_runs(id) ON DELETE CASCADE mà không có index trên chính cột loop_run_id — nên mỗi lần xoá, SQLite phải quét toàn bộ 8.284.000 dòng của bảng con để tìm dòng cần xoá theo.

Đây cũng là lời giải cho nhịp tăng tuyến tính ở dưới: bảng con lớn thêm ~640.000 dòng mỗi ngày, nên mỗi lần quét đắt thêm đúng chừng ấy.

Nếu sau này cần bật lại dự án mori, cách sửa là một dòng, không phải tắt:

sql
CREATE INDEX IF NOT EXISTS idx_qa_tests_loop_run ON quality_artifact_test_results(loop_run_id);

Luật rút ra, áp cho cả Nemo12: mọi cột khoá ngoại có ON DELETE CASCADE phải có index trên chính nó. Thiếu index ở đó không làm chậm lúc đọc, nó làm chậm lúc GHI, và hoá đơn D1 tính theo dòng đọc nên cái giá hiện ra ở một chỗ không ai nghĩ tới.

Dòng đọc đang TĂNG TUYẾN TÍNH, không đứng yên ​

Đây là chỗ nguy hiểm mà bản đầu bỏ sót. Dòng đọc mỗi ngày của mori-learning-library:

text
17-21/8   14 → 16 tỷ/ngày   (đang leo)
22/8      0,72 tỷ            ← có gì đó reset
23/8-2/9  0,03 tỷ/ngày       (phẳng, ~12.000 truy vấn/ngày)
3/9       1,64 tỷ            ← bắt đầu leo lại
4-15/9    1,6 → 13,06 tỷ/ngày (tăng đều ~1 tỷ mỗi ngày)

Số truy vấn mỗi ngày gần như không đổi (~5.600), nhưng số dòng đọc mỗi truy vấn tăng đều — tức bảng bị quét đang lớn dần và truy vấn không có index. Đây không phải một khoản cố định $144/tháng: theo nhịp 15/9 (13 tỷ/ngày) thì riêng database này đã là ~390 tỷ dòng/tháng ≈ $365/tháng và tháng sau còn cao hơn.

Cron của dự án đã ngừng: 60.480 lượt/tháng ​

WorkerCronLượt/tháng
chuyenchon-public-emdash* * * * *43.200
duhoc27-ai-production*/5 * * * *8.640
capos-api*/15 * * * *2.880
chuyenchon-diagnosis-quality*/15 * * * *2.880
api-conan-school4 biểu thức1.110
eduone-api, chuyenchon-ebook-quality, chuyenchon-api-gateway, heart150-api1.770

Bản thân request thì rẻ, nhưng chính các cron này là thứ kéo theo dòng D1 và neuron AI ở trên. duhoc27-ai-production gọi model AI 8.640 lần một tháng cho một dự án không còn ai dùng.

Quy mô tài khoản ​

78 worker (15 của Nemo12) · 20 D1, 7,83 GB (3 của Nemo12, 88,7 MB) · 10 R2 bucket, 0,78 GB (1 của Nemo12) · 7 KV namespace · 10 Pages project (0 của Nemo12).

Workers traffic 30 ngày: 732.622 request, 93% thuộc dự án đã ngừng. Hai worker dẫn đầu đều là đồ cũ: conan-www-stale-asset-bridge 246k và api-conan-school 244k.

GitHub Actions theo repo, tháng 9 ​

RepoTiền
conanplatform$19.97
nemo12.com$9.26
conan1$2.90
sutucon.com$0.82
còn lại$0.25

Trong repo nemo12.com: 100 lượt gần nhất tốn 352 phút, ~96 phút (27%) cháy vào lượt đỏ hoặc bị huỷ. ci.yml đã được tối ưu hai đợt (gộp 12 workflow thành 1 job ngày 23/8; cache node_modules cắt ~280s mỗi lượt ngày 4/9) nên phần còn lại nằm ở kỷ luật commit, không nằm ở YAML.

Đề xuất, xếp theo tiền ​

#ViệcCắt đượcRủi ro
1Tắt URL workers.dev của chuyenchon-mori-quality~$144/tháng và đang tăngLùi lại được bằng một lệnh; nhưng có nguồn ngoài đang gọi nó 520 lượt/ngày mà ta chưa biết là ai
2Tắt cron duhoc27-ai-production và các cron dự án cũ còn lạiphần lớn $67 AILùi lại được
3Sau một chu kỳ sạch: xoá worker + D1 của dự án đã ngừng~$2 dung lượngKhông lùi được, phải export trước
4Rà repo conanplatformtới $20/thángNgoài phạm vi repo này
5Chạy cổng ở máy trước khi push~$2,5/thángKhông

Việc 1 và 2 cắt khoảng $210 trong hoá đơn $232, và không đụng gì tới Nemo12.

Việc 1 gọn hơn nhiều so với bản đầu: chỉ cần chạm một worker, và worker đó không có cron, không route, không domain, không ai binding tới. Rủi ro duy nhất là nguồn ngoài đang gọi nó — phải biết đó là gì trước khi tắt.

bash
# tắt (lùi lại được: đổi enabled thành true là bật lại)
curl -X POST -H "Authorization: Bearer $TOKEN" \
  "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT/workers/scripts/chuyenchon-mori-quality/subdomain" \
  -H 'Content-Type: application/json' -d '{"enabled":false}'

Việc 1 đã thi hành 16/9/2026 (xem đầu mục này). Việc 2-5 đang chờ chủ dự án xác nhận từng cụm dự án. Đợt rà sau phải kiểm lại: dòng đọc D1 của mori-learning-library có về gần 0 không.

Đợt 2026-09-27 — render video làm cạn hạn mức Actions (SRC-1076) ​

Sự việc. Ngày 26.09.2026, CI của toàn kho chết từ 07:57: mọi workflow, mọi nhánh, đều startup_failure với 0 job được cấp. Không file nào trong .github/ đổi, YAML hợp lệ, Actions vẫn enabled. Nguyên nhân là hạn mức Actions của tài khoản đã cạn.

Số đo. 8 lượt render-videos trong 10 tiếng:

Tổng thời gian216 phút
Lượt render74
Video khác nhau38
Tức là dựng lại thứ y nguyên~110 phút, một nửa
Mỗi video~2 phút 55
Kho kịch bản71 → một lượt dựng trọn bộ ≈ 3,5 giờ
Gói free, repo private2.000 phút/tháng

Một lượt dựng trọn bộ ăn hơn 10% ngân sách tháng. Hai lượt lặp như hôm ấy ăn thêm chừng ấy nữa.

Vì sao đắt về bản chất. Remotion dựng video bằng cách mở Chromium rồi vẽ từng khung hình. Ở 1920×1080 và 30 fps, một video 90 giây là 2.700 khung, chạy trên runner 2 vCPU. Không có mẹo nào làm việc ấy rẻ đi mười lần — chỉ có cách làm nó ít lần hơn và nhẹ hơn mỗi lần.

Bốn thay đổi (chủ dự án chốt 27.09.2026).

#Thay đổiCắt được
1Bỏ qua video có vân tay không đổi (media_videos.script_hash, migration 0300)~50%
2Ảnh bìa cắt từ mp4 bằng ffmpeg thay cho remotion still~40 giây/video
3Bundle một lần cho cả mẻ thay vì mỗi video một lượtvài phút mỗi mẻ
4Đầu ra 720p (--scale, giữ khung thiết kế 1920×1080)gần một nửa công vẽ

Ba cái đầu không đổi một điểm ảnh nào. Cái thứ tư đổi độ phân giải đầu ra, giữ nguyên bố cục.

Vân tay gồm kịch bản VÀ mã dựng hình. Thiếu vế thứ hai thì một lượt sửa giao diện video sẽ không dựng lại gì cả, và kho video đứng im trong khi mã đã đổi — hỏng theo hướng im lặng nhất. Hệ quả phải chấp nhận: sửa một dòng trong tools/videos/src/ là dựng lại cả kho, nên hãy gộp các lượt sửa giao diện lại.

Nguyên nhân THẬT không phải phút Actions — là dung lượng artifact.

Nâng hạn mức phút hai lần đều không gỡ được CI. Thứ chặn nằm ở chỗ khác:

Artifact videos còn sống22 cái, 1.168,9 MB
Gói free cho lưu trữ dùng chung500 MB

Bước upload-artifact giữ mọi mp4 14 ngày, mỗi lượt 50–65 MB, 8 lượt trong hai ngày.

Vượt hạn mức LƯU TRỮ chặn Actions y như vượt hạn mức PHÚT, và biểu hiện giống hệt: mọi workflow, mọi nhánh, startup_failure với 0 job và không log. Đây là chỗ chẩn đoán dễ sai nhất — triệu chứng chỉ nói "không khởi động được", không nói vì sao, và bản năng đầu tiên là nghĩ tới phút.

Cách phân biệt: đọc repos/{owner}/{repo}/actions/artifacts và cộng size_in_bytes của những cái expired == false. Lượt rà 27.09 mất nửa ngày mới nghĩ tới đó.

Đã xoá 22 artifact ấy (1.169 MB → 0). Không mất gì: mp4 đã nằm trên R2 và phát được qua /v1/public/videos/{id} — artifact chỉ là bản chép để xem trước.

Và sửa cho khỏi tái diễn: artifact chỉ giữ khi upload=false (lượt render thử), retention 14 ngày → 3 ngày. Lượt đã đưa lên R2 thì không cần bản chép thứ hai.

Điều đáng nhớ hơn con số. render-videos chưa bao giờ chạy tự động — nó chỉ có workflow_dispatch. Thứ làm cạn ngân sách là các phiên bấm nó nhiều lần, không phải một cái cron bỏ quên. Nên chỗ vá đúng là ở luật và ở cổng máy kiểm, không phải ở lịch chạy.

Đợt 2026-09-29 (SRC-1127) ​

Chủ dự án: "rà soát tiền trên Cloudflare để giảm hẳn số tiền cần trả", và "CI hầu như không tốn đồng nào".

Cloudflare, trang Billable usage (chu kỳ 03.09 - 02.10): đã dùng $119.70, dự phóng $133.00 (đợt 16.09 dự phóng $232.24), trung bình $4.43/ngày.

KhoảnDùngVượt hạn mứcTiền
D1 dòng đọc94,11 tỷ69,11 tỷ$69.11
Workers AI (RTN)3,84 triệu3,53 triệu$38.84
D1 dòng ghi60,72 triệu10,72 triệu$11.00
D1 dung lượng5,64 GB-tháng1 GB-tháng$0.75
Mọi khoản kháctrong hạn mức0$0.00

Ai gây ra (node scripts/cost-audit.mjs, 30 ngày):

NguồnSố đoƯớc tiền/thángDự án
D1 mori-learning-library92,9 tỷ dòng đọc (98,2%), 59 triệu dòng ghi~$68 + ~$9mori (đã ngừng)
Workers AI deepseek-v4-pro4,04 triệu neuron~$44không phải Nemo12 (Nemo12 không gọi model này)
Workers AI llama-3.3-70b3,02 triệu neuron~$33Nemo12: cron Foundry tự sinh bài
D1 nemo12-platform0,62 tỷ dòng đọc (0,7%)~$0Nemo12

Nguồn đọc của mori: workflow mori-learning-experience-quality-v2 (*/3 * * * *, 14.400 lượt/tháng) trên worker chuyenchon-mori-quality; câu INSERT OR REPLACE INTO quality_loop_runs đọc ~4,77 triệu dòng mỗi lần (19.009 lần = 90,7 tỷ dòng).

Đã làm (phần của Nemo12, không cần hỏi):

  • Tắt cron Foundry (FOUNDRY_AUTO_DRAIN "1" → "0"): nó được bật cho đợt 1 từ 28.08 với ghi chú "xong đợt thì đổi về 0" nhưng bị để bật suốt một tháng. Cắt ~$33/tháng Workers AI. Sinh bài vẫn chạy tay được.
  • CI một job cho mỗi loại test: test API 3 phần → 1, e2e 5 phần → 1. Một lượt PR đụng cả learn và API từ 11 job xuống 5; GitHub làm tròn từng job lên phút và mỗi job cài lại node_modules. Đổi lại chậm hơn vài phút mỗi lượt. 100 lượt gần nhất: 281 phút, ~31 phút cháy vào lượt đỏ hoặc bị huỷ.

Chờ chủ dự án (không tự làm, luật skill /cost-audit §4): tắt cron rồi mới xoá, hỏi từng cụm. Cụm đáng nhất là mori/chuyenchon: tắt workflow mori-learning-experience-quality-v2 cắt ~$77/tháng D1 ngay lập tức. Nguồn gọi deepseek-v4-pro (~$44) cần tra thêm trong dashboard Workers AI / AI Gateway theo từng worker. Sau khi tắt cả hai, hoá đơn Cloudflare dự kiến về gần mức sàn $5 của gói Workers Paid.

Đo lại cùng ngày, theo NGÀY chứ không theo 30 ngày (GraphQL, từ 20.09): con số 30 ngày ở trên phần lớn là quá khứ.

  • Workflow mori-learning-experience-quality-v2 đã ngừng từ 16.09.2026 02:30 (lần kích hoạt cuối, API Workflows); không còn cron nào của nó để tắt. D1 cả tài khoản nay chỉ ~50 triệu dòng đọc/ngày (~1,5 tỷ/tháng, dưới hạn mức 25 tỷ): D1 dòng đọc chu kỳ tới ≈ $0.
  • deepseek-v4-pro còn lác đác (68 nghìn neuron trong 9 ngày, ~$0,7). Không thuộc Nemo12: Foundry gọi DeepSeek qua nhà cung cấp riêng (deepseek/deepseek-chat), không qua Workers AI.
  • Workers AI 9 ngày: Llama 70B 288 nghìn (Foundry, nay đã tắt), Aura-2 122 nghìn (giọng đọc), deepseek 68 nghìn.
  • Dự phóng chu kỳ tới (03.10 - 02.11): ~$10, gồm sàn $5, Workers AI ~$4, D1 dung lượng ~$2,5 (7,8 GB của mori-learning-library; xoá db ấy là việc không lùi lại được, cần chủ dự án quyết và sao lưu trước).

GitHub (trang Billing, tháng 9 tới 29.09): $77,12 gộp, trừ $12,80 miễn phí; ngân sách Actions đã dùng 100%. Theo repo: nemo12.com $49,95, conanplatform $22,80, conan1 $3,01, sutucon.com $0,82, duhoc27.com $0,17. Đã tắt GitHub Actions của conanplatform (chủ dự án đồng ý 29.09.2026; bật lại bằng một nút trong Settings). Phần của nemo12.com chủ yếu là lượt render video (26-27.09) và CI chia nhiều job (đã gộp ở PR SRC-1127). Nếu muốn Actions gần như $0 hẳn: repo công khai thì phút Actions miễn phí, nhưng đó là quyết định của chủ dự án.