Hono no edge: APIs ultrarrápidas em Cloudflare Workers e Deno Deploy
1. O que é Hono e por que ele brilha no edge computing
Hono é um framework web minimalista criado pelo desenvolvedor japonês Yusuke Wada, projetado especificamente para rodar em runtimes de borda (edge computing). Sua filosofia central é oferecer o máximo de desempenho com o mínimo de sobrecarga — o pacote comprimido tem aproximadamente 14KB, sem dependências pesadas.
Diferentemente de Express (que carrega um ecossistema inteiro de middlewares) ou Fastify (que depende de plugins e schemas complexos), Hono foi concebido para ser executado onde cada milissegundo importa: Cloudflare Workers, Deno Deploy, Bun e Node.js. O suporte nativo a múltiplos runtimes significa que você escreve uma API uma vez e a implanta em qualquer lugar.
A principal vantagem técnica está no roteador interno. Hono usa um algoritmo de correspondência de padrões baseado em tries (árvores de prefixo), que oferece complexidade O(n) para rotas estáticas e O(1) para rotas dinâmicas — um ganho significativo em cenários com centenas de endpoints.
// Comparação de inicialização mínima
// Express: ~5MB com dependências
// Fastify: ~3MB com dependências
// Hono: ~14KB sem dependências externas
2. Configurando Hono no Cloudflare Workers
Para começar com Cloudflare Workers, você precisa do Wrangler CLI instalado. O processo é direto e orientado a TypeScript desde o início.
# Instalação do Wrangler e criação do projeto
npm install -g wrangler
wrangler init hono-worker --yes
cd hono-worker
npm install hono
Com o projeto configurado, o arquivo src/index.ts recebe a estrutura básica da API:
import { Hono } from 'hono'
import { handle } from 'hono/cloudflare-workers'
const app = new Hono()
app.get('/', (c) => c.text('Hello Hono no Edge!'))
app.get('/api/users/:id', (c) => {
const id = c.req.param('id')
return c.json({ userId: id, timestamp: Date.now() })
})
export default handle(app)
O deploy é igualmente simples:
wrangler deploy
Os primeiros testes de latência mostram resultados impressionantes: requisições respondidas em menos de 5ms (incluindo cold start) na maioria das regiões globais da Cloudflare. Isso ocorre porque o Worker já está "quente" após a primeira requisição, e o Hono adiciona apenas microssegundos ao tempo de resposta.
3. Hono com Deno Deploy: simplicidade e desempenho
Deno Deploy oferece uma experiência ainda mais enxuta. Não há necessidade de bundlers ou configurações complexas — você importa o Hono diretamente de uma URL.
# Inicialização do projeto Deno
deno init hono-deno
cd hono-deno
O arquivo main.ts fica assim:
import { Hono } from 'https://deno.land/x/hono@v3.11.7/mod.ts'
import { serve } from 'https://deno.land/x/hono@v3.11.7/deno.ts'
const app = new Hono()
app.get('/', (c) => c.text('Hono no Deno Deploy!'))
app.post('/api/data', async (c) => {
const body = await c.req.json()
return c.json({ received: body, processed: true })
})
serve(app, { port: 8000 })
Para deploy, use o dashboard do Deno Deploy ou o CLI:
deployctl deploy --project=hono-demo main.ts
Comparando cold starts: Cloudflare Workers tendem a ter cold starts ligeiramente menores (cerca de 1-2ms) para Workers simples, enquanto Deno Deploy apresenta cold starts de 3-5ms. Porém, Deno compensa com uma experiência de desenvolvimento mais fluida, sem necessidade de bundlers ou configurações de build.
4. Recursos avançados para APIs ultrarrápidas
Validação com Zod
Hono integra-se perfeitamente com Zod para validação de dados no edge:
import { z } from 'zod'
import { zValidator } from 'hono/zod-validator'
const schema = z.object({
name: z.string().min(3),
email: z.string().email()
})
app.post('/api/users', zValidator('json', schema), async (c) => {
const user = c.req.valid('json')
return c.json({ success: true, user })
})
Cache inteligente
Para reduzir ainda mais a latência, use cabeçalhos Cache-Control e Workers KV:
app.get('/api/products', async (c) => {
const cacheKey = 'products-list'
const cached = await c.env.KV.get(cacheKey, 'json')
if (cached) {
return c.json(cached, 200, {
'Cache-Control': 'public, max-age=3600',
'X-Cache': 'HIT'
})
}
const products = await fetchProducts()
await c.env.KV.put(cacheKey, JSON.stringify(products), { expirationTtl: 3600 })
return c.json(products, 200, {
'Cache-Control': 'public, max-age=3600',
'X-Cache': 'MISS'
})
})
Streaming e Server-Sent Events
Hono suporta streaming nativo, ideal para APIs em tempo real:
app.get('/events', (c) => {
return c.stream(async (stream) => {
for (let i = 0; i < 10; i++) {
await stream.write(`data: Evento ${i}\n\n`)
await stream.sleep(1000)
}
})
})
5. Padrões de roteamento e middleware para edge
Hono oferece roteamento flexível com suporte a parâmetros dinâmicos e expressões regulares:
// Roteamento dinâmico
app.get('/api/users/:id/posts/:postId', (c) => {
const { id, postId } = c.req.param()
return c.json({ user: id, post: postId })
})
// Roteamento com regex
app.get('/api/items/:id{[0-9]+}', (c) => {
const id = c.req.param('id')
return c.json({ itemId: parseInt(id) })
})
Middlewares globais e por rota permitem implementar autenticação, CORS e rate limiting sem esforço:
import { cors } from 'hono/cors'
import { bearerAuth } from 'hono/bearer-auth'
// Middleware global
app.use('*', cors({
origin: 'https://meudominio.com',
allowMethods: ['GET', 'POST']
}))
// Middleware por rota
app.use('/api/admin/*', bearerAuth({ token: 'secret-token' }))
// Rate limiting simples
app.use('/api/*', async (c, next) => {
const ip = c.req.header('CF-Connecting-IP') || 'unknown'
const count = await c.env.KV.get(`rate:${ip}`, 'json') || 0
if (count > 100) {
return c.json({ error: 'Rate limit exceeded' }, 429)
}
await c.env.KV.put(`rate:${ip}`, String(count + 1), { expirationTtl: 60 })
await next()
})
Tratamento de erros padronizado:
app.onError((err, c) => {
console.error(`Erro: ${err.message}`)
return c.json({
error: 'Internal Server Error',
message: err.message
}, 500)
})
app.notFound((c) => {
return c.json({ error: 'Not Found' }, 404)
})
6. Integração com serviços de borda (KV, R2, D1)
Workers KV para sessões
app.post('/api/login', async (c) => {
const { username, password } = await c.req.json()
const user = await authenticate(username, password)
if (!user) {
return c.json({ error: 'Invalid credentials' }, 401)
}
const sessionId = crypto.randomUUID()
await c.env.KV.put(`session:${sessionId}`, JSON.stringify(user), {
expirationTtl: 86400 // 24 horas
})
return c.json({ sessionId })
})
R2 para upload de arquivos
app.post('/api/upload', async (c) => {
const formData = await c.req.formData()
const file = formData.get('file') as File
if (!file) {
return c.json({ error: 'No file provided' }, 400)
}
const key = `uploads/${Date.now()}-${file.name}`
await c.env.R2.put(key, await file.arrayBuffer(), {
httpMetadata: { contentType: file.type }
})
return c.json({ url: `https://cdn.exemplo.com/${key}` })
})
D1 (SQLite serverless)
app.get('/api/users', async (c) => {
const { results } = await c.env.DB.prepare(
'SELECT id, name, email FROM users LIMIT 10'
).all()
return c.json(results)
})
7. Testes, monitoramento e boas práticas
Testes unitários com Vitest para Workers:
// tests/api.test.ts
import { describe, it, expect } from 'vitest'
import app from '../src/index'
describe('API Hono', () => {
it('deve retornar saudação', async () => {
const res = await app.request('/')
expect(res.status).toBe(200)
expect(await res.text()).toBe('Hello Hono no Edge!')
})
it('deve validar dados do usuário', async () => {
const res = await app.request('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Jo', email: 'invalido' })
})
expect(res.status).toBe(400)
})
})
Monitoramento com Cloudflare Observability:
// Adicione métricas personalizadas
app.use('*', async (c, next) => {
const start = Date.now()
await next()
const duration = Date.now() - start
c.executionCtx.waitUntil(
c.env.METRICS.writeDataPoint({
blobs: [c.req.method, c.req.path],
doubles: [duration]
})
)
})
Boas práticas para deploy contínuo:
- Versionamento semântico das APIs (
/v1/,/v2/) - Testes automatizados antes do deploy
- Deploy gradual com Cloudflare Workers (staging → production)
- Monitoramento de erros com Sentry ou Datadog
8. Casos de uso reais e quando evitar Hono no edge
Casos ideais
- APIs de geolocalização: Workers respondem em milissegundos na borda mais próxima
- Webhooks: Processamento rápido de eventos sem overhead de servidor
- Autenticação descentralizada: Verificação de tokens JWT sem estado
- APIs de consulta rápida: Catálogos de produtos, preços em tempo real
Limitações
- Workloads pesados de CPU: Processamento de imagens, machine learning ou criptografia intensa
- Dependências nativas: Bibliotecas que exigem binários compilados (ex: sharp, bcrypt)
- Conexões longas: WebSockets persistentes em grande escala podem ser custosos
Alternativas
- Fastify: Para APIs monolíticas que exigem ecossistema rico de plugins
- NestJS: Quando a arquitetura modular e injeção de dependência são requisitos
- Servidores tradicionais: Para workloads que ultrapassam os limites de CPU/memória do edge (10ms de CPU, 128MB RAM)
Referências
- Documentação oficial do Hono — Guia completo de instalação, roteamento, middlewares e integrações com runtimes de borda
- Cloudflare Workers - Getting Started — Tutorial oficial para criar e implantar Workers com Wrangler CLI
- Deno Deploy Documentation — Referência completa para deploy de aplicações Deno no edge, incluindo integração com Hono
- Zod Validation Library — Documentação oficial da biblioteca de validação de schemas TypeScript, amplamente usada com Hono
- Cloudflare Workers KV — Guia prático de armazenamento chave-valor distribuído para dados de sessão e cache
- Hono + Zod: Validação no Edge — Artigo técnico demonstrando validação de dados com Zod em APIs Hono
- Comparação de Frameworks Web para Edge Computing — Análise da Cloudflare sobre desempenho de diferentes frameworks em Workers