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:

CampoPropósito
nameNome do Worker exibido no painel
mainArquivo de entrada resolvido pelo Wrangler
compatibility_dateFixa o comportamento da API do runtime a uma data específica
routesMapeia 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ísticaCloudflare WorkersAWS Lambda@EdgeDeno Deploy
RuntimeIsolamentos V8Contêiner Node.jsIsolamentos V8
Cold start< 1 ms100–500 ms~50 ms
PoPs globais300+~4 regiões CloudFront35 regiões
Nível gratuito100k req/diaPagamento por requisição100k req/dia
Tempo CPU máx.50 ms (grátis) / 30 s (pago)30 s50 ms
ArmazenamentoKV, R2, D1, Durable ObjectsDynamoDB (separado)Deno KV
TypeScriptNativo (integrado)Via etapa de buildNativo
Preço (além do grátis)US$0,50/milhão requisições~US$0,60/milhão + LambdaUS$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 com wrangler init e teste localmente com wrangler dev
  • O arquivo wrangler.toml controla o nome do Worker, ponto de entrada, data de compatibilidade, rotas e todos os bindings de recursos
  • Use wrangler secret put para valores sensíveis e [vars] no wrangler.toml para 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-action do 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

Artigos Relacionados