Pular para o conteúdo

Design clássico · Pleno

Juiz online (LeetCode)

Projeto de entrevista clássico. Pontos centrais: sandbox, agendamento de jobs e rankings e leaderboards.

14 min de leitura · Conteúdo revisado em 23 de outubro de 2026

Resposta curta

Projeto de entrevista clássico. Pontos centrais: sandbox, agendamento de jobs e rankings e leaderboards. O exercício clássico é projetar uma plataforma como o LeetCode, que ajuda engenheiros a se preparar para entrevistas de programação e promove competições de código periódicas.

01 · CONTEXTO

Um juiz online em escala modesta

O exercício clássico é projetar uma plataforma como o LeetCode, que ajuda engenheiros a se preparar para entrevistas de programação e promove competições de código periódicas. O usuário vê a lista de problemas, abre um problema e escreve a solução em várias linguagens, envia o código e recebe retorno imediato, e acompanha um ranking ao vivo durante as competições.

Os requisitos não funcionais moldam o desenho: priorizar disponibilidade sobre consistência, garantir isolamento e segurança ao rodar código de usuário, devolver o resultado da submissão em até cinco segundos e escalar para competições com cem mil usuários.

Segundo a análise do Hello Interview, a plataforma real tem poucas centenas de milhares de usuários e cerca de quatro mil problemas. Em relação à maioria dos exercícios de design, é um sistema de escala pequena, e isso deve pesar nas escolhas.

02 · MODELO E API

Entidades, endpoints e arquitetura simples

Três entidades bastam. O problema guarda o enunciado, os casos de teste e a saída esperada; a submissão guarda o código enviado e o resultado da execução contra os casos de teste; e o ranking guarda a classificação das competições.

A API segue os requisitos um a um: uma listagem paginada de problemas, a leitura de um problema com o código inicial na linguagem pedida, o envio de uma solução e a leitura paginada do ranking de uma competição.

Para um sistema pequeno, a análise defende uma arquitetura cliente-servidor simples, até monolítica, porque o custo de gerenciar vários serviços não compensa. Para guardar os problemas, escolhe um banco NoSQL como o DynamoDB, já que não há consultas complexas e os casos de teste podem ficar aninhados como subdocumento do problema.

03 · EXECUÇÃO

Onde rodar código desconhecido

Rodar a submissão é o ponto em que o caso fica interessante. A opção ingênua, executar o código dentro do servidor da API, é descrita como um risco enorme de segurança. Além disso, o código roda no mesmo processo do servidor: se ele travar, derruba o servidor junto.

OpçãoO que ofereceLimite principal
Máquina virtualAmbiente isolado sobre o servidor, que pode ser reiniciado se algo der erradoConsome muitos recursos e demora a iniciar
ContêinerCompartilha o kernel do host e isola os processos da aplicação; é mais leve e inicia mais rápidoIsola menos que a máquina virtual e exige configuração cuidadosa para evitar fuga para o host
Função serverlessPequena, sem estado e disparada por evento; o provedor escala conforme a demandaA partida a frio adiciona latência na primeira requisição, e limites de recursos afetam execuções pesadas

A análise escolhe contêineres, um para cada linguagem suportada e reaproveitado entre várias submissões em vez de criar uma máquina virtual por envio. Prefere-os à função serverless porque não prevê grande variação no volume de submissões e quer evitar a latência de partida a frio.

  1. O cliente envia o código e o identificador do problema ao servidor de API, que os encaminha ao contêiner da linguagem escolhida.

    Diagrama da arquitetura: Execução da submissão em contêiner
    CLClienteenvia o código
    CPServidor de API
    CPExecutor em contêiner
    DBBanco de problemas e submissões
  2. O executor gerencia o contêiner da linguagem, que roda o código em um ambiente isolado.

    Diagrama da arquitetura: Execução da submissão em contêiner
    CLCliente
    CPServidor de API
    CPExecutor em contêinercontêiner da linguagem
    DBBanco de problemas e submissões
  3. O executor aciona o contêiner de forma síncrona, espera o término e lê a saída; o contêiner em si não faz chamadas de saída.

    Diagrama da arquitetura: Execução da submissão em contêiner
    CLCliente
    CPServidor de API
    CPExecutor em contêinersandbox
    DBBanco de problemas e submissões
  4. O servidor de API grava o resultado da submissão no banco e o devolve ao cliente.

    Diagrama da arquitetura: Execução da submissão em contêiner
    CLCliente
    CPServidor de API
    CPExecutor em contêiner
    DBBanco de problemas e submissõesresultado

