Resposta A: Anthropic Claude Opus 5
SERVIÇO DE NOTIFICAÇÃO EM TEMPO REAL — PLANO DE DESIGN DO SISTEMA
- RECAPITULAÇÃO DOS REQUISITOS E ESTIMATIVA DE CAPACIDADE
Matemática do tráfego:
- 100M DAU x 10 eventos/dia = 1B eventos de gatilho de notificação por dia.
- Média = 1B / 86.400 ≈ 11.600 eventos/segundo. Pico em 5x ≈ 58.000 eventos/segundo.
- Multiplicador de fan-out: a maioria dos eventos (curtir, comentar, seguir, DM) tem como alvo exatamente um destinatário, então o fan-out é de aproximadamente 1:1. No entanto, eventos de contas com muitos seguidores (uma celebridade postando) podem ter fan-out para milhões de destinatários; trate esses como...
Mostrar resposta completa ▼
SERVIÇO DE NOTIFICAÇÃO EM TEMPO REAL — PLANO DE DESIGN DO SISTEMA
- RECAPITULAÇÃO DOS REQUISITOS E ESTIMATIVA DE CAPACIDADE
Matemática do tráfego:
- 100M DAU x 10 eventos/dia = 1B eventos de gatilho de notificação por dia.
- Média = 1B / 86.400 ≈ 11.600 eventos/segundo. Pico em 5x ≈ 58.000 eventos/segundo.
- Multiplicador de fan-out: a maioria dos eventos (curtir, comentar, seguir, DM) tem como alvo exatamente um destinatário, então o fan-out é de aproximadamente 1:1. No entanto, eventos de contas com muitos seguidores (uma celebridade postando) podem ter fan-out para milhões de destinatários; trate esses como um caminho "fan-out em massa" separado. Assuma entrega de pico efetiva de 80.000–100.000 notificações/segundo, incluindo campanhas em massa.
- Armazenamento: histórico das últimas 100 notificações por usuário. Assuma ~400 bytes por linha -> 100 x 400B = 40KB/usuário -> 100M usuários ≈ 4TB de histórico quente, mais fator de replicação 3 ≈ 12TB. Facilmente particionável.
- Conexões: assuma 20–25% do DAU online simultaneamente no pico ≈ 20–25M de conexões WebSocket ativas. Com ~100K conexões por nó de gateway (Linux ajustado, epoll), são 200–250 nós mais margem.
Metas não funcionais:
- Latência p99 de ponta a ponta inferior a 2s para usuários online (medida desde a ingestão do evento até o ack do cliente).
- 99,9% de disponibilidade = ~43 minutos de inatividade por mês.
- Entrega pelo menos uma vez com desduplicação idempotente no lado do cliente/servidor.
- ARQUITETURA DE ALTO NÍVEL
O design é um pipeline orientado a eventos com uma divisão clara entre o caminho de ingestão (rápido, durável, otimizado para gravação) e o caminho de entrega (específico do canal, com tentativas).
Fluxo:
Serviços produtores (Serviço de Postagem, Serviço de Grafo Social, Serviço de Comentários, Serviço de Mensagens)
-> API/Gateway de Notificação (gRPC + REST, autenticação, limitação de taxa, validação de esquema, chave de idempotência)
-> Tópico Kafka notification.events (particionado por recipient_user_id quando conhecido, caso contrário por actor_id)
-> Serviço de Fan-out (resolve destinatários, expande eventos de celebridades, aplica regras de agregação)
-> Tópico Kafka notification.deliveries (uma mensagem por destinatário)
-> Serviço de Preferências e Políticas (consulta in-line via cache: opt-ins de canal, horários de silêncio, mudo/bloqueio, resumo vs. instantâneo)
-> Roteador / Despachante grava em tópicos por canal:
deliver.websocket, deliver.mobile_push, deliver.web_push, deliver.email
-> Trabalhadores de Canal:
Despachante WebSocket -> Consulta ao Registro de Conexões -> Nó do Gateway em Tempo Real -> cliente
Trabalhador de Push Móvel -> APNs (iOS) / FCM (Android)
Trabalhador de Push Web -> protocolo VAPID/Web Push via serviços de push do navegador
Trabalhador de E-mail -> SES / SendGrid, com renderização de modelo e agrupamento de resumos
-> Em paralelo, um consumidor de Histórico de Gravação persiste cada entrega no armazenamento de Histórico de Notificações e incrementa contadores de não lidos.
Transversal: Serviço de Modelos, Registro de Dispositivos, Registro de Conexões, Armazenamento de Desduplicação, Filas de Mensagens Mortas e um plano de Administração/Análise consumindo os mesmos fluxos Kafka.
- COMPONENTES CHAVE E RESPONSABILIDADES
Gateway de API de Notificação
- Ponto de entrada único para produtores internos (gRPC, esquemas protobuf em um registro) e para APIs de leitura do cliente (REST/GraphQL para histórico, marcar como lido, preferências).
- Responsabilidades: autenticação (mTLS serviço a serviço, JWT para clientes), limitação de taxa/quotas por locatário e por produtor, validação de solicitação, aceitação de chave de idempotência e anexo durável imediato ao Kafka. Retorna 202 Accepted rapidamente; não realiza trabalho de entrega in-line.
Ingestão de Eventos / Kafka
- Log durável e reproduzível.
notification.eventscom ~256 partições, fator de replicação 3, min.insync.replicas=2, acks=all, retenção de 7 dias para recuperação de reprodução e incidentes. - Fornece back-pressure e buffer natural para o pico de 5x, desacoplando produtores de provedores terceirizados lentos.
Serviço de Fan-out
- Resolve um evento em uma lista de destinatários. Para eventos 1:1, é um pass-through. Para eventos 1:N (nova postagem para seguidores, atividade de thread de grupo), ele consulta o Serviço de Grafo Social e emite mensagens de destinatário em lotes.
- Estratégia de fan-out híbrida: baseada em push (gravação por destinatário) para contas normais; baseada em pull/preguiçosa para contas acima de um limite de seguidores (por exemplo, 1M+), onde um único "marcador de feed" é gravado e os destinatários se materializam na leitura. Isso evita que um evento de celebridade crie uma tempestade de gravação de 50M mensagens no caminho quente.
- Limita a taxa de expansões em massa para um tópico Kafka separado de baixa prioridade para que nunca sufoquem as notificações interativas.
- Aplica agregação/coalescência: "Alice e outras 24 pessoas curtiram sua postagem" em vez de 25 linhas, usando uma janela deslizante curta (por exemplo, 30–60s) com chave (destinatário, post_id, tipo) no Redis.
Serviço de Preferências e Políticas
- Armazena e serve preferências de canal por usuário, opt-ins em nível de categoria, horários de silêncio com fuso horário, configurações de nível de dispositivo, listas de mudo/bloqueio e sinalizadores de consentimento legal (GDPR/CAN-SPAM).
- O caminho de leitura é armazenado em cache no Redis com invalidação write-through; meta de consulta p99 inferior a 5ms. Fonte da verdade em um armazenamento relacional.
- Aplica limitação de frequência (por exemplo, no máximo N pushes/hora por usuário) para proteger a experiência do usuário e as quotas do provedor.
Roteador / Despachante
- Mapeia uma entrega aprovada em itens de trabalho específicos do canal. Decide "apenas no aplicativo + WebSocket se online; caso contrário, push móvel" usando o Registro de Conexões e agenda resumos de e-mail em vez de envios instantâneos quando as preferências indicam isso.
Gateway em Tempo Real (camada WebSocket)
- Camada com estado mantendo conexões WebSocket persistentes (fallback: Server-Sent Events, depois long polling).
- Na conexão: autenticar, registrar (user_id, device_id) -> gateway_node_id no Registro de Conexões (Cluster Redis, TTL + atualização de heartbeat), em seguida, enviar qualquer backlog não lido.
- Na entrega: o despachante consulta o nó, envia via um fluxo gRPC interno ou um canal Kafka/Redis Pub/Sub por nó; o gateway grava no socket e aguarda um ack do cliente.
- Heartbeats a cada 30s; heartbeats perdidos removem a entrada do registro e futuras notificações caem automaticamente para o push móvel.
Trabalhadores de Canal
- Trabalhador de Push Móvel: agrupa para APNs (HTTP/2 multiplexado, autenticação baseada em token) e FCM. Lida com limites de concorrência por provedor, backoff exponencial com jitter e remove tokens de dispositivo inválidos/não registrados do Registro de Dispositivos.
- Trabalhador de Push Web: protocolo Web Push com chaves VAPID e criptografia de payload.
- Trabalhador de E-mail: renderiza modelos, suporta resumos instantâneos, horários e diários; lida com bounces/reclamações via webhooks do provedor e mantém uma lista de supressão.
- Todos os trabalhadores são consumidores idempotentes com chave por notification_id e gravam o status terminal de volta em um tópico
delivery.status.
Histórico de Gravação e Caminho de Leitura
- Consumidor que persiste notificações e mantém contadores de não lidos no Redis (contador autoritativo periodicamente reconciliado do armazenamento).
- A API de leitura atende às últimas 100 notificações do armazenamento de histórico, com um cache Redis da primeira página por usuário para leituras típicas de sub-10ms.
Serviços de Suporte
- Serviço de Modelos: modelos localizados e versionados com interpolação de variáveis; desacopla alterações de cópia de implantações de código.
- Registro de Dispositivos: token_dispositivo, plataforma, versao_app, local, fuso_horario, ultimo_visto.
- Armazenamento de Desduplicação: Redis com TTL de 24h em (producer_id, idempotency_key) para fazer com que pelo menos uma vez se comporte como efetivamente uma vez.
- Agendador: para notificações atrasadas/agendadas e janelas de resumo (filas agrupadas por tempo em conjuntos ordenados do Redis ou um agendador dedicado como uma escada de tópicos de atraso do Kafka).
- DLQ + Replayer: mensagens venenosas estacionadas e reproduzíveis após correções.
- MODELO DE DADOS E ESCOLHAS DE BANCO DE DADOS
a) Histórico de Notificações — Cassandra (ou ScyllaDB / DynamoDB)
Tabela: notifications_by_user
- Chave de partição: user_id
- Chave de clusterização: created_at DESC, notification_id
- Colunas: type, actor_id(s), target_type, target_id, aggregated_count, preview_text, image_url, deep_link, read_at, channels_sent, created_at
- TTL: 90 dias; a aplicação limita as leituras a 100 linhas.
Justificativa: o padrão de acesso é uma única chave de partição bem conhecida com uma fatia ordenada por tempo — exatamente o ponto forte da Cassandra. Ela oferece escalabilidade de gravação linear (precisamos de 60–100K gravações/segundo sustentadas), replicação masterless multirregional para disponibilidade, consistência ajustável (gravação QUORUM/LOCAL_QUORUM, leitura LOCAL_ONE para o feed) e TTL nativo para retenção. Não precisamos de junções ou transações de várias linhas aqui, então um armazenamento relacional apenas adicionaria dor de particionamento e risco de amplificação de gravação.
b) Contadores de não lidos e primeira página quente — Cluster Redis
- Contador inteiro
unread:{user_id}; - Lista JSON em cache
notif:page0:{user_id}.
Justificativa: os contadores são lidos a cada abertura do aplicativo (QPS extremamente alto, baixo valor por leitura) e devem ser de milissegundos de um único dígito. O Redis absorve isso de forma barata; os contadores da Cassandra são comparativamente caros e propensos a erros. Os contadores são reconciliados assincronamente para que a deriva se auto-corrija.
c) Preferências do usuário e tokens de dispositivo — PostgreSQL (particionado por user_id) com cache read-through Redis
Tabelas: user_preferences(user_id, category, channel, enabled, quiet_hours_start, quiet_hours_end, timezone, updated_at), devices(device_id, user_id, platform, push_token, locale, last_seen, active), suppression_list(email, reason, created_at).
Justificativa: esses dados têm baixo volume, são pesados em leitura, relacionais (usuários -> dispositivos -> configurações por categoria) e se beneficiam de transações e restrições para correção e auditabilidade (registros de consentimento têm peso de conformidade). O volume é pequeno o suficiente (~100M linhas) para particionar trivialmente e para armazenar em cache quase inteiramente.
d) Registro de Conexões — Cluster Redis
conn:{user_id}-> conjunto de {device_id, gateway_node_id, connected_at}, TTL 90s atualizado por heartbeat.
Justificativa: efêmero, rotatividade extremamente alta, deve ser rápido; a durabilidade é desnecessária porque uma entrada perdida degrada graciosamente para fallback de push.
e) Desduplicação / idempotência — Redis com TTL, sem backup (perda apenas arrisca um duplicado raro).
f) Modelos e configuração — PostgreSQL + armazenamento de objetos para ativos, armazenados em cache na borda.
g) Análise — eventos transmitidos do Kafka para um data lake (S3/Parquet) e data warehouse (Snowflake/BigQuery) para relatórios de taxa de entrega, taxa de abertura e latência; ClickHouse para dashboards operacionais quase em tempo real.
- RECOMENDAÇÕES DE PILHA DE TECNOLOGIA
- Linguagem/runtime: Go para o gateway, gateway em tempo real e trabalhadores (goroutines e baixa memória por conexão adequam-se a milhões de sockets); Java/Kotlin aceitável para agregação pesada em Kafka Streams.
- Mensagens: Apache Kafka (gerenciado: MSK/Confluent) como espinha dorsal; tópicos separados por canal e por classe de prioridade. Kafka Streams ou Flink para agregação/coalescência com janelas.
- Transporte em tempo real: WebSocket sobre TLS com SSE e fallbacks de long-poll; balanceamento de carga NLB/L4 com esvaziamento de conexão; roteamento fixo não é necessário, pois o registro armazena a identidade do nó.
- Cache: Cluster Redis (ou Elasticache/MemoryDB) para contadores, preferências, registro, desduplicação, limites de taxa.
- Armazenamentos de dados: Cassandra/ScyllaDB para histórico; PostgreSQL (Aurora) para preferências/dispositivos; S3 + data warehouse para análise.
- Provedores de push: APNs, FCM, Web Push (VAPID); e-mail via SES com SendGrid como provedor secundário atrás de uma camada de abstração de provedor para failover.
- Infraestrutura: Kubernetes com HPA/KEDA escalando em lag do consumidor Kafka (não apenas CPU), malha de serviço Envoy/Istio para mTLS e retentativas, Terraform para IaC.
- Observabilidade: rastreamento OpenTelemetry (id de rastreamento propagado do evento produtor para ack do cliente), métricas Prometheus + Grafana, logs estruturados em Loki/ELK, alertas PagerDuty em SLOs.
- Bibliotecas de resiliência: disjuntores e bulkheads para cada provedor externo, limitadores de taxa de token-bucket, backoff exponencial com jitter.
- ESTRATÉGIAS DE ESCALABILIDADE, LATÊNCIA E DISPONIBILIDADE
Escalabilidade
- Todos os componentes sem estado (API, fan-out, roteador, trabalhadores) escalam horizontalmente; a contagem de partições do Kafka é o teto de paralelismo, portanto, provisione partições para 5–10x o pico atual desde o primeiro dia (reparticionar é operacionalmente doloroso).
- Auto-escala em lag do consumidor com KEDA para que um pico de 5x acione o scale-out em segundos; mantenha um buffer quente de 30–40% de margem, pois a escala não é instantânea.
- Particione por user_id consistentemente entre Cassandra, Postgres e Redis para que os dados de um único usuário sejam co-localizados e a mitigação de partições quentes seja uniforme.
- Pistas de prioridade: notificações interativas (DM, comentário em sua postagem) usam um tópico de alta prioridade com grupos de consumidores dedicados; fan-out em massa/marketing/celebridade usa uma pista de baixa prioridade com limitação de taxa. Isso garante o SLO de 2s para as notificações que os usuários realmente notam.
- Tratamento de celebridades/chaves quentes via fan-out híbrido push/pull descrito acima, mais chaves de partição com sal para alvos extremamente quentes.
Baixa latência (p99 inferior a 2s)
- O caminho crítico é intencionalmente curto: anexo de API -> Kafka -> fan-out -> acerto de cache de preferência -> consulta de registro -> gravação WebSocket. Todas as consultas são Redis (sub-5ms); nenhuma gravação síncrona no banco de dados bloqueia a entrega.
- A persistência do histórico e a análise são assíncronas, fora do caminho de entrega.
- Produtores Kafka ajustados com linger.ms=5 e compressão (lz4) para equilibrar o lote em relação à latência; consumidores usam commit manual após o processamento.
- Implantação multirregional com usuários fixados na região mais próxima para reduzir o RTT; conexões WebSocket terminam nas bordas regionais.
- Janelas de agregação são configuráveis por tipo e desabilitadas para tipos críticos de latência, como DMs.
- Sondas sintéticas contínuas medem a latência real de ponta a ponta por região e por canal.
Alta disponibilidade (99,9% +)
- Nenhum ponto único de falha: multi-AZ para cada camada, Kafka RF=3 com min.insync.replicas=2, gravações Cassandra RF=3 com LOCAL_QUORUM, Postgres com standby síncrono e failover automatizado.
- Multi-região ativa-ativa para as camadas em tempo real e de entrega; Cassandra replica entre regiões de forma assíncrona, Postgres usa réplicas de leitura regionais com uma região de gravação designada.
- Degradação graciosa: se o caminho WebSocket estiver com defeito, retorne ao push móvel; se o cache de preferência estiver inativo, retorne ao Postgres e depois a padrões conservadores; se as gravações da Cassandra falharem, continue entregando em tempo real e reproduza as gravações de histórico do Kafka posteriormente.
- Tentativas com backoff exponencial mais jitter, tentativas limitadas, depois DLQ com alertas e uma ferramenta de reprodução.
- Disjuntores por provedor externo para que uma interrupção da APNs não possa esgotar os threads do trabalhador e parar o e-mail.
- Entrega pelo menos uma vez mais desduplicação de notification_id no servidor e cliente; os clientes também desduplicam na reconexão ao reproduzir o backlog não lido.
- Práticas de confiabilidade: exercícios de caos/game day (matar um nó de gateway e verificar o fallback de push), testes de carga em 5x pico, implantações blue-green e canary, flags de recursos para kill switches por canal, descarte de backpressure de tráfego de baixa prioridade antes de alta prioridade.
- GARRAFAS DE GARGALO E COMPROMISSOS
Prováveis gargalos
- Provedores terceirizados (APNs/FCM/e-mail): o teto mais difícil, pois a taxa de transferência não é nossa para escalar. Mitigar com pool de conexões sobre HTTP/2, loteamento, limitadores de taxa por provedor, failover multi-provedor para e-mail e suavização baseada em fila de picos.
- Fan-out de celebridades: uma única postagem pode gerar dezenas de milhões de entregas. Mitigado por push/pull híbrido, pistas de massa com limitação de taxa e agregação.
- Camada de conexão WebSocket: memória e descritores de arquivo por nó, mais reconexões em massa após uma implantação ou falha de rede. Mitigar com limites de kernel ajustados, reconexão escalonada com jitter e backoff exponencial imposto no lado do cliente, e esvaziamento lento de conexão durante implantações.
- Chaves quentes do Redis: chave de agregação de uma postagem viral ou um contador compartilhado. Mitigar com salting de chaves, caches locais na memória com TTL curtos e particionamento no lado do cliente.
- Amplificação de gravação da Cassandra e pressão de compactação a 100K gravações/segundo. Mitigar com compactação de janela de tempo (TWCS) adequada para dados de TTL de série temporal, e por não armazenar tipos de notificação de baixo valor no histórico.
- Desvio de partição Kafka se particionado por uma chave de baixa cardinalidade; sempre particionar por recipient_user_id no tópico de entrega.
Compromissos explícitos
- Pelo menos uma vez em vez de exatamente uma vez: exatamente uma vez entre provedores externos heterogêneos é impraticável e caro. Aceitamos duplicatas raras e as resolvemos com chaves de idempotência e desduplicação no lado do cliente — mais barato e muito mais disponível.
- Consistência eventual para contadores e histórico em vez de consistência forte: um selo de não lido que está momentaneamente incorreto em um é aceitável; latência de vários segundos para garantir que não esteja é inaceitável. Trabalhos de reconciliação limitam a deriva.
- Persistência poliglota em vez de um único banco de dados: isso aumenta a superfície operacional (três armazenamentos de dados mais Redis), mas cada carga de trabalho obtém o motor certo. Um único cluster Postgres se tornaria o gargalo a 1B gravações/dia; um único cluster Cassandra tornaria as auditorias de preferências e consentimento complicadas.
- Fan-out baseado em push para a maioria dos usuários, baseado em pull para celebridades: complexidade de código adicionada, mas é a única maneira de evitar tempestades de gravação ilimitadas.
- A agregação melhora a experiência do usuário e reduz drasticamente o volume de entrega, mas adiciona até uma janela de latência para tipos agregáveis. Mantemos janelas curtas e isentamos DMs.
- Multi-região ativa-ativa aumenta o custo e introduz sutilezas de consistência entre regiões, justificadas pelos alvos de disponibilidade e latência. Se o orçamento fosse restrito, uma postura de região única com standby quente ainda atenderia a 99,9%, mas com um RTO mais longo.
- Kafka em vez de uma fila gerenciada mais simples (SQS): mais sobrecarga operacional, mas precisamos de reprodução, partições ordenadas por chave, múltiplos grupos de consumidores independentes e retenção de 7 dias para recuperação de incidentes.
- Armazenar apenas as últimas ~100 notificações com um TTL de 90 dias troca a completude do arquivo por custo e desempenho de leitura; dados de longo prazo vivem no data lake de análise, se necessário.
- PLANO DE IMPLANTAÇÃO (FASADO)
Fase 1: API de Ingestão + Kafka + escritor de histórico + API de leitura (apenas notificações no aplicativo). Estabelece a espinha dorsal durável.
Fase 2: Gateway em tempo real, registro de conexões, contadores de não lidos, entrega WebSocket com fallback de push.
Fase 3: Trabalhadores de push móvel e push web, registro de dispositivos, serviço de preferências e horários de silêncio.
Fase 4: Resumos instantâneos e de e-mail, serviço de modelos, tratamento de supressão.
Fase 5: Agregação/coalescência, fan-out híbrido de celebridades, limitação de frequência.
Fase 6: Multi-região ativa-ativa, testes de caos, validação de carga 5x, dashboards de SLO e orçamentos de erro.
- MÉTRICAS CHAVE E SLOs
- Latência p50/p95/p99 de ponta a ponta por canal (SLO: p99 inferior a 2s para WebSocket).
- Taxa de sucesso de entrega por canal; taxas de erro do provedor e taxa de invalidação de token.
- Lag do consumidor Kafka por tópico (principal sinal de auto-escala e paginação).
- Contagem de conexões WebSocket, taxa de churn e taxa de ack.
- Deriva do contador de não lidos detectada pela reconciliação.
- Profundidade e idade do DLQ.
- Disponibilidade por API medida da perspectiva do cliente, rastreada contra um orçamento de erro mensal.
Resultado
Votos de vitória
3 / 3
Pontuação média
Pontuação total
Comentário geral
A Resposta A é um projeto excepcional e altamente concreto, com estimativas de capacidade quantificadas, caminhos de ingestão e entrega claramente separados, modelos de dados detalhados, filas de prioridade, fan-out híbrido, resiliência específica do canal, e medidas acionáveis de disponibilidade e latência. Seus pontos mais fortes são as configurações operacionais explícitas, planejamento de capacidade WebSocket, caminhos de degradação de falhas e uma análise incomumente completa de gargalos e trade-offs. A principal fraqueza é que não utiliza explicitamente um padrão de publicação de eventos outbox ou transacional nos serviços de origem, deixando uma lacuna potencial entre a transação de negócios originária e a ingestão durável no Kafka. Alguns detalhes de consistência multirregional também são tratados em um nível alto.
Ver detalhes da avaliação ▼
Qualidade da arquitetura
Peso 30%O pipeline durável orientado a eventos, tópicos de fan-out e canal separados, roteamento de políticas, registro de conexões, gateway em tempo real, escritor de histórico assíncrono e filas de prioridade formam uma arquitetura lógica com responsabilidades claras. A principal lacuna é a falta de um outbox explícito no serviço de origem, de modo que uma transação de negócios possa teoricamente ser confirmada sem que seu evento de notificação chegue à API de ingestão. A relação entre um registro de histórico lógico e múltiplas entregas de canal também poderia ser declarada com mais precisão.
Completude
Peso 20%Aborda todas as áreas solicitadas e vai além delas com estimativas de capacidade, dimensionamento de conexões, esquemas detalhados, comportamento do canal, controles de conformidade, observabilidade, fases de implantação e SLOs mensuráveis. Pequenas omissões incluem publicação transacional de origem e uma explicação mais exata de como o armazenamento impõe uma política estrita de últimos 100 em vez de apenas limitar leituras e aplicar TTL.
Análise de trade-offs
Peso 20%A resposta examina explicitamente e corretamente entrega pelo menos uma vez versus exatamente uma vez, consistência eventual versus forte, persistência poliglota, fan-out push versus pull, latência de agregação, custo multirregional, Kafka versus filas mais simples e limites de retenção. Os trade-offs são vinculados aos requisitos e acompanhados por estratégias de mitigação, em vez de serem listados abstratamente.
Escalabilidade e confiabilidade
Peso 20%O projeto quantifica o tráfego médio e de pico, estima a capacidade simultânea de WebSocket, dimensiona consumidores por lag do Kafka, reserva headroom quente, isola tráfego prioritário, lida com fan-out de celebridades e especifica replicação multizona, configurações de quorum, novas tentativas, DLQs, disjuntores, caminhos de fallback, testes de carga e exercícios de caos. Alguns comportamentos de dados regionais ativo-ativo e atomicidade de eventos de origem requerem mais detalhes.
Clareza
Peso 10%Apesar de seu comprimento, a organização numerada, o fluxo explícito, os componentes nomeados, os esquemas e as seções separadas para dimensionamento, disponibilidade, gargalos, implantação e métricas tornam o plano fácil de navegar. Algumas declarações são excessivamente confiantes ou comprimidas, como chamar o particionamento de 100 milhões de linhas de trivial, e algumas semânticas de canal/histórico poderiam ser formuladas com mais cuidado.
Pontuação total
Comentário geral
Uma resposta excepcional que exemplifica um projeto de sistema de nível sênior. É abrangente, bem estruturada, quantitativamente fundamentada e demonstra um profundo entendimento de trade-offs e realidades operacionais. O projeto é altamente detalhado, com escolhas tecnológicas específicas e estratégias concretas para escalabilidade e confiabilidade. A inclusão de um plano de lançamento faseado e uma seção dedicada a métricas/SLOs o eleva além de um projeto puramente teórico, fazendo com que pareça um documento pronto para produção.
Ver detalhes da avaliação ▼
Qualidade da arquitetura
Peso 30%A arquitetura é excepcionalmente sólida, detalhada e bem articulada. O fluxo orientado a eventos é claro e a separação de responsabilidades entre componentes como a API, o serviço Fan-out e os workers específicos do canal é excelente. A inclusão de uma estratégia híbrida de fan-out push/pull para contas de celebridades demonstra um entendimento sofisticado do espaço do problema.
Completude
Peso 20%Esta resposta é excepcionalmente completa. Aborda todas as partes da solicitação em grande detalhe e vai além, incluindo uma estimativa de capacidade detalhada, um plano de lançamento faseado e uma seção dedicada a métricas chave e SLOs. Este nível de detalhe é o que se esperaria do documento de projeto de um engenheiro sênior.
Análise de trade-offs
Peso 20%A discussão sobre gargalos e trade-offs é excelente. Não apenas identifica problemas potenciais, mas também lista explicitamente os compromissos de design feitos, como a escolha de entrega at-least-once em vez de exactly-once e o uso de persistência poliglota. O raciocínio é aguçado, conciso e demonstra uma perspectiva de engenharia madura.
Escalabilidade e confiabilidade
Peso 20%As estratégias de escalabilidade e confiabilidade são detalhadas e concretas. Menciona abordagens específicas como auto-scaling com base no atraso do consumidor Kafka com KEDA, uso de filas de prioridade para diferentes tipos de tráfego e implementação de uma escada de degradação graciosa. A inclusão de práticas como engenharia de caos mostra uma abordagem proativa à confiabilidade.
Clareza
Peso 10%A resposta é excepcionalmente clara e bem estruturada. O uso de seções numeradas, um diagrama de fluxo baseado em texto no início e bullet points concisos torna a grande quantidade de informações técnicas muito fácil de seguir e digerir. O fluxo lógico dos requisitos às métricas é impecável.
Pontuação total
Comentário geral
A é um documento de design de nível de equipe próximo. Ele começa com cálculos concretos de capacidade (eventos/segundo, dimensionamento de armazenamento, contagens de conexões WebSocket e estimativas de nós), em seguida, percorre uma divisão clara de ingestão vs. entrega com detalhes de configuração específicos (contagens de partições Kafka, configurações de replicação, acks, retenção), um fan-out híbrido push/pull para contas de celebridades, filas de prioridade para proteger o SLO de 2s, modelos de dados por loja com justificativas explícitas, uma escada de degradação graciosa, práticas de caos/game-day, um plano de lançamento faseado e métricas de SLO. A seção de trade-offs é excepcional: cada escolha (at-least-once vs. exactly-once, persistência poliglota, Kafka vs. SQS, custo de latência de agregação, custo multirregional) é declarada com a alternativa e por que foi rejeitada. Pontos fracos menores: a densidade pode torná-lo uma leitura pesada e não discute o padrão outbox para durabilidade do evento do lado do produtor.
Ver detalhes da avaliação ▼
Qualidade da arquitetura
Peso 30%Arquitetura excepcional: divisão clara de ingestão/entrega, fan-out híbrido push/pull com um limite concreto de seguidores, filas de prioridade garantindo o SLO de 2s para eventos interativos, camada de conexão dimensionada (20-25M de soquetes, ~100K por nó) e topologia Kafka específica (256 partições, RF=3, min.insync.replicas=2, retenção de 7 dias). As responsabilidades dos componentes são precisas e o caminho crítico é deliberadamente mantido livre de gravações síncronas no banco de dados.
Completude
Peso 20%Cobre todos os requisitos do prompt mais extras: estimativa de capacidade com cálculos de armazenamento, modelos de dados completos para seis lojas com justificativas, todos os quatro canais, resumos, conformidade (GDPR/CAN-SPAM, listas de supressão), observabilidade com SLOs, um plano de lançamento faseado e uma seção dedicada a gargalos/trade-offs. Nada do prompt está faltando.
Análise de trade-offs
Peso 20%Seção de trade-offs excepcional: cada decisão nomeia a alternativa e por que foi rejeitada (at-least-once vs. exactly-once, persistência poliglota vs. banco de dados único, Kafka vs. SQS, fan-out push vs. pull, custo ativo-ativo vs. standby quente, latência de agregação vs. volume). Os trade-offs são incorporados às justificativas em toda parte, não confinados a uma única seção.
Escalabilidade e confiabilidade
Peso 20%Concreto e quantificado: justificativa de superprovisionamento de partições, escalonamento automático KEDA por atraso do consumidor com 30-40% de headroom quente, chaves quentes salgadas, compactação TWCS para taxa de gravação, configurações explícitas de replicação e quorum de Cassandra/Postgres/Kafka, escada de degradação graciosa, disjuntores por provedor, testes de caos e validação de carga 5x, e ferramentas de replay de DLQ. Liga diretamente os mecanismos às metas de 100M DAU / 5x pico / 99,9%.
Clareza
Peso 10%Excelente estrutura numerada, desde os requisitos até o lançamento e as métricas; o diagrama de fluxo em forma de texto facilita o acompanhamento do pipeline. A densidade de detalhes ocasionalmente torna as seções pesadas, mas os títulos e a formatação consistente as mantêm navegáveis.