Para criar um encurtador de URL você precisa de quatro coisas: um lugar para armazenar o mapeamento de um código curto para um URL de destino, uma forma de gerar um código único para cada novo link, um manipulador de redirecionamento que consulta o código e retorna um redirecionamento HTTP, e um cache na frente da consulta porque as leituras superam as escritas por uma ampla margem. Esse é o núcleo completo, e você pode colocá-lo em funcionamento em uma tarde.
A armadilha é pensar que a versão da tarde é o produto. Um redirecionamento que funciona no seu laptop e um serviço de encurtamento de URL que sobrevive a estranhos apontando-o para malware, sobrecarregando-o com tráfego e esperando quatro noves de disponibilidade são problemas de engenharia diferentes. O primeiro é um algoritmo. O segundo é um compromisso operacional.
Este guia constrói o núcleo honestamente e passa a maior parte do tempo na parte que os tutoriais de design de sistemas pulam: o que você ainda tem que construir depois que o redirecionamento funciona. Se você quiser primeiro a introdução conceitual, como funcionam os encurtadores de URL cobre a mecânica sem o código.
A Versão Resumida: O Que um Encurtador de URL Realmente Faz#
Um encurtador de URL é uma consulta de chave-valor usando um redirecionamento HTTP. A chave é o código curto, o valor é o URL longo, e o trabalho completo é transformar example.com/aB3x9 em um 302 apontando para o endereço original.
O modelo de dados é uma tabela:
CREATE TABLE links (
id BIGSERIAL PRIMARY KEY,
short_code TEXT NOT NULL UNIQUE,
long_url TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
CREATE UNIQUE INDEX idx_links_short_code ON links (short_code);
Há dois caminhos por ela. O caminho de escrita recebe um URL longo, gera um código curto e insere a linha. O caminho de leitura recebe um código curto, consulta a linha e retorna um redirecionamento. As leituras dominam por uma proporção que geralmente está em torno de 1000 para 1, então quase toda a sua atenção de engenharia deve se concentrar em tornar a consulta rápida e barata. O índice único em short_code é o que mantém essa consulta como uma busca de índice em vez de uma varredura. Esse é o núcleo completo.
Gerando o Código Curto: Base62, Aleatório ou Hash#
O código curto é onde a decisão interessante mora. Você tem três estratégias realistas, e elas trocam comprimento, previsibilidade e dificuldade de lidar com colisões.
Base62 de um ID único é o clássico. Pegue o ID de linha com incremento automático e codifique-o em base62, os 62 caracteres a-z, A-Z e 0-9. Os códigos são curtos, nunca colidem porque cada ID é único, e crescem um caractere a mais aproximadamente a cada 62x em volume. A desvantagem é que são sequenciais e previsíveis, então qualquer pessoa pode percorrer seu espaço de nomes.
const alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
// encode turns a positive integer ID into a base62 short code.
func encode(id uint64) string {
if id == 0 {
return string(alphabet[0])
}
var b []byte
for id > 0 {
b = append(b, alphabet[id%62])
id /= 62
}
// reverse, since we built the digits least-significant first
for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
b[i], b[j] = b[j], b[i]
}
return string(b)
}
Strings aleatórias resolvem o problema da previsibilidade. Gere um código aleatório curto, por exemplo com uma biblioteca como nanoid, e verifique-o no índice único antes de salvar. Com sete caracteres de base62 você tem trilhões de possibilidades, então as colisões são raras, mas você ainda precisa lidar com a inserção rara que falha na restrição de unicidade repetindo com um novo código.
Aplicar hash ao URL é a terceira opção e geralmente a pior. Um hash do URL longo é determinístico, o que parece conveniente, mas você ainda tem que truncá-lo, ainda tem colisões, e URLs idênticos mapeiam para códigos idênticos, o que vaza informações. A maioria dos serviços de produção escolhe base62 para IDs internos ou códigos aleatórios para os públicos. Slugs personalizados ou de marca, os códigos que um usuário digita manualmente, são validados no mesmo índice único antes de serem aceitos.
O Caminho de Redirecionamento: 301 vs 302 e Por Que Isso Decide Suas Análises#
O código de status do redirecionamento não é uma escolha cosmética. Ele decide se você verá um segundo clique alguma vez.
Um 301 Moved Permanently diz aos navegadores e proxies que a mudança é permanente, então eles o armazenam em cache. Após a primeira visita, o navegador pode enviar cliques futuros diretamente para o destino sem tocar no seu servidor. Ótimo para velocidade bruta, fatal para análises, porque os cliques que você mais quer contar são os que nunca chegam a você. A semântica HTTP está detalhada no RFC 9110, que define tanto os redirecionamentos permanentes quanto os temporários.
Um 302 Found ou 307 Temporary Redirect é requisitado novamente a cada vez. O navegador consulta seu servidor a cada clique, o que significa que você pode contar cada visita e pode alterar o destino mais tarde sem lutar contra caches desatualizados. Para um encurtador de links cujo valor todo é links editáveis e dados de cliques, esse é o padrão correto. O custo é uma ida e volta de rede por clique, que um acerto de cache torna insignificante.
A regra geral: use 302, a menos que você tenha um motivo específico para querer o link congelado e armazenado em cache para sempre. O post redirecionamentos 301 vs 302 analisa o equilíbrio em detalhes, e tipos de redirecionamentos cobre o restante da família 3xx, incluindo quando 307 e 308 são importantes.
Armazenamento e Cache: Projetando para uma Proporção de Leitura/Escrita de 1000:1#
Como as leituras superam as escritas, o banco de dados não é seu gargalo, sua estratégia de cache é. O padrão é um cache de leitura antecipada: em um clique, verifique primeiro um cache em memória e só recorra ao banco de dados em uma falha, gravando o resultado de volta no cache para a próxima vez.
func resolve(ctx context.Context, code string) (string, error) {
if url, ok := cache.Get(code); ok {
return url, nil // hot path: served from memory
}
url, err := db.LookupLongURL(ctx, code)
if err != nil {
return "", err
}
cache.Set(code, url) // populate for the next click
return url, nil
}
Em produção, isso geralmente se torna dois níveis: um pequeno cache em processo para os links mais acessados, apoiado por um armazenamento compartilhado em memória como Redis, para que cada instância do servidor se beneficie de uma consulta que qualquer uma delas já realizou. O banco de dados, a fonte de verdade, é acessado apenas em uma falha genuinamente fria. Acerte essa camada e um único servidor modesto lida com um enorme volume de cliques. O post estratégia de cache para redirecionamentos de URL aprofunda as decisões de despejo e dimensionamento, e o guia principal sobre atingir p95 abaixo de 15ms cobre como é um caminho de redirecionamento otimizado sob carga.
Se você preferir não executar nada disso, a API do Elido oferece o nível de redirecionamento, o cache e a entrega em região EU com p95 abaixo de 15ms em um acerto de cache, com uma única chamada. Comece grátis e pule as operações.
Contando Cliques Sem Desacelerar o Redirecionamento#
O erro que mata a latência do redirecionamento é gravar o clique no banco de dados dentro do manipulador de redirecionamento. Faça isso e cada visitante espera pela sua escrita de análise antes de receber o redirecionamento.
Desacople-os. O manipulador emite o redirecionamento imediatamente e dispara o evento de clique em um log durável ou fila de mensagens como trabalho fire-and-forget. Um consumidor separado lê esse fluxo e grava eventos em um armazenamento de análise no seu próprio horário. O visitante nunca espera, e uma consulta de relatório que varre milhões de linhas de cliques nunca compete com o caminho de redirecionamento pelos recursos. Um banco de dados de análise colunar lida com essas consultas agregadas muito melhor do que um armazenamento de linhas, e é por isso que os eventos de clique geralmente pousam em um lugar diferente da tabela de links. O post ingestão de cliques fire-and-forget detalha o lado da fila, e por que um armazenamento colunar supera o Postgres para análise de cliques explica a escolha de armazenamento. As análises do Elido seguem essa forma para que os cliques sejam consultáveis em segundos sem adicionar milissegundos ao redirecionamento.
O Que Você Ainda Tem Que Construir: Os Difíceis 80 Por Cento#
Aqui está a parte que os guias de design de sistemas deixam de fora. Um redirecionamento funcionando é talvez um quinto de um serviço real de encurtamento de URL. O restante é tudo que transforma uma demonstração em algo que você pode colocar na internet pública.
- Varredura de abusos e segurança. Um encurtador público é um alvo de phishing em poucas horas após o lançamento. Você precisa verificar os destinos em um feed de ameaças como o Google Safe Browsing e revarrer, porque um URL limpo na criação pode se tornar malicioso mais tarde. O checklist de segurança para encurtadores de URL é a lista completa.
- Limitação de taxa e idempotência. Um endpoint de criação aberto é explorado por scripts imediatamente. Você precisa de limites por chave e idempotência para que uma solicitação repetida não crie links duplicados. A mecânica está em limites de taxa de API e idempotência.
- Domínios personalizados com TLS. Links de marca significam emitir certificados para domínios que você não possui, sob demanda, sem etapas manuais.
- Dados de cliques seguros para GDPR. No momento em que você registra cliques você está processando dados pessoais. Truncar endereços IP e documentar a retenção não é opcional na EU, como GDPR para encurtadores de URL explica.
- Alta disponibilidade. Seu redirecionamento agora está no caminho crítico de cada link que alguém já compartilhou. O tempo de inatividade quebra o conteúdo de outras pessoas, então a barra de disponibilidade é mais alta do que para a maioria dos aplicativos.
Nada disso é exótico. São apenas muito trabalho sustentado, e nunca termina, o que é a razão honesta pela qual a maioria das equipes para no MVP e busca algo mantido.
Construir, Comprar ou Auto-Hospedar#
Construir você mesmo é a melhor forma de entender redirecionamentos, codificação e cache, e para uma ferramenta interna fechada o MVP pode ser tudo que você precisará. Construa. Você aprenderá mais em um fim de semana do que qualquer preparação para entrevista lhe dará.
Para qualquer coisa pública ou voltada para negócios, avalie a manutenção honestamente. O redirecionamento é livre; o tratamento de abusos, o TLS de domínio personalizado, o pipeline de análise e o plantão de suporte não são. Se você quiser o controle sem escrever do zero, pode auto-hospedar um serviço existente, e o Elido tem um caminho de auto-hospedagem exatamente para isso, com o post de opções de código aberto apresentando-as lado a lado. Se preferir terceirizar completamente, a solução para desenvolvedores e o início rápido de API e SDK fornecem um nível de redirecionamento de produção sem o backlog acima.
Relacionados no Blog#
- Como funcionam os encurtadores de URL - a introdução conceitual, sem código necessário.
- Atingir p95 abaixo de 15ms para redirecionamentos - o guia principal de engenharia sobre um caminho de redirecionamento otimizado.
- Estratégia de cache para redirecionamentos de URL - o cache de dois níveis em profundidade.
- Ingestão de cliques fire-and-forget - desacoplando análises do redirecionamento.
- Encurtadores de URL auto-hospedados - as opções de código aberto se você preferir não construir do zero.
Experimente Elido
Cole uma URL, obtenha um link curto
Sem cadastro. O link vive 30 dias. Cadastre-se para mantê-lo para sempre.
Grátis, sem necessidade de registo · 2 por dia