Executando verificação de segurança...
2

Deno + Deno KV + Deno Deploy: API Serverless com Banco de Dados Embutido

O erro que me custou uma madrugada

Em março de 2024, um cliente pediu um serviço de redirecionamento de URLs para uma campanha de marketing. Requisitos: latência abaixo de 100ms, suportar picos de 5k req/s durante lives no Instagram, e estar no ar em 48 horas. Meu instinto foi levantar um Node.js com Redis na AWS, como fiz dezenas de vezes. Mas o setup de VPC, ElastiCache, ECS, ALB e o pipeline de deploy consumiram 6 horas só de infraestrutura. Quando o serviço ficou pronto, a latência p95 batia 210ms por causa do round-trip até a região us-east-1 (o público era 90% Brasil).

Refiz tudo com Deno Deploy + Deno KV em uma tarde. O cold start caiu para 47ms, a latência p95 para 38ms (edge em GRU), e o custo mensal ficou em $0 dentro do free tier. Esse post é o que eu gostaria de ter lido antes daquela madrugada.

O que é Deno KV e por que ele muda a equação serverless

Deno KV é um banco de dados chave-valor transacional embutido no runtime Deno. Localmente, ele usa SQLite. No Deno Deploy, ele roda sobre FoundationDB, o mesmo motor que sustenta o Apple iCloud e o Snowflake. Isso significa que você tem um banco de dados com consistência forte, replicação global e zero configuração, sem instalar nada, sem connection string, sem driver.

A diferença fundamental para quem vem de Node.js: no ecossistema Node, o runtime (Node.js/libuv) cuida de I/O e você conecta bancos externos via TCP. No Deno Deploy, o banco é parte do runtime. Não existe round-trip de rede para o banco, porque o KV roda no mesmo processo de edge.

AspectoNode.js + Redis (ElastiCache)Node.js + Postgres (Neon)Deno Deploy + Deno KV
Cold start típico150-400ms (Lambda)200-600ms (Lambda + connection)30-60ms
Latência de leitura1-5ms (mesma AZ)5-20ms (serverless proxy)<1ms (co-located)
Setup de infraVPC, Security Group, ElastiCacheConnection pooling, migrationsZero
Custo até 100k req/dia~$15-30/mês~$5-10/mês$0 (free tier)
Modelo de dadosChave-valor, sem transações nativasRelacional completoChave-valor com transações ACID
Replicação globalManual (Global Datastore)Read replicas manuaisAutomática (35+ regiões)

Estrutura do projeto: encurtador de URLs

Vou construir um encurtador de URLs completo para ilustrar cada peça. A estrutura é propositalmente simples: um único arquivo main.ts para a API e um kv.ts para a camada de dados. Em produção, eu separo mais, mas para um serviço focado como este, menos arquivos significa menos overhead cognitivo.

// kv.ts - Camada de acesso ao Deno KV
// Abrimos o KV sem argumentos: localmente usa SQLite em /tmp,
// no Deno Deploy conecta automaticamente ao FoundationDB distribuído.
const kv = await Deno.openKv();

export interface ShortenedUrl {
  originalUrl: string;
  slug: string;
  clicks: number;
  createdAt: string;
  expiresAt: string | null;
}

// Chaves compostas permitem queries eficientes por prefixo.
// ["urls", slug] para lookup rápido no redirect.
// ["urls_by_date", isoDate, slug] para listagem cronológica.
export async function createShortUrl(
  slug: string,
  originalUrl: string,
  ttlDays: number | null = null
): Promise<ShortenedUrl> {
  const now = new Date();
  const entry: ShortenedUrl = {
    originalUrl,
    slug,
    clicks: 0,
    createdAt: now.toISOString(),
    expiresAt: ttlDays
      ? new Date(now.getTime() + ttlDays * 86_400_000).toISOString()
      : null,
  };

  // Transação atômica: garante que o slug não foi criado entre
  // o check e o set (race condition real em serverless com múltiplas instâncias)
  const result = await kv.atomic()
    .check({ key: ["urls", slug], versionstamp: null }) // só cria se não existir
    .set(["urls", slug], entry)
    .set(["urls_by_date", now.toISOString(), slug], entry)
    .commit();

  if (!result.ok) {
    throw new Error(`Slug "${slug}" já existe`);
  }

  return entry;
}

O check com versionstamp: null é o equivalente a um


Leia o artigo completo em https://vivodecodigo.com.br/backend/deno-kv-deploy-api-serverless-database-javascript

Carregando publicação patrocinada...
1
1

Não faz muito sentido mesmo não (estou falando do nome) mas basicamente é uma aplicação rodando em um servidor que você não tem que gerenciar pra fazer funcionar, tudo é gerenciado por terceiros a unica coisa que você controla nesse caso é seu código. Então o nome realmente não faz sentido, existe um server ele só é abstraído.