TL;DR — Resumo Rápido
Cloudflare Workers executa JavaScript no edge com isolamentos V8. Implante seu primeiro Worker com Wrangler, configure KV, segredos e CI/CD com GitHub Actions.
O Cloudflare Workers leva a computação serverless ao edge — seu código é executado em data centers distribuídos em mais de 300 cidades do mundo, a milissegundos dos seus usuários, sem necessidade de provisionar ou escalar servidores. Construído sobre isolamentos V8 (o mesmo motor que impulsiona o Chrome e o Node.js), o Workers alcança tempos de cold start abaixo de 1 milissegundo, sendo dramaticamente mais rápido que as funções serverless tradicionais baseadas em contêineres. Neste guia você irá do zero a um Worker totalmente implantado em produção com armazenamento KV, segredos criptografados, domínios personalizados e um pipeline de implantação automatizado com GitHub Actions.
Pré-requisitos
- Node.js 18+ instalado localmente
- Uma conta Cloudflare (o nível gratuito funciona para tudo neste guia)
- Familiaridade básica com JavaScript ou TypeScript
- Um domínio registrado adicionado à Cloudflare (necessário apenas para a seção de domínio personalizado)
- npm ou pnpm como gerenciador de pacotes
Criando seu Primeiro Worker
Instale o Wrangler, a CLI oficial da Cloudflare, globalmente:
npm install -g wrangler
wrangler login
O comando wrangler login abre uma janela do navegador e solicita que você autorize o Wrangler a acessar sua conta Cloudflare. Após a autorização, as credenciais são armazenadas em ~/.wrangler/config/default.toml.
Crie um novo projeto:
wrangler init my-api-worker
cd my-api-worker
O Wrangler apresenta algumas perguntas — escolha TypeScript e o template “Hello World” Worker. A estrutura do diretório resultante é:
my-api-worker/
src/
index.ts ← seu código Worker
wrangler.toml ← configuração do projeto
package.json
tsconfig.json
Entendendo o wrangler.toml
O arquivo wrangler.toml é o manifesto do projeto. Uma configuração mínima parece assim:
name = "my-api-worker"
main = "src/index.ts"
compatibility_date = "2024-09-23"
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
Campos principais:
| Campo | Propósito |
|---|---|
name | Nome do Worker exibido no painel |
main | Arquivo de entrada resolvido pelo Wrangler |
compatibility_date | Fixa o comportamento da API do runtime a uma data específica |
routes | Mapeia padrões de URL para este Worker |
[[kv_namespaces]] | Vincula namespaces KV como variáveis de ambiente |
[vars] | Variáveis de ambiente em texto simples |
A compatibility_date é importante — a Cloudflare ocasionalmente introduz mudanças que quebram compatibilidade nas APIs de Worker, e essa data fixa qual conjunto de APIs seu Worker vê.
Escrevendo o Worker
O ponto de entrada do Worker exporta um objeto padrão com um handler fetch. Cada requisição HTTP recebida chama esse handler:
export interface Env {
MY_KV: KVNamespace;
API_SECRET: string;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
// Rota: retornar JSON
if (url.pathname === '/api/status') {
return Response.json({ status: 'ok', region: request.cf?.colo });
}
// Rota: retornar HTML
if (url.pathname === '/') {
return new Response(
`<h1>Olá do edge!</h1>`,
{ headers: { 'Content-Type': 'text/html;charset=UTF-8' } }
);
}
return new Response('Não Encontrado', { status: 404 });
}
};
Padrões de Request e Response
O Workers usa a API Fetch padrão — Request, Response e Headers são idênticos às APIs do navegador. Isso significa que o código que você escreve para Workers é amplamente portável.
Retornar JSON é idiomático com Response.json():
return Response.json({ items: ['a', 'b', 'c'] }, {
headers: { 'Cache-Control': 'public, max-age=60' }
});
Redirecionar uma requisição:
return Response.redirect('https://example.com/novo-caminho', 301);
Modificar uma resposta proxiada (o padrão “transform”):
const upstream = await fetch(request);
const body = await upstream.text();
return new Response(body.replace('texto antigo', 'texto novo'), upstream);
Desenvolvimento Local
Execute o servidor de desenvolvimento local:
wrangler dev
O Wrangler inicia um servidor local em http://localhost:8787 que emula o runtime da Cloudflare incluindo KV, Durable Objects, R2 e o objeto de metadados request.cf. O hot reload é acionado automaticamente em mudanças de arquivos.
Para testar contra a infraestrutura real da Cloudflare:
wrangler dev --remote
Inspecione o tráfico em tempo real com o log tail integrado em um segundo terminal:
wrangler tail
Implantando em Produção
Implante com um único comando:
wrangler deploy
O Wrangler compila seu TypeScript, empacota as dependências e faz upload do Worker para a rede da Cloudflare. A implantação se propaga globalmente em segundos. A saída inclui a URL do workers.dev:
Published my-api-worker (2.45 sec)
https://my-api-worker.seu-subdominio.workers.dev
Conectando um Domínio Personalizado
Adicione um bloco routes no wrangler.toml para rotear requisições do seu domínio proxiado pela Cloudflare para o Worker:
[[routes]]
pattern = "api.example.com/*"
zone_name = "example.com"
Alternativamente, use o recurso Custom Domains:
[[routes]]
pattern = "api.example.com"
custom_domain = true
Variáveis de Ambiente e Segredos
Variáveis Simples
A configuração não sensível fica no wrangler.toml:
[vars]
ENVIRONMENT = "production"
MAX_RETRIES = "3"
Segredos Criptografados
Os segredos são criptografados em repouso. Adicione-os via CLI:
wrangler secret put API_KEY
O Wrangler solicitará que você insira o valor de forma interativa. Liste os segredos existentes:
wrangler secret list
No Worker, os segredos aparecem como env.API_KEY — indistinguíveis das variáveis simples em tempo de execução.
Armazenamento KV
O KV (Workers KV) é um armazenamento chave-valor distribuído globalmente com consistência eventual. É excelente para armazenar configurações, sessões de usuários, respostas de API em cache e flags de funcionalidades.
Crie um namespace KV:
wrangler kv namespace create CACHE
Adicione o binding ao wrangler.toml:
[[kv_namespaces]]
binding = "CACHE"
id = "abc123def456..."
Escreva e leia do KV no Worker:
// Escrever (com TTL opcional em segundos)
await env.CACHE.put('usuario:123', JSON.stringify(dadosUsuario), { expirationTtl: 3600 });
// Ler
const raw = await env.CACHE.get('usuario:123');
const usuario = raw ? JSON.parse(raw) : null;
// Deletar
await env.CACHE.delete('usuario:123');
Comparação
| Característica | Cloudflare Workers | AWS Lambda@Edge | Deno Deploy |
|---|---|---|---|
| Runtime | Isolamentos V8 | Contêiner Node.js | Isolamentos V8 |
| Cold start | < 1 ms | 100–500 ms | ~50 ms |
| PoPs globais | 300+ | ~4 regiões CloudFront | 35 regiões |
| Nível gratuito | 100k req/dia | Pagamento por requisição | 100k req/dia |
| Tempo CPU máx. | 50 ms (grátis) / 30 s (pago) | 30 s | 50 ms |
| Armazenamento | KV, R2, D1, Durable Objects | DynamoDB (separado) | Deno KV |
| TypeScript | Nativo (integrado) | Via etapa de build | Nativo |
| Preço (além do grátis) | US$0,50/milhão requisições | ~US$0,60/milhão + Lambda | US$0,50/milhão requisições |
O Workers vence em cold start e distribuição global. O Lambda@Edge é a escolha certa se você já está profundamente integrado no ecossistema AWS. O Deno Deploy é uma boa alternativa se você quiser o modelo de permissões do Deno.
Cenário Real: Worker Proxy de API
Você tem uma API de terceiros que não suporta CORS, requer uma chave de API que você não pode expor ao navegador e responde com dados que deseja cachear e transformar. Um Cloudflare Worker é a solução perfeita.
export interface Env {
UPSTREAM_API_KEY: string;
CACHE: KVNamespace;
}
export default {
async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
const url = new URL(request.url);
const upstreamUrl = `https://api.terceiros.com${url.pathname}${url.search}`;
const cacheKey = upstreamUrl;
// Verificar cache KV primeiro
const cached = await env.CACHE.get(cacheKey);
if (cached) {
return Response.json(JSON.parse(cached), {
headers: { 'X-Cache': 'HIT', 'Access-Control-Allow-Origin': '*' }
});
}
// Buscar do upstream com chave secreta
const upstream = await fetch(upstreamUrl, {
headers: { 'Authorization': `Bearer ${env.UPSTREAM_API_KEY}` }
});
if (!upstream.ok) {
return new Response('Erro upstream', { status: upstream.status });
}
const data = await upstream.json();
// Cachear a resposta por 5 minutos
ctx.waitUntil(env.CACHE.put(cacheKey, JSON.stringify(data), { expirationTtl: 300 }));
return Response.json(data, {
headers: { 'X-Cache': 'MISS', 'Access-Control-Allow-Origin': '*' }
});
}
};
CI/CD com GitHub Actions
Automatize implantações em cada push para main:
# .github/workflows/deploy.yml
name: Deploy Worker
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy
steps:
- uses: actions/checkout@v4
- name: Configurar Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- name: Instalar dependências
run: npm ci
- name: Implantar no Cloudflare Workers
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
Adicione CF_API_TOKEN e CLOUDFLARE_ACCOUNT_ID como segredos do repositório no GitHub. Crie o token de API no painel da Cloudflare em Perfil → Tokens de API → Criar Token usando o modelo “Edit Cloudflare Workers”.
Armadilhas e Casos Especiais
Limite de tempo de CPU — O plano gratuito permite 10 ms de tempo de CPU por requisição. O plano Workers Paid aumenta isso para 30 segundos. Trabalho intensivo em CPU pode atingir esse limite; descarregue computação pesada para uma fila ou use Durable Objects.
Limites de sub-requisições — Cada invocação de Worker pode fazer até 50 chamadas fetch() de saída no plano gratuito (1000 no pago).
Data de compatibilidade e mudanças que quebram compatibilidade — Ao atualizar compatibility_date, revise o registro de mudanças das flags de compatibilidade.
Limites de tamanho — Scripts de Worker são limitados a 1 MB após compressão (10 MB no plano pago). Dependências npm grandes podem ultrapassar esse limite; use tree shaking.
Sem acesso ao sistema de arquivos — Workers não têm E/S de disco. Toda persistência deve passar por KV, R2, D1 ou Durable Objects.
waitUntil para trabalho em segundo plano — Use ctx.waitUntil(promise) para trabalho que deve ser concluído após o envio da resposta (como escritas em cache).
Solução de Problemas
Error: Script startup exceeded CPU time limit — Seu Worker está fazendo trabalho custoso durante a inicialização do módulo. Mova operações custosas para dentro do handler ou use inicialização lazy.
TypeError: Cannot read properties of undefined (reading 'get') — Um binding KV ou outro binding está faltando no wrangler.toml, ou você está acessando env.MEU_BINDING antes de o binding estar configurado.
wrangler deploy falha com “Authentication error” — Sua sessão do Wrangler expirou. Execute wrangler login novamente ou defina a variável de ambiente CLOUDFLARE_API_TOKEN.
Erros de CORS no navegador — A resposta do Worker está faltando Access-Control-Allow-Origin. Adicione o cabeçalho no seu construtor de Response. Também trate a requisição de preflight OPTIONS separadamente.
Domínio personalizado não roteando para o Worker — Certifique-se de que o domínio está proxiado pela Cloudflare (nuvem laranja nas configurações DNS), o padrão de rota no wrangler.toml usa o curinga /* se necessário, e você reimplantou após alterar o wrangler.toml.
Resumo
- Cloudflare Workers são funções serverless baseadas em isolamentos V8 que executam no edge com cold starts abaixo de milissegundo e distribuição global
- Instale o Wrangler com
npm install -g wrangler, faça o scaffold comwrangler inite teste localmente comwrangler dev - O arquivo
wrangler.tomlcontrola o nome do Worker, ponto de entrada, data de compatibilidade, rotas e todos os bindings de recursos - Use
wrangler secret putpara valores sensíveis e[vars]nowrangler.tomlpara configuração não sensível - Os namespaces KV fornecem armazenamento chave-valor distribuído globalmente, acessível via
env.BINDING.get/put/delete - O Workers supera o Lambda@Edge em cold start e alcance global; o Lambda@Edge é preferível para integração profunda no ecossistema AWS
- A Action
wrangler-actiondo GitHub fornece CI/CD pronto para uso; limite seu token de API apenas a permissões de Workers - Fique atento aos limites de tempo de CPU, limites de sub-requisições e o teto de 1 MB de tamanho de script no plano gratuito