WRK
vs
PGS
Workers vs Pages
api • deploy • edge fn

Cloudflare Workers vs Pages: khi nào dùng cái nào?

Workers là serverless function thuần, Pages là hosting tĩnh có kèm Functions — bảng so sánh rõ, use case cụ thể, và cách chọn đúng cho từng loại dự án.

10 phút đọc17/06/2026

Kết luận nhanh

  • Dùng Workers khi bạn cần chạy logic ở edge: API backend, proxy, xác thực, middleware, job handler — không cần serve file tĩnh
  • Dùng Pages khi bạn có frontend: Next.js, Astro, SvelteKit, React SPA — Pages lo cả phần hosting lẫn phần server (Pages Functions chính là Workers bên dưới)
  • Không phải chọn một trong hai: nhiều dự án dùng Pages cho frontend + Workers riêng cho backend API, rồi bind chung KV/D1/R2

Bảng so sánh nhanh

Workers Pages
Mục đích chính Serverless function tại edge Static hosting + Functions
Cách deploy wrangler deploy Git push (hoặc wrangler pages deploy)
Serve file tĩnh Không (phải kết hợp R2 hoặc KV) Có — tự động từ build output
Server-side logic Toàn bộ là logic Pages Functions (Workers bên dưới)
Framework hỗ trợ Không có sẵn Next.js, Astro, SvelteKit, Remix...
Bind KV/D1/R2/Queue Có (trong Pages Functions)
Cron trigger Có ([triggers] trong wrangler.toml) Không
Free tier requests 100.000 req/ngày Không giới hạn requests (vô hạn)
Free tier build Không áp dụng 500 build/tháng
Custom domain
Preview deployment Không Có (mỗi branch/PR tạo preview URL)

Workers là gì và làm được gì

Workers là nền tảng serverless function của Cloudflare chạy ở edge — tức là code của bạn chạy trên datacenter Cloudflare gần người dùng nhất, không phải trên một server cố định.

Mỗi Worker nhận một HTTP request, xử lý, và trả về response. Không có server, không có container, không có cold start đáng kể.

Worker cơ bản trông như thế này

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const url = new URL(request.url);

    if (url.pathname === "/api/ping") {
      return Response.json({ ok: true, ts: Date.now() });
    }

    return new Response("Not found", { status: 404 });
  },
};

Deploy bằng:

wrangler deploy

Workers phù hợp cho bài toán nào

API backend thuần

Khi app mobile hoặc SPA cần một API nhẹ, không muốn dựng server riêng:

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    if (request.method === "POST" && new URL(request.url).pathname === "/api/contact") {
      const body = await request.json<{ email: string; message: string }>();
      await env.DB.prepare("INSERT INTO contacts (email, message) VALUES (?, ?)")
        .bind(body.email, body.message)
        .run();
      return Response.json({ ok: true });
    }
    return new Response("Not found", { status: 404 });
  },
};

Proxy và middleware

Chèn logic trước khi request đến origin server: xác thực token, rate limit, rewrite URL, thêm header:

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const token = request.headers.get("Authorization");
    if (!token || !(await verify(token, env.JWT_SECRET))) {
      return new Response("Unauthorized", { status: 401 });
    }
    return fetch(request); // forward to origin
  },
};

Cron job tại edge

Workers có thể chạy định kỳ không cần request từ người dùng:

# wrangler.toml
[triggers]
crons = ["0 * * * *"] # mỗi giờ
export default {
  async scheduled(event: ScheduledEvent, env: Env): Promise<void> {
    await syncDataFromExternalApi(env);
  },
};

Pages Functions không có cron trigger.

Queue consumer

Xử lý job từ Cloudflare Queues:

export default {
  async queue(batch: MessageBatch<Job>, env: Env): Promise<void> {
    for (const msg of batch.messages) {
      await processJob(msg.body, env);
      msg.ack();
    }
  },
};

Pages là gì và làm được gì

Pages là nền tảng hosting tĩnh của Cloudflare. Bạn connect repo GitHub/GitLab, mỗi lần push code Pages sẽ tự build và deploy lên CDN toàn cầu.

Điểm đặc biệt: Pages không chỉ serve file HTML/CSS/JS tĩnh — nó có Pages Functions, cho phép bạn viết server-side logic nằm ngay trong project, bind vào KV/D1/R2/Queue y hệt Workers.

Cấu trúc project Pages với Functions

my-app/
├── src/                  # frontend code (Next.js, Astro,...)
├── functions/            # Pages Functions
│   ├── api/
│   │   ├── posts.ts      # → /api/posts
│   │   └── contact.ts    # → /api/contact
│   └── _middleware.ts    # chạy trước mọi request
└── package.json

Pages Function tự routing theo tên file — không cần config thêm.

