Larissa Campos
Submitted on Oct 17, 2026, 9:48 AM
Evaluated on Oct 17, 2026, 9:55 AM
The score is an AI recommendation; the decision is yours.
Evaluation
Final score = 70% diagram + 30% defense of the follow-up questions.
Scores by dimension
Strengths
- Uso de fila SQS para desacoplar a ingestão de eventos do sistema de pagamentos externo, garantindo que o fluxo de checkout não seja bloqueado.
- Armazenamento de regras de campanha no S3 com recarga periódica em memória, atendendo ao requisito de alterar regras sem a necessidade de deploy.
Weaknesses
- Violação da restrição de eventos fora de ordem: a solução não descreve como tratar um reembolso que chega antes da confirmação da compra, o que pode falhar ou gerar inconsistências.
- Implementação de idempotência baseada em verificação prévia (check-then-act: consulta antes de inserir) sem constraint de unicidade no banco, suscetível a race conditions em entregas concorrentes no SQS.
- Controle de concorrência frágil no resgate (checkout): checar saldo na API antes de subtrair via UPDATE expõe o sistema a resgates concorrentes que podem deixar o saldo negativo, violando a regra de nunca ficar abaixo de zero.
- Modelagem de dados baseada em mutação direta de saldo (`UPDATE clientes SET saldo = ...`) em vez de um modelo formal de livro-razão (ledger) append-only como fonte primária da verdade.
Missing components
- Dead Letter Queue (DLQ) ou fila de reprocessamento para eventos fora de ordem e falhas
Suggestions
- Adicionar uma constraint de chave única (UNIQUE) em `purchase_id` no MySQL para garantir idempotência a nível de banco de dados e evitar créditos duplicados mesmo com múltiplos workers paralelos.
- Utilizar atualização atômica condicional no checkout (`UPDATE clientes SET saldo = saldo - :valor WHERE id = :id AND saldo >= :valor`) ou padrão de reserva temporária para assegurar que o saldo nunca fique negativo.
- Modelar uma tabela de ledger (extrato append-only) contendo eventos imutáveis (crédito, débito, estorno) e derivar o saldo acumulado a partir dela.
- Implementar uma tabela de 'operações pendentes' ou Dead Letter Queue (DLQ) com retentativa para acomodar eventos de reembolso que cheguem antes da compra confirmada.
Integrity signals
Recorded by the candidate's browser during the design and the defense. They are signals to review, not proof: a second monitor, a notification or pasting one's own notes also create records. And no records doesn't rule anything out, because another device, such as a phone, doesn't show up. These records don't change the score.
- Left the tab or window 4× for 7 min 5 s in total.
- Pasted text 2×: 1,340 characters in total; the largest paste had 910.
- Copied parts of the statement 1× (640 characters in total).
Timeline
Time counted from the start of each step.
- Design 02:50Copied 640 characters from the statement
- Design 07:50Left the tab for 1 min 35 s
- Design 18:50Left the tab for 2 min 20 s
- Design 32:50Left the tab for 1 min 20 s
- Design 36:00Pasted 910 characters into the explanation
- Design 36:30Left the tab for 1 min 50 s
- Defense 03:20Pasted 430 characters into answer 2
Diagram and explanation
On a phone the diagram is shown smaller. You can pinch to zoom, but it reads better on a computer.
Candidate's explanation
O sistema de pagamento manda a compra para uma fila SQS. Um worker lê a fila, carrega as regras de um JSON no S3 (recarrega a cada 5 minutos) e calcula o valor do cashback. Para não creditar duas vezes, o worker consulta se a compra já está na tabela de cashback antes de inserir. Se não estiver, insere a compra e faz UPDATE clientes SET saldo = saldo + valor. Quando chega reembolso, o worker faz o mesmo cálculo e subtrai do saldo. A API de cashback responde saldo e extrato direto do MySQL. No checkout, a API confere se o saldo é suficiente e faz o UPDATE subtraindo o valor usado. Para escalar, aumento o número de workers e uso réplicas de leitura no MySQL se precisar.
Defense questions
1. Sua estratégia contra duplicidade e resgates baseia-se em consultar o banco antes de atualizar ('check-then-act'). Como você evita condições de corrida tanto entre workers concorrentes processando a mesma mensagem SQS em paralelo quanto em múltiplos resgates simultâneos no checkout para garantir que o saldo nunca fique negativo?
Dá para usar uma transação com SELECT FOR UPDATE na linha do cliente antes de atualizar o saldo, assim dois workers não atualizam ao mesmo tempo. No checkout faço a mesma coisa.
Answer review5.0
O uso de SELECT FOR UPDATE resolve a concorrência imediata no checkout para evitar saldo negativo, mas não soluciona a idempotência na ingestão de mensagens duplicadas da SQS sem uma restrição única explícita no banco de dados. A resposta não aborda constraints de unicidade nem mecanismos de idempotency key para evitar inserções duplicadas caso duas transações concorrentes chequem a existência da compra.
2. Uma das restrições críticas é que eventos podem chegar fora de ordem (um reembolso antes da compra) e podem existir reembolsos parciais. Como o seu worker lida com o cálculo e persistência se a mensagem de estorno chegar antes da confirmação original da compra?
Em sistemas distribuídos, a ordenação de mensagens não é garantida. Uma abordagem comum é utilizar filas FIFO, que garantem a entrega na ordem de envio, combinadas com deduplicação baseada em um identificador único da mensagem. Assim, os eventos de uma mesma compra são processados na sequência correta e o estorno só é aplicado depois do crédito, evitando inconsistências no saldo do cliente e garantindo a integridade dos dados.
Answer review3.0
A resposta sugere filas FIFO como solução genérica, mas ignora a premissa explícita do desafio de que o sistema de pagamento é externo e os eventos chegam fora de ordem da origem. Faltou propor um padrão de compensação, retenção em estado pendente ou tabela de eventos desordenados para reconciliar o estorno quando a compra de fato for processada.
3. Para aplicar a regra de teto (cap) mensal de cashback por cliente sob um pico de 400 compras por segundo, como você estrutura a modelagem e bloqueios no MySQL para evitar gargalos de lock contention ou consultas agregadas pesadas a cada transação?
Eu guardaria um campo total_mes na tabela de clientes e somaria ali a cada crédito. Como cada cliente compra poucas vezes, não acho que vai ter muita disputa de lock.
Answer review4.5
A criação de um acumulador desnormalizado por cliente simplifica a verificação do teto e evita agregações pesadas na leitura. Contudo, a resposta não detalha o ciclo de virada de mês (reset do campo) nem o controle transacional caso ocorram reembolsos ou concorrência no fechamento do teto mensal.