Blog

Vì sao render PDF tại Edge quan trọng khi vượt 10K invoice mỗi ngày

Cold start, độ trễ theo vùng và compute mỗi trang đổi hình khi volume vượt một ngưỡng. Góc nhìn thực tế về lúc Edge rendering không còn là ý tưởng hay, mà bắt đầu tự trả tiền cho nó.

Nếu bạn render vài trăm PDF mỗi ngày trên một backend Lambda hoặc một Kubernetes pod nhỏ, kiến trúc không thật sự quan trọng. Cách nào cũng chạy được. Cách nào cũng đủ nhanh.

Mọi thứ đổi khi scale. Khi bạn emit hàng chục nghìn tài liệu mỗi ngày, tức gần như mọi nền tảng ecommerce, carrier logistics, BNPL service, payroll provider hoặc invoicing platform có traction vừa phải, ba con số bắt đầu gây đau:

  1. Cold-start latency, vì ở đâu đó luôn có thứ đang cold.
  2. Regional latency, vì khách hàng của bạn không ở cạnh origin.
  3. Compute mỗi lần render, vì bạn trả nó hàng chục nghìn lần mỗi ngày.

Bài này đi qua cách từng con số đổi hình sau khoảng 10K render/ngày, và vì sao renderer deploy tại Edge như gPdf về bản chất là một loại giải pháp khác, không phải “cùng thứ đó nhưng nhanh hơn”.

1. Thuế cold-start cộng dồn theo concurrency

Cold start không chỉ là phiền phức; nó là hàm của concurrency curve. Kịch bản thường diễn ra như sau:

  • Bạn provision N=10 warm containers theo traffic trung bình.
  • Một spike 3x ập tới: Black Friday, ngày trả lương, cuối quý.
  • 20 container mới cold-start để hấp thụ spike. Mỗi container mất 1,5-2,5 giây để boot Chromium / Prince / runtime của bạn.
  • Trong 30 giây đó, các container mới phục vụ ở p99 = 2 giây, kéo p99 toàn cục lên theo.
  • Timeout budget downstream của bạn, có lẽ 5-10 giây cho toàn bộ order pipeline, giờ bị PDF generation ăn mất.

Điều này ổn khi traffic phẳng. Nó rất tệ khi traffic có spike, mà traffic PDF thì luôn có spike: invoice bắn ở ranh giới billing cycle, label bắn khi carrier pickup, statement bắn cuối tháng.

Phương án Edge-deployed: Cloudflare Worker isolate cold-start trong 5-20 ms, không phải 1,5-2,5 giây. Không có container để spin, không có JVM/V8 lớn để khởi tạo, không có browser để bootstrap; WASM module load vào một process vốn đã sống. Cold-start không còn là thứ bạn phải thiết kế kiến trúc quanh nó.

Riêng với gPdf, worst cold start quan sát được trong benchmark của chúng tôi khoảng 12 ms, và chỉ ở request đầu tiên tới isolate mới được gán. Các request sau trên cùng isolate bỏ qua cả phần đó.

2. Regional latency là thật, kể cả với request “nhanh”

Round-trip từ Sydney tới origin us-east-1 là 200 ms trước khi code của bạn làm bất kỳ việc gì. Từ São Paulo tới eu-west-1 khoảng 190 ms. Từ Mumbai tới us-east khoảng 220 ms.

Đó là mỗi chiều. Vì vậy một PDF API tập trung render phía server 300 ms, từ góc nhìn khách hàng ở Sydney, sẽ trông như sau:

client → us-east  : 200 ms
us-east render    : 300 ms
us-east → client  : 200 ms
total wall-clock  : 700 ms

Với flow tương tác như “preview invoice trước khi gửi”, điều đó khó chịu. Với backend job volume cao, nó có thể không đáng chú ý.

Phương án Edge-deployed: Cloudflare chạy ở hơn 300 thành phố. Colo gần nhất với khách hàng Sydney của bạn cách khoảng 5 ms. Cùng render đó trở thành:

client → SYD colo : 5 ms
SYD render        : 4 ms
SYD → client      : 5 ms
total wall-clock  : 14 ms

Đó là cải thiện 50 lần cho flow tương tác. Với backend job, lợi ích có thể hòa vốn, nhưng preview PDF tương tác như “cho tôi xem trước khi gửi” trở thành mượt thay vì giật.

Lợi ích bậc hai bị ẩn: nếu PDF API chạy tại Edge, bạn có thể đưa logic lân cận tới đó luôn: preview PDF ở checkout, rate-limit, auth check. Mỗi phần đẩy ra Edge loại bỏ một round trip khỏi hot path.

3. Compute mỗi lần render là hóa đơn âm thầm cộng dồn

Phép tính Lambda ở 100K render/ngày:

  • Puppeteer khoảng 600 ms wall, 1024 MB memory: khoảng 240 USD/tháng chỉ cho compute, chưa tính egress.
  • DocRaptor ở tier 89 USD/100K trang: khoảng 2.670 USD/tháng ở 100K/ngày (= 3M/tháng).
  • gPdf ở tier 5 USD/100K trang: khoảng 150 USD/tháng ở 100K/ngày. Hoặc khoảng 5 USD/tháng nếu bạn đúng ở 100K/tháng.

Khoảng cách chi phí không biến mất khi bạn scale; nó rộng ra. Ở 1M render/ngày:

  • Hạ tầng Puppeteer: khoảng 2.400 USD/tháng + ops + on-call
  • DocRaptor: khoảng 26.700 USD/tháng
  • gPdf: 1.500 USD/tháng flat, giả sử bạn đàm phán volume trên public price grid

Phản ứng phổ biến: “Chắc trong thực tế tiết kiệm nhỏ hơn, phải có gì ẩn.” Theo kinh nghiệm của chúng tôi, không. Driver chi phí trong PDF generation là compute footprint của renderer. Khi bạn đổi một process Chromium 600 MB lấy một WASM module 4 MB, chi phí mỗi lần render giảm khoảng 100 lần, và hóa đơn đi theo.

Lý do mô hình này vẫn bền cho chúng tôi: giá nền của Cloudflare Workers Bundled khoảng 0,50 USD cho 1 triệu request. Với renderer dùng khoảng 1,5 ms CPU mỗi call, cost-of-goods-sold mỗi render thật sự dưới cent. Chúng tôi markup vừa phải để thành một business bền vững, và bạn vẫn thấy khoảng cách 18 lần.

“Edge-deployed” thật sự mua cho bạn gì

Ba thứ, không thứ nào là slide marketing.

Latency dự đoán được dưới mọi tải

Vì không có boot cost trên từng request, p50 và p99 ở gần nhau hơn. Chúng tôi thường thấy p99 nằm trong 3x p50 ngay cả ở đỉnh traffic spike, trong khi Puppeteer có thể lên 10x p50 trong cold-start storm.

Một artifact deploy được ở mọi nơi

Một module .wasm deploy giống nhau tới mọi Cloudflare colo. Không có câu hỏi “pool Sydney đã warm chưa”; mọi isolate boot module trong vài millisecond và phục vụ giống nhau. Điều này thật sự đơn giản hơn vận hành regional Lambda concurrency reservations.

Một đường tới embedding

Nếu một ngày bạn muốn chạy gPdf bên trong perimeter của khách hàng, như VPC, isolated cluster hoặc intranet air-gapped, cùng WASM module đó vẫn hoạt động. Đó là khác biệt giữa “chúng tôi host SaaS” và “chúng tôi ship công nghệ chạy được ở mọi nơi”.

Khi nào cách này không phù hợp

Edge không phải phép màu miễn phí. Có những workload nơi centralized thắng:

  • Render nhiều giây. Nếu một PDF đơn mất 30 giây, như financial statement lớn hoặc scientific report, container chạy dài có state bền sẽ phù hợp hơn việc vật lộn với CPU cap ở Edge.
  • Render cần database khác. Nếu render cần JOIN ba bảng OLAP, hãy đặt renderer gần database, không phải Edge. Giải pháp: làm JOIN trước, rồi gửi JSON ra Edge cho bước render thật.
  • Output cần post-processing. Watermarking, signing, archival: nếu pipeline sau render nhiều bước và stateful, tính “stateless” của Edge render có thể thành chi phí thay vì tính năng.

Với phần còn lại, và đó là phần lớn traffic B2B invoice/label/receipt, Edge thắng ở mọi trục quan trọng.

Khi nào nên ngừng chịu đựng setup hiện tại

Checklist đơn giản. Nếu bạn tick được ba mục, phép tính migration đã nghiêng:

  • Chi phí hạ tầng PDF hàng tháng vượt 300 USD.
  • p99 latency PDF vượt 800 ms trong traffic bình thường.
  • Bạn từng gặp cold-start incident ảnh hưởng khách hàng.
  • Bạn đã mất hơn 4 giờ debug glyph CJK / RTL / emoji bị thiếu.
  • Bạn tạo PDF trong flow tương tác như preview hoặc download trên màn hình.
  • Bạn vận hành ở hơn một khu vực địa lý.

Ba mục đầu đi cùng nhau nghĩa là bạn vừa trả tiền vừa bị đau. Ba mục sau nghĩa là renderer tập trung đang thật sự giới hạn quyết định sản phẩm mà lẽ ra bạn có thể làm.

Nếu điều đó nghe quen, Playground render một sample invoice trong browser của bạn dưới 5 ms. Hãy để nó tự nói.