Pages phù hợp cho bài toán nào

Full-stack app với framework

Pages hỗ trợ sẵn Next.js, Astro, SvelteKit, Remix, Nuxt và nhiều framework khác qua adapter. Build một lần, Pages tự lo deploy và CDN:

# Next.js trên Pages
npm install @cloudflare/next-on-pages
# deploy
wrangler pages deploy .vercel/output/static

Static site / blog

Blog tĩnh dùng Astro, Hugo, Eleventy... — Pages serve file nhanh từ edge, không cần server:

# Astro build rồi deploy
npm run build
wrangler pages deploy dist

App có frontend + server nhẹ

SPA cần vài endpoint — viết Pages Functions thay vì dựng Workers riêng:

// functions/api/products.ts
export async function onRequestGet(context: EventContext<Env, string, unknown>) {
  const products = await context.env.DB.prepare("SELECT * FROM products").all();
  return Response.json(products.results);
}

Preview deployment theo branch

Mỗi PR tự động tạo URL preview riêng — tiện để review trước khi merge:

https://feat-new-checkout.my-app.pages.dev

Workers không có tính năng này.


Pages Functions chính là Workers

Điều hay bị nhầm: người ta nghĩ Pages Functions "kém hơn" Workers. Thực ra Pages Functions chạy trên cùng runtime với Workers — V8 isolates, edge network, khả năng bind KV/D1/R2/Queue y hệt nhau.

Điểm khác biệt:

  • Pages Functions routing theo file system (functions/api/users.ts/api/users)
  • Workers routing do bạn tự xử lý trong code
  • Pages Functions không có cron trigger
  • Pages Functions không nhận Queue message trực tiếp

Nếu app của bạn là Next.js on Pages, toàn bộ API routes (app/api/) đều chạy trên Workers runtime — bạn vẫn bind được D1, KV, R2 bình thường qua process.env hoặc context.env.


Khi nào dùng Workers, khi nào dùng Pages

Dùng Workers khi

  • Bạn xây API backend thuần, không có frontend đi kèm
  • Cần cron trigger chạy định kỳ
  • Cần nhận và xử lý message từ Queue
  • Viết proxy hoặc middleware chặn trước origin
  • Muốn kiểm soát hoàn toàn routing và logic không ràng buộc vào structure của Pages
  • Script nhỏ chạy edge: image resize, auth check, geo redirect

Dùng Pages khi

  • Có frontend framework cần deploy: Next.js, Astro, SvelteKit, Remix
  • Cần static hosting + CDN cho HTML/CSS/JS/image
  • Muốn preview deployment theo branch/PR
  • API đơn giản, có thể đặt trong functions/ cùng project
  • Muốn deploy bằng git push thay vì CI/CD riêng

Dùng cả hai khi

Đây là pattern phổ biến nhất với app thật:

Pages (frontend Next.js)
  └── bind KV, D1, R2

Workers (backend API riêng)
  └── bind cùng KV, D1, R2
  └── có cron trigger
  └── nhận Queue message

Frontend gọi Worker API qua fetch("/api/...") hoặc domain riêng. Cả hai đều bind vào cùng namespace KV và database D1.


Free tier so sánh

Workers free tier

  • 100.000 requests/ngày — qua giới hạn này sẽ tính phí ($0.50/triệu requests)
  • 10ms CPU time/request trên free plan (không phải wall time — là thời gian CPU thực)
  • Cron trigger: 1 cron/Worker trên free plan
  • Không giới hạn số Worker

Pages free tier

  • Không giới hạn requests — serving file tĩnh hoàn toàn miễn phí
  • 500 builds/tháng (đủ dùng cho team nhỏ)
  • 1 project trên free plan (paid thì unlimited)
  • Preview deployment: không giới hạn
  • Pages Functions dùng chung quota với Workers — vẫn tính 100.000 requests/ngày

Tức là nếu app của bạn chỉ là static site không có Functions, Pages free tier thực sự không giới hạn. Ngay khi bạn bắt đầu dùng Functions, quota sẽ tính vào Workers limit.


Tóm lại nên chọn gì

Bạn đang làm Nên dùng
API backend không có frontend Workers
Background job, cron, Queue consumer Workers
Proxy / edge middleware Workers
Blog, docs site, landing page Pages
Next.js / Astro / SvelteKit app Pages
Full-stack với frontend + API nhẹ Pages (+ Functions)
Frontend phức tạp + backend nặng Pages + Workers riêng

Nếu đang phân vân, quy tắc đơn giản: có frontend thì dùng Pages, không có frontend thì dùng Workers. Pages Functions đủ mạnh cho phần lớn backend nhẹ, và nếu sau này cần tách ra, chuyển Function sang Workers standalone không khó.