Skip to content
EngineeringJuly 12, 2026

Xây LLM gateway trên Cloudflare Workers

AnyRouter chạy trên một cụm Cloudflare Worker, không phải server sống lâu. Thiết kế bị ràng buộc cụ thể: trần 128MB RAM cấm buffer cả response, trần script 3MiB buộc tách nhiều Worker, và quy tắc cứng — mọi cuộc gọi upstream đều đi qua Cloudflare AI Gateway. Đây là kiến trúc thực tế.

Vì sao Worker thay vì một server

Cloudflare Worker là isolate, không phải process — khởi động theo request, xử lý xong rồi không giữ RAM hay connection giữa các lần gọi. Không server cần hâm nóng, không fleet cần scale, không region cần chọn; cùng một script chạy ở mọi edge Cloudflare. Với gateway mà việc chỉ là «nhận request, chọn upstream, stream response về», mô hình theo request rất hợp — nhưng mọi quyết định kiến trúc phải tôn trọng giới hạn isolate mà server thường không có.

Hai giới hạn định hình hầu hết phần còn lại: trần 128MB RAM mỗi isolate, và trần script nén 3MiB mỗi Worker.

Stream, đừng bao giờ buffer

Trần 128MB biến một pattern server phổ biến thành nguy hiểm: đọc hết response upstream vào RAM rồi mới forward. Completion LLM có thể dài vô hạn, và await response.text() trên stream không biên không có trần riêng — nó phình đến khi isolate hết bộ nhớ.

Anti-patternWhy it breaksCorrect pattern
await response.text() on unbounded upstream dataMemory exhaustion against the 128MB isolate limitStream: return new Response(readableStream, { headers })
Module-level mutable state for request dataCross-request leakage between isolates handling different usersPer-request state on c.set(...) or closures
Floating promises for background workDropped results, swallowed errors after the response returnsc.executionCtx.waitUntil(promise)

Thực tế, chat completions, Anthropic messages và Responses API đều trả Response gốc bọc SSE của upstream, dịch dialect từng chunk thay vì gom rồi phát lại:

export default (async (c) => {
  const upstream = await fetch(upstreamUrl, { method: "POST", body, headers })

  // Never buffer: pipe the upstream stream straight through,
  // translating SSE dialect chunk-by-chunk as it passes.
  return new Response(upstream.body.pipeThrough(dialectTranslator), {
    status: upstream.status,
    headers: { "Content-Type": "text/event-stream", "Cache-Control": "no-cache" },
  })
}) satisfies HonoHandler
Streaming pattern used across the executor's chat/messages/responses paths.

Trần 3MiB buộc tách nhiều Worker

Một Worker đơn vượt trần script nén 3MiB của Cloudflare khi engine routing, catalog, Durable Objects, MCP, OAuth và cả bề mặt Hono API nằm chung một script. Cách xử lý là hub-and-spoke: một web Worker giữ route toàn zone, rồi forward sang spoke qua service binding, hoặc tự serve trang.

WorkerHostOwns
anyrouter (web hub)anyrouter.dev (apex)SSR landing pages; routes and forwards everything else
anyrouter-apiservice binding onlyHono app, executor, catalog, Durable Objects
anyrouter-dashboarddash.anyrouter.devDashboard app
anyrouter-adminadmin.anyrouter.devAdmin app
anyrouter-mcpservice binding onlyMCP server (JSON-RPC + OAuth)
anyrouter-flowcron + service bindingWorkflows and scheduled jobs

Mỗi spoke proxy /api/* cùng origin sang anyrouter-api qua service binding, nên trình duyệt không bao giờ cross-origin — không cần CORS, cũng không mở thêm bề mặt public cho từng Worker.

Mọi upstream đi qua AI Gateway

Dispatch tới nhà cung cấp mô hình thật sự đi đúng một trong ba hình transport, tất cả đổ vào Cloudflare AI Gateway chứ không gọi API nhà cung cấp trực tiếp:

TransportReachesHow
Workers AI bindingFirst-party and partner-hosted Workers AI catalog modelsc.env.AI.run(model, body, { gateway: { id }, returnRawResponse: true })
Unified AI Gateway RESTCF unified-billing catalog, third-party modelsOne API token, cf-aig-gateway-id header, usage bills via Unified Billing
Per-provider AI Gateway RESTBYOK and direct providers (OpenAI, Anthropic, xAI, Groq, DeepInfra, ...)cf-aig-authorization header plus the provider's own key in Authorization

Tách này vô hình với người dùng cuối — mọi backend dùng cùng huy hiệu «Cloudflare AI Gateway» dù transport nào phục vụ. Quy tắc phía sau chặt hơn nghe: mọi upstream phải đi gateway.ai.cloudflare.com, đúng một ngoại lệ đã ghi: backend first-party không có HTTP origin để proxy (nó tới thiết bị của user qua WebSocket outbound).

Primitive bảo mật mà edge cho sẵn

Chạy trên Workers cũng nghĩa là primitive crypto của nền tảng là mặc định, không phải dependency thêm:

  • crypto.getRandomValues() or crypto.randomUUID() — never Math.random() for tokens or ids
  • crypto.subtle for all cryptographic operations, including per-row encryption at rest
  • crypto.subtle.timingSafeEqual for secret comparison, so key checks aren't timing-attackable
  • Secrets live in wrangler secret put, never hardcoded in source or committed config

Xử lý lỗi tường minh cũng quan trọng hơn framework có trang exception toàn cục — cố ý tránh passThroughOnException(), vì nó giấu bug thật sau fallback im lặng thay vì đưa lên error handler của Hono để log và sửa.

Edge đánh đổi gì

Không thứ nào miễn phí. Mọi giới hạn trên là ràng buộc kiến trúc phải vòng, không phải đã xóa — trần 3MiB nghĩa là tính năng mới phải nghĩ thuộc Worker nào, và quy tắc chỉ-stream nghĩa là không có lối tắt post-process cả response trước khi tới client. Đổi lại là script chạy giống nhau ở mọi edge, không có fleet server phía sau.

AnyRouter live network stats dashboard showing aggregate request and token volume
The same Worker split serves this traffic — no dedicated servers behind it.

Xem vòng đời request, catalog và routing live trong tài khoản của bạn.

Mở dashboard

Gửi request đầu trong hai phút

Bắt đầu miễn phí với key của bạn, hoặc nạp rồi trả theo token. Go: $4 credit/tháng — $2/tháng, hoặc miễn phí khi góp một provider key.

Bắt đầu miễn phí