04 · SANDBOX

Endurecendo o contêiner

Contêineres compartilham o kernel do host, então a configuração decide a segurança. A análise lista medidas adicionais, resumidas abaixo.

MedidaEfeito
Sistema de arquivos somente leituraCódigo montado como somente leitura; a saída vai para um diretório temporário apagado pouco depois
Limites de CPU e memóriaSe os limites forem excedidos, o contêiner é encerrado, evitando esgotamento de recursos
Tempo limite explícitoEncerra o processo que passar de um limite predefinido, o que também ajuda a cumprir o requisito de resposta em cinco segundos
Sem acesso à redeA rede do contêiner é desativada; na AWS, grupos de segurança e NACLs da VPC restringem o tráfego, exceto conexões essenciais
Chamadas de sistema restritasO seccomp limita as chamadas de sistema que o contêiner pode fazer, para não comprometer o host

05 · ESCALA

Picos de submissões: fila e contêineres

A conta da análise parte de um pico de dez mil submissões, cada uma rodando cerca de cem casos de teste, com uma premissa conservadora de cem milissegundos por caso. Isso dá um milhão de casos de teste, ou cem mil segundos de execução, e cerca de 1.667 núcleos para terminar em um minuto. A própria fonte nota que, na prática, a maioria dos casos termina em 10 a 50 ms.

Escalar na vertical não resolve: os maiores tipos de instância da AWS chegam a algumas centenas de vCPUs, e uma máquina grande e cara ficaria ociosa na maior parte do tempo.

A saída é escalar na horizontal os contêineres de cada linguagem, com grupos de auto scaling ajustando o número de instâncias à demanda. O único risco considerável é o superprovisionamento, que a fonte trata como administrável, já que a nuvem facilita subir e descer capacidade.

A análise ainda propõe uma fila gerenciada entre o servidor de API e os contêineres: a API enfileira a submissão e os contêineres retiram itens conforme ficam disponíveis. A execução pode levar vários segundos porque o código roda contra centenas de casos de teste, o que combina com o padrão de tarefas longas, em que a API devolve logo um identificador de trabalho e workers em segundo plano fazem o trabalho demorado.

  1. O cliente envia o código ao servidor de API, que coloca a submissão na fila em vez de executá-la na hora.

    Diagrama da arquitetura: Submissões com fila e executores
    CLCliente
    CPServidor de API
    QFila de submissõesbuffer
    CPExecutores em contêiner
    DBBanco de submissões
    CHCache do ranking
  2. Os executores retiram submissões da fila conforme ficam disponíveis. A fila ajuda a gerenciar a carga e permite tentar de novo se um contêiner falhar.

    Diagrama da arquitetura: Submissões com fila e executores
    CLCliente
    CPServidor de API
    QFila de submissõesbuffer
    CPExecutores em contêiner
    DBBanco de submissões
    CHCache do ranking
  3. Quando o executor obtém o resultado, avisa o servidor de aplicação.

    Diagrama da arquitetura: Submissões com fila e executores
    CLCliente
    CPServidor de API
    QFila de submissões
    CPExecutores em contêinerexecuta o código
    DBBanco de submissões
    CHCache do ranking
  4. O servidor atualiza ao mesmo tempo o banco e o cache.

    Diagrama da arquitetura: Submissões com fila e executores
    CLCliente
    CPServidor de API
    QFila de submissões
    CPExecutores em contêiner
    DBBanco de submissõesresultado
    CHCache do rankingranking
  5. Como a fila tornou o sistema assíncrono, o cliente consulta o resultado em intervalos, a cada segundo na proposta da fonte; o endpoint busca a submissão no banco.

    Diagrama da arquitetura: Submissões com fila e executores
    CLClienteconsulta o resultado
    CPServidor de API
    QFila de submissões
    CPExecutores em contêiner
    DBBanco de submissões
    CHCache do ranking

Alguns candidatos propõem uma conexão persistente, como WebSockets, para evitar o polling. A fonte diz que funcionaria, mas acrescenta complexidade e não é necessária com consulta a cada segundo.

06 · RANKING

Ranking ao vivo sem derrubar o banco

A fonte define a competição com noventa minutos de duração e até cem mil usuários. A pontuação é o número de problemas resolvidos e, em caso de empate, vale o tempo para concluir todos os dez problemas.

A versão ingênua consulta as submissões da competição, agrupa por usuário e ordena pelo número de problemas distintos resolvidos, e o cliente repete o pedido a cada poucos segundos. A própria análise avisa que isso coloca carga significativa no banco.

AbordagemComo funcionaLimite principal
Polling com consulta ao bancoA cada polling o servidor consulta o banco, ordena os usuários e devolve o topoCarga alta no banco e latência crescente com o número de usuários
Cache com atualização periódicaUm cache como o Redis guarda o ranking e é atualizado periodicamente a partir do bancoA atualização é tão recente quanto o refresh do cache, e o cliente ainda precisa consultar
Conjunto ordenado do RedisBanco e conjunto ordenado são atualizados a cada submissão processada, e o servidor devolve o topo da memóriaAtraso por polling de cerca de cinco segundos, aceitável para a maioria dos usuários

No Redis, o ranking fica em um conjunto ordenado com uma chave por competição: o valor é o identificador do usuário e a pontuação é o total ou o tempo de solução. Ao processar uma submissão, atualiza-se o conjunto com ZADD, e o topo é lido com ZRANGE em ordem reversa, com as pontuações.

  1. O cliente pede o ranking da competição e repete o pedido a cada cinco segundos.

    Diagrama da arquitetura: Ranking ao vivo com Redis
    CLClientepede o ranking
    CPServidor de API
    CHConjunto ordenado do Redis
    DBBanco de submissões
  2. O servidor lê o topo diretamente do conjunto ordenado em memória, sem consultas caras ao banco.

    Diagrama da arquitetura: Ranking ao vivo com Redis
    CLCliente
    CPServidor de API
    CHConjunto ordenado do Redisconjunto ordenado
    DBBanco de submissões
  3. Quando uma submissão é processada, o banco e o conjunto ordenado são atualizados.

    Diagrama da arquitetura: Ranking ao vivo com Redis
    CLCliente
    CPServidor de API
    CHConjunto ordenado do RedisZADD
    DBBanco de submissõessubmissão

O cliente recebe as primeiras páginas do topo e busca as seguintes conforme navega. A análise prefere polling a WebSockets, que seriam exagero para o número modesto de usuários e o atraso aceitável, e sugere até variar o intervalo, consultando com mais frequência no fim da competição.

07 · CASOS DE TESTE

Um conjunto de testes para qualquer linguagem

Escrever casos de teste por problema e por linguagem seria um pesadelo de manutenção. A saída é escrever um único conjunto por problema, executável em qualquer linguagem, com um formato padrão de serialização e um harness de teste por linguagem, que desserializa a entrada, passa ao código do usuário e compara com a saída esperada.

Para uma árvore binária, por exemplo, a análise serializa a entrada em um array por travessia em ordem de nível (BFS), e cada linguagem precisa de um harness capaz de reconstruí-la antes de chamar a solução do usuário.

08 · FECHAMENTO

Simplicidade com caminho para crescer

A fonte descreve como ideal um sistema bem simples, sem excesso de engenharia, mas com um caminho claro para escalar se for preciso. Para nível sênior, espera discutir prós e contras entre contêiner, máquina virtual e função serverless e justificar a escolha, além de sair do modo de desenhar caixas e explicar como rodar de fato os casos de teste.

Perguntas frequentes

O que é Juiz online (LeetCode)?

Projeto de entrevista clássico. Pontos centrais: sandbox, agendamento de jobs e rankings e leaderboards.

O que o design de Juiz online (LeetCode) cobre?

Ele está organizado nestas seções: Um juiz online em escala modesta, Entidades, endpoints e arquitetura simples, Onde rodar código desconhecido, Endurecendo o contêiner, Picos de submissões: fila e contêineres e Ranking ao vivo sem derrubar o banco.

Quanto tempo leva Juiz online (LeetCode) 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.