Design clássico · Pleno
Compartilhamento de fotos (Instagram/Flickr)
Projeto de entrevista clássico. Pontos centrais: entrega de blobs e vídeo e fan-out de feed.
Resposta curta
Projeto de entrevista clássico. Pontos centrais: entrega de blobs e vídeo e fan-out de feed. Um app de compartilhamento de fotos deixa a pessoa publicar imagens e vídeos e vê-los de volta, rápido, em qualquer lugar. Na versão de entrevista da Hello Interview, os requisitos centrais são criar posts com foto, vídeo e legenda e ver um feed cronológico de…
01 · CONTEXTO E ESCOPO
O que um app de fotos precisa fazer
Um app de compartilhamento de fotos deixa a pessoa publicar imagens e vídeos e vê-los de volta, rápido, em qualquer lugar. Na versão de entrevista da Hello Interview, os requisitos centrais são criar posts com foto, vídeo e legenda e ver um feed cronológico de quem se segue. Num exercício de levantamento de requisitos, o que torna o caso interessante não é a lista de posts, e sim o peso dos arquivos.
A mesma fonte pede que a mídia seja exibida quase instantaneamente e fixa tamanhos máximos para fotos e vídeos. Com arquivos desse porte, a pergunta passa a ser por onde os bytes viajam e onde eles moram.
02 · O CAMINHO INGÊNUO
Passar o arquivo pela API
O primeiro desenho que vem à mente faz o servidor de API receber o arquivo e repassá-lo ao armazenamento. A Hello Interview descreve exatamente esse fluxo e aponta que ele funciona para arquivos pequenos e quebra quando eles crescem. Já guardar o arquivo no banco de dados é pior: bancos são ótimos com dados estruturados e ruins com objetos binários grandes.
O app envia o arquivo inteiro para o servidor de API.
A API repassa os mesmos bytes ao armazenamento de objetos.
Só então grava no banco os metadados do post. Cada upload grande ocupa conexão e banda da API por todo o tempo da transferência.
O problema não é a correção, é o custo: a camada que deveria só decidir e autorizar vira um canal de transporte, e escalar uploads significa escalar servidores de API.
03 · UPLOAD DIRETO
URL pré-assinada: a API autoriza, o armazenamento recebe
O padrão de blobs grandes tira a API do caminho dos bytes: ela gera uma URL pré-assinada e o cliente envia o arquivo direto ao armazenamento de objetos, e depois baixa por uma CDN. Na S3, essa URL permite um upload sem que quem envia tenha credenciais da nuvem.
A URL vale pelo período definido quando foi gerada, e funciona como um token ao portador: quem a possui tem o acesso. Por isso o prazo deve ser curto e a chave do objeto deve ser escolhida pelo servidor, nunca pelo cliente.
O app pede ao serviço de posts permissão para enviar uma foto. O serviço decide a chave do objeto e devolve a URL pré-assinada.
Na mesma chamada, o serviço registra o post com estado pendente. Nenhum byte da foto passou por aqui.
O app envia o arquivo direto ao armazenamento de objetos usando a URL.
O armazenamento avisa a fila de que há um objeto novo, e o worker de imagens consome o aviso.
O worker gera as variações de tamanho, grava no armazenamento e marca o post como pronto no banco.
04 · ARQUIVOS GRANDES E PROCESSAMENTO
Partes, eventos e durabilidade
Para arquivos grandes, o upload em partes divide o objeto em pedaços enviados de forma independente. Se uma parte falha, só ela é reenviada, sem afetar as outras. A documentação da S3 recomenda esse modo para objetos de 100 MB ou mais, o que cobre vídeos e não costuma ser necessário para fotos comuns.
| Abordagem | Caminho dos bytes | Quando usar ou ponto fraco |
|---|---|---|
| Upload pela API | Cliente, API, armazenamento | Simples, mas a API vira gargalo com arquivos grandes |
| URL pré-assinada | Cliente direto ao armazenamento | Padrão para fotos; a API só autoriza |
| Upload em partes | Cliente direto, em pedaços | Vídeos e arquivos grandes; permite retomar partes que falharam |
Depois do upload, o processamento não precisa bloquear o usuário. O armazenamento pode publicar um evento de objeto criado para uma fila, um tópico ou uma função, e um worker gera as variações de tamanho. Esses eventos são entregues pelo menos uma vez, então o worker precisa tolerar o mesmo aviso duas vezes. É o papel clássico das filas de mensagens.
O armazenamento de objetos também resolve a durabilidade. O armazenamento padrão da S3 é projetado para durabilidade de 99,999999999% e guarda os objetos de forma redundante em no mínimo três zonas de disponibilidade. Perder o arquivo de uma foto é um dano que o usuário não perdoa, e é isso que justifica não guardá-lo em discos de servidores de aplicação.
05 · ENTREGA
A CDN na frente do armazenamento
Na leitura, o armazenamento de objetos vira a origem, e uma CDN fica na frente. Se a imagem já está no ponto de presença mais próximo, ela é entregue imediatamente; se não está, a CDN a busca na origem, e as próximas pessoas da região já encontram a cópia.
Ao abrir um post, o app recebe os metadados com a URL da variação adequada ao tamanho da tela.
O app pede a imagem à CDN, não ao armazenamento. A CDN responde pela cópia, se tiver.
Se a CDN não tem a imagem, busca na origem e guarda a cópia para os próximos pedidos.
Dois cuidados tornam o cache eficaz: dar a cada variação uma chave de objeto própria e nunca sobrescrevê-la, para que a cópia na CDN não fique velha, e servir a variação menor que atende a tela, para não gastar banda com pixels que ninguém vê.
Perguntas frequentes
O que é Compartilhamento de fotos (Instagram/Flickr)?
Projeto de entrevista clássico. Pontos centrais: entrega de blobs e vídeo e fan-out de feed.
O que o design de Compartilhamento de fotos (Instagram/Flickr) cobre?
Ele está organizado nestas seções: O que um app de fotos precisa fazer, Passar o arquivo pela API, URL pré-assinada: a API autoriza, o armazenamento recebe, Partes, eventos e durabilidade e A CDN na frente do armazenamento.
Quanto tempo leva Compartilhamento de fotos (Instagram/Flickr) e qual é o nível?
Leva cerca de 14 minutos para ler e tem nível Pleno.
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.