
Ảnh và file đính kèm là thứ phình nhanh nhất trong một phần mềm quản trị, và cũng là thứ hay bị quyết định sau cùng. Cloudflare R2 là một lựa chọn tốt: lưu file dạng object storage, dùng được thư viện viết cho S3, và không tính phí băng thông tải ra — khác với nhiều nơi tính tiền theo lượt tải. Nhưng chọn chỗ lưu ảnh không tách rời khỏi hai câu hỏi còn lại: app chạy ở đâu, database nằm ở đâu.
R2 là gì, khác thư mục uploads chỗ nào
Trên một máy chủ thường, ảnh người dùng tải lên được ghi xuống một thư mục, ví dụ uploads/. Đơn giản, nhanh, và có nhược điểm: ảnh gắn chặt với cái máy đó. Máy hỏng là mất, muốn chạy hai máy cho nhẹ tải thì hai máy không thấy ảnh của nhau.
Object storage làm khác. Mỗi file là một "object" có khoá riêng, nằm trong kho tách rời khỏi máy chạy app. App cầm địa chỉ của file chứ không cầm ổ đĩa. Thêm máy, đổi máy, dựng lại app — ảnh vẫn nguyên chỗ cũ.
R2 là dịch vụ object storage của Cloudflare. Điểm tiện nhất cho người làm: nó tương thích API S3. Nghĩa là thư viện và công cụ bạn đã quen dùng với S3 phần lớn cắm vào R2 là chạy, không phải học lại từ đầu, và sau này muốn đổi sang nhà cung cấp khác cũng ít phải viết lại.

Điểm mạnh lớn nhất: không tính tiền băng thông tải ra
Với object storage, hoá đơn thường gồm ba phần: tiền dung lượng lưu, tiền số lượt thao tác, và tiền băng thông tải ra. Phần thứ ba là phần hay làm người ta giật mình — trang nào nhiều ảnh, nhiều lượt xem thì khoản này lớn dần theo lượng khách, rất khó đoán trước.
R2 bỏ hẳn phần băng thông tải ra. Bạn trả tiền dung lượng và thao tác, còn chuyện khách tải ảnh về bao nhiêu lần thì không tính thêm. Với một web nhiều hình — catalogue sản phẩm, thư viện ảnh công trình, trang tin — khác biệt này rõ.
R2 cũng có gói miễn phí theo dung lượng (khoảng 10 GB — con số tham khảo, nên kiểm lại trang giá chính thức vì các nền tảng này đổi gói thường xuyên). Phần lớn phần mềm quản trị nội bộ của doanh nghiệp nhỏ chạy vài năm vẫn chưa chạm trần đó.
R2 không làm thay những việc này
Đừng nhầm R2 với một bộ xử lý ảnh. Nó chỉ cất file và trả file ra.
- Đổi cỡ ảnh, nén, tạo thumbnail, đóng watermark — R2 không làm. Cloudflare có dịch vụ riêng tên Images cho việc xử lý và đổi cỡ ảnh, và Stream cho video. Cả hai là dịch vụ trả phí tách biệt, không nằm trong R2.
- Nếu app chạy trên Cloudflare Workers, bạn gần như buộc phải dùng R2. Workers không có ổ đĩa lâu dài, nên không có "thư mục uploads" để ghi vào.
- Thư viện xử lý ảnh native không chạy trên Workers.
sharp— thư viện phổ biến nhất để nén và đổi cỡ ảnh trong hệ Node — không dùng được ở đó. App cần xử lý ảnh mà lại đặt trên Workers thì phải tìm đường khác ngay từ lúc thiết kế, chứ không sửa được lúc sắp xong.
Ba quyết định phải chốt cùng lúc
Nhiều người hỏi riêng lẻ: "ảnh nên để đâu?". Nhưng câu trả lời phụ thuộc vào hai thứ khác. Một bộ hạ tầng web app gồm ba chỗ đặt: app chạy ở đâu, database nằm ở đâu, ảnh và file ở đâu. Ba thứ này ăn vào nhau.
Web nhỏ: landing page, blog, trang giới thiệu
App đặt thẳng trên Cloudflare, dữ liệu dùng D1 (database SQLite dạng serverless của Cloudflare), ảnh để R2. Gần như không tốn tiền, không có máy chủ nào để nuôi, không có đêm nào phải lo ổ cứng đầy.
Loại này dữ liệu ít, nghiệp vụ đơn giản, chủ yếu là đọc. D1 thừa sức.
App vừa: có đăng nhập, có nghiệp vụ, dữ liệu tăng đều
Frontend đặt trên Cloudflare, database dùng Postgres managed — kiểu Neon hoặc Supabase — hoặc Postgres tự dựng trên VPS, ảnh vẫn để R2.
Lý do tách database ra: tới mức này bạn cần quan hệ nhiều bảng, transaction, truy vấn báo cáo — Postgres đầy đủ làm tốt hơn hẳn. "Managed" nghĩa là nhà cung cấp lo sao lưu, vá lỗi, mở rộng.
Phần mềm quản trị nhiều nghiệp vụ
Nhân sự, kho, bán hàng, kế toán — có upload chứng từ, xuất Excel, job chạy nền, có khi gọi AI. Đặt app và Postgres cùng trên VPS, triển khai bằng Dokploy cho gọn. Ảnh để ổ đĩa VPS hoặc đẩy sang R2 đều được. Cloudflare đứng trước làm cổng: DNS, CDN, chống DDoS, SSL.
Khi nào chọn ổ đĩa VPS? Ảnh ít, chỉ nhân viên nội bộ xem, muốn đơn giản — đổi lại bạn tự lo sao lưu và để mắt tới dung lượng trống. Ảnh nhiều, khách bên ngoài xem, hoặc tính chạy nhiều máy sau này thì R2 đáng hơn.

Bảng chọn theo quy mô
| Quy mô | App chạy ở đâu | Database | Ảnh và file |
|---|---|---|---|
| Landing page, blog, web giới thiệu | Cloudflare | D1 | R2 |
| Công cụ nhỏ: form, tra cứu, chấm công đơn giản | Cloudflare | D1 | R2 |
| App vừa, có nghiệp vụ và đăng nhập | Cloudflare (frontend) | Postgres managed hoặc trên VPS | R2 |
| Phần mềm quản trị nhiều nghiệp vụ | VPS (Dokploy) | Postgres trên VPS | Ổ đĩa VPS hoặc R2 |
Bảng này là điểm khởi đầu, không phải luật. Bài trước đã so sánh kỹ hơn chuyện chọn Cloudflare hay VPS để chạy app.
5F Edu đang làm thế nào
Nói cho cụ thể, tránh lý thuyết suông. Chính 5fedu.com chạy Next.js và PostgreSQL trên VPS bằng Dokploy, ảnh lưu ở ổ đĩa (volume) của máy chủ. Chọn vậy vì site có job chạy nền và xử lý ảnh — hai thứ vướng ngay nếu đặt lên Workers.
Đổi lại, phần sao lưu là việc của chúng tôi, không ai làm thay. Đó chính là cái giá của việc tự chủ.
Phần ai cũng gật đầu rồi quên: sao lưu
Dù bạn chọn tổ hợp nào, có một thứ không được bỏ: sao lưu database và ảnh ra một nơi khác.
"Nơi khác" nghĩa là khác máy, khác nhà cung cấp thì càng tốt. Backup nằm cùng ổ đĩa với dữ liệu gốc thì khi máy hỏng là mất cả hai. Và đây là điểm hay bị sót nhất: rất nhiều người sao lưu database đều đặn nhưng quên mất thư mục ảnh. Khôi phục xong thì bảng dữ liệu đầy đủ còn chứng từ scan thì trắng trơn.
Mỗi vài tháng nên thử khôi phục bản sao lưu ra một chỗ tạm. Bản backup chưa từng khôi phục thử thì chưa gọi là backup.

Dữ liệu cá nhân của khách hàng
Nếu app lưu hồ sơ nhân sự, hồ sơ bệnh án, thông tin học viên hay dữ liệu khách hàng, chỗ đặt dữ liệu không còn là chuyện kỹ thuật thuần tuý.
Bạn cần trả lời rõ ba câu: dữ liệu nằm ở đâu, ai truy cập được, bản sao lưu để chỗ nào. Quy định bảo vệ dữ liệu cá nhân ở Việt Nam là thứ nên xem trước khi chọn hạ tầng, chứ không phải xem sau khi đã chạy được nửa năm — lúc đó đổi rất tốn.
Nếu bạn đang phân vân nên đặt app, database và ảnh ở đâu cho phần mềm của mình, 5F Edu nhận tư vấn và làm web app quản trị theo nghiệp vụ thực tế.
Câu hỏi thường gặp
›R2 có thay được thư mục uploads trên máy chủ không?
Có, và trong nhiều trường hợp còn tốt hơn vì ảnh không dính vào một máy cụ thể. Nhưng app phải sửa code: thay vì ghi file xuống đĩa thì gọi API để đẩy lên R2 và lưu lại khoá của file.
›Dùng R2 có bị tính tiền khi khách xem ảnh nhiều không?
R2 không tính phí băng thông tải ra, nên lượt xem tăng không làm phần đó tăng. Bạn vẫn trả tiền dung lượng lưu và số lượt thao tác. Mức giá cụ thể nên kiểm lại trang chính thức của Cloudflare.
›App trên Cloudflare Workers có nén ảnh được không?
Không nén bằng thư viện native như `sharp`. Workers không chạy được loại thư viện đó. Phương án là dùng Cloudflare Images — dịch vụ trả phí riêng — hoặc xử lý ảnh ở một nơi khác rồi mới đẩy vào R2.
›Database nên dùng D1 hay Postgres?
App nhỏ, ít bảng, chủ yếu đọc thì D1 đủ và rất đỡ công. Nghiệp vụ nhiều bảng, nhiều transaction, báo cáo phức tạp thì Postgres hơn hẳn — dù đặt trên VPS hay dùng dịch vụ managed.
›Ảnh để trên VPS có an toàn không?
An toàn hay không nằm ở chỗ bạn có sao lưu ra nơi khác hay không, chứ không nằm ở việc để trên VPS. Ảnh ở ổ đĩa VPS mà không có bản sao nào bên ngoài thì một lần hỏng ổ là mất sạch.
Tác giả
Chuyên gia chuyển đổi số · Đại diện 5F Edu
Hơn 8 năm triển khai và tư vấn chuyển đổi số cho doanh nghiệp vừa và nhỏ: chuẩn hoá quy trình, xây phần mềm quản lý bằng AppSheet và web app, tự động hoá bằng N8N. Người làm kênh YouTube Nghiện AppSheet.



