Pular para o conteúdo

Design clássico · Júnior

Encurtador de URL

Hash ou contador? Base62, colisões, cache de redirecionamento e 100:1 de leitura para escrita.

12 min de leitura · Conteúdo revisado em 22 de outubro de 2026

Resposta curta

Hash ou contador? Base62, colisões, cache de redirecionamento e 100:1 de leitura para escrita. Um encurtador de URL recebe um endereço longo e devolve um código curto. Quando alguém abre o link curto, o sistema descobre o endereço original e redireciona. É simples de explicar e por isso é um bom primeiro exercício de levantamento de requisitos.

01 · CONTEXTO E REQUISITOS

O que um encurtador precisa fazer

Um encurtador de URL recebe um endereço longo e devolve um código curto. Quando alguém abre o link curto, o sistema descobre o endereço original e redireciona. É simples de explicar e por isso é um bom primeiro exercício de levantamento de requisitos.

Os requisitos funcionais são só dois: criar o link curto e redirecionar a partir dele. Um terceiro, opcional, é permitir que a pessoa escolha o próprio alias. Entre os requisitos não funcionais, três mandam no desenho: cada código aponta para uma única URL longa, o redirecionamento é rápido e o serviço fica quase sempre no ar, com disponibilidade acima de consistência.

02 · ESTIMATIVA DE ESCALA

Contas de guardanapo

O livro da ByteByteGo parte de cem milhões de URLs criadas por dia, o que dá cerca de mil e cem escritas por segundo. Com uma razão de dez leituras para cada escrita, são mais de onze mil leituras por segundo. Em dez anos seriam 365 bilhões de registros e, com URLs de cerca de cem bytes, em torno de 36,5 TB.

A Hello Interview usa outras premissas: um bilhão de URLs e cem milhões de usuários ativos por dia, com uma proporção de mil cliques para cada link criado. As duas fontes discordam na razão entre leitura e escrita, e isso é esperado: estimativa é hipótese, não fato. O que importa é a conclusão comum de que a leitura domina muito a escrita.

03 · API E MODELO DE DADOS

Dois endpoints e uma tabela

A API tem uma rota para criar, por exemplo um POST em /urls, e outra para redirecionar, um GET que recebe o código curto e responde com um redirecionamento HTTP para a URL longa.

O modelo de dados é uma tabela que liga o código à URL longa. Na versão mais simples do livro ela tem três colunas: id, código curto e URL longa. A chave de busca é o código curto, porque é ele que chega em cada clique.

  1. O navegador envia a URL longa para a API do encurtador.

    Diagrama da arquitetura: Encurtador: primeira versão
    CLNavegador
    CPAPI do encurtador
    DBBanco de mapeamentos
  2. A API decide um código curto e grava o par código e URL longa no banco.

    Diagrama da arquitetura: Encurtador: primeira versão
    CLNavegador
    CPAPI do encurtadorgera o código
    DBBanco de mapeamentosgrava o par
  3. Depois, quem abre o link curto faz um GET com o código; a API consulta o banco e devolve o redirecionamento.

    Diagrama da arquitetura: Encurtador: primeira versão
    CLNavegador
    CPAPI do encurtador
    DBBanco de mapeamentosbusca pelo código

Esta primeira versão funciona, mas deixa em aberto a pergunta central do caso: como a API decide o código curto?

04 · GERAR A CHAVE CURTA

Hash ou contador, e o papel da base62

Há duas famílias de solução. A primeira aplica uma função de hash, como CRC32, MD5 ou SHA-1, à URL longa e usa só os primeiros caracteres do resultado. A saída de um hash parece aleatória, e esse resultado costuma ser codificado em base62.

Base62 usa letras minúsculas, maiúsculas e dígitos. Com sete caracteres há cerca de 3,5 trilhões de combinações, mais do que as 365 bilhões de URLs da estimativa. Com oito caracteres são cerca de 218 trilhões.

O problema do hash é a colisão: duas URLs diferentes podem gerar o mesmo código, e com mais URLs guardadas a chance de duplicata cresce. Resolver consultando o banco a cada pedido é caro. Duas defesas são uma restrição UNIQUE na coluna do código e um filtro de Bloom, que responde rápido e usa pouca memória se um código já existe.

A segunda família usa um contador. Cada URL recebe o próximo número, convertido em base62. Como cada número é único, não há colisão. O custo é depender de um gerador de IDs únicos, e códigos sequenciais são previsíveis, o que permite enumerar links.

CritérioHash + base62Contador + base62
ColisãoPossível e precisa ser resolvidaNão ocorre, pois cada ID é único
Dependência extraNão precisa de gerador de IDsDepende de um gerador de IDs únicos
PrevisibilidadeCódigo sem relação com a ordem de criaçãoCódigos sequenciais podem ser enumerados

Para esta versão de nível júnior, o contador é a escolha mais simples de explicar e evita o tratamento de colisões. Nesse desenho, o serviço de escrita pede ao contador, por exemplo um Redis, um número único e converte para base62. Como Redis é de thread única e tem operações atômicas, ele serve de contador; para não pedir um número a cada escrita, cada instância pode reservar um lote de valores.

  1. O navegador envia a URL longa; o balanceador a encaminha a uma instância do serviço de escrita.

    Diagrama da arquitetura: Encurtador: geração da chave
    CLNavegador
    NWBalanceador
    CPServiço de escrita
    CHContador (Redis)
    DBBanco de mapeamentos
  2. O serviço de escrita pede um número ao contador. Cada valor devolvido é único, por isso não há colisão.

    Diagrama da arquitetura: Encurtador: geração da chave
    CLNavegador
    NWBalanceador
    CPServiço de escrita
    CHContador (Redis)número único
    DBBanco de mapeamentos
  3. O serviço converte o número para base62 e grava o par código e URL longa no banco.

    Diagrama da arquitetura: Encurtador: geração da chave
    CLNavegador
    NWBalanceador
    CPServiço de escritaconverte
    CHContador (Redis)
    DBBanco de mapeamentosgrava o par
  4. Para não ir ao contador a cada escrita, a instância pode reservar um lote de valores e consumir localmente.

    Diagrama da arquitetura: Encurtador: geração da chave
    CLNavegador
    NWBalanceador
    CPServiço de escrita
    CHContador (Redis)menos chamadas
    DBBanco de mapeamentos

05 · CACHE E REDIRECIONAMENTO

Leitura rápida: cache e o código 301 ou 302

Como as leituras dominam, vale pôr um cache em memória, como Redis ou Memcached, na frente do banco. Boa prática: o tempo de vida (TTL) do cache deve ser igual ou menor que a expiração da URL, para o cache nunca servir um link já vencido. Separar o serviço de leitura do de escrita permite escalar cada lado de forma independente.

  1. O navegador abre o link curto; o balanceador envia o clique a uma instância de leitura.

    Diagrama da arquitetura: Encurtador: leitura com cache
    CLNavegador
    NWBalanceador
    CPServiço de leitura
    CHCache de redirecionamentos
    DBBanco de mapeamentos
  2. O serviço de leitura consulta o cache. Se o código está lá, responde de imediato sem tocar no banco.

    Diagrama da arquitetura: Encurtador: leitura com cache
    CLNavegador
    NWBalanceador
    CPServiço de leitura
    CHCache de redirecionamentosacerto
    DBBanco de mapeamentos
  3. Se o código não está no cache, o serviço busca no banco, guarda o resultado no cache e responde.

    Diagrama da arquitetura: Encurtador: leitura com cache
    CLNavegador
    NWBalanceador
    CPServiço de leitura
    CHCache de redirecionamentosguarda o código
    DBBanco de mapeamentosfalha do cache

Falta escolher o código HTTP do redirecionamento. O 301 diz que a URL mudou para sempre: o navegador guarda a resposta e os cliques seguintes nem chegam ao encurtador. O 302 diz que a mudança é temporária: todo clique passa de novo pelo serviço.

Critério301 (permanente)302 (temporário)
NavegadorGuarda a resposta em cacheNão guarda; volta ao encurtador a cada clique
Carga no servidorMenorMaior
Análise de cliques e controle do linkPerde parte dos cliquesRegistra cliques e permite atualizar ou expirar o link

Se o objetivo é reduzir carga, o 301 faz sentido; se importam análise de cliques e poder de atualizar ou expirar links, o 302 é a escolha melhor. A Hello Interview adota o 302 em seu desenho.

06 · EVOLUÇÃO E LIMITES

O que muda quando o sistema cresce

Com mais tráfego, o cache e o banco precisam dar conta de mais leituras. Com seis caracteres o espaço acaba em cerca de 56 bilhões de URLs, e então é preciso passar a sete. Em várias regiões, cada uma pode receber faixas separadas do contador, para não repetir números.

Perguntas frequentes

O que é Encurtador de URL?

Hash ou contador? Base62, colisões, cache de redirecionamento e 100:1 de leitura para escrita.

O que o design de Encurtador de URL cobre?

Ele está organizado nestas seções: O que um encurtador precisa fazer, Contas de guardanapo, Dois endpoints e uma tabela, Hash ou contador, e o papel da base62, Leitura rápida: cache e o código 301 ou 302 e O que muda quando o sistema cresce.

Quanto tempo leva Encurtador de URL e qual é o nível?

Leva cerca de 12 minutos para ler e tem nível Júnior.

Agora projete você mesmo

Rode este caso como uma entrevista na escola de System Design: você toma as decisões, o tutor as questiona e você vê a nota do seu desenho.