1) O documento discute a arquitetura do sistema de transferências entre contas NuConta do Nubank, incluindo microsserviços, event sourcing e consistência em sistemas distribuídos.
2) É apresentado o fluxo de transferência entre contas, com ênfase nos requisitos de processamento at-least-once e idempotência para garantir a consistência.
3) O Backend for Frontends (BFF) com GraphQL é descrito como forma de fornecer dados de forma flexível para diferentes versões de frontend.
2. Agenda
● NuConta
● Microsserviços no Nubank
● Transferindo dinheiro entre NuContas
○ Event-sourcing: Modularidade e Escalabilidade
○ Consistência em sistemas distribuídos
● O feed de movimentações
○ Backend for Frontends com GraphQL
25. Pedido de envio
RecebimentosEnvios
Saldos
Pedido
Envio Solicitado
Liquidação
Envio
Liquidação efetuada
Dinheiro enviado para
NuConta
Recebimento
Dinheiro
Recebido
Depósito
E se o cliente quiser enviar transferências para outra instituição financeira?
26. Pedido de envio
Envios
Saldos
Pedido
Envio Solicitado
Liquidação
Envio
Liquidação efetuada
Depósito
E se o cliente quiser enviar transferências para outra instituição financeira?
Dinheiro enviado
para outra
instituição
Integração
com o
banco
central
27. Pedido de envio
RecebimentosEnvios
Saldos
Pedido
Envio Solicitado
Liquidação
Envio
Liquidação efetuada
Dinheiro enviado para
NuConta
Recebimento
Dinheiro
Recebido
Depósito
E se o cliente receber transferências de outra instituição financeira?
29. Pedido de envio
RecebimentosEnvios
Saldos
Pedido
Envio Solicitado
Liquidação
Envio
Liquidação efetuada
Dinheiro enviado para
NuConta
Recebimento
Dinheiro
Recebido
Depósito
E se o cliente quiser pagar a fatura do cartão de crédito?
30. Pedido de Pagamento
Pagamento de
Fatura
Saldos
Pedido
Pagamento
Solicitado
Liquidação
Pagamento
Liquidação efetuada
Pagamento de fatura
Depósito
E se o cliente quiser pagar a fatura do cartão de crédito?
Cartão de
crédito
34. O que pode dar errado?
Pedido de envio
Envios
Liquidação
Saldos
Envio
Solicitado
Envio
Liquidação para envio
Recebimentos
Recebimento
Dinheiro enviado para
NuConta
Dinheiro
Recebido
Depósito
Pedido
35. O que pode dar errado?
Pedido de envio
Envios
Saldos
Envio
Solicitado
Envio
Liquidação para envio
Recebimentos
Recebimento
Dinheiro enviado para
NuConta
Dinheiro
Recebido
Depósito
Liquidação
Pedido
36. Primeiro requisito: Processamento at-least-once
Todo evento publicado é recebido e processado
completamente pelos consumidores pelo menos uma vez
38. Primeiro requisito: Processamento at-least-once
● Mensagens são persistidas e replicadas no Kafka cluster, podendo ser
consumidas a qualquer momento
● Próxima mensagem da fila será entregue de novo até que consumidor
confirme que completou seu processamento
● Consumidor só deve confirmar o processamento depois que completar todos
os efeitos colaterais
39. Segundo requisito: Idempotência
● Uma operação é idempotente se aplicá-la várias vezes é equivalente a aplicá-la
uma vez
● Exemplos:
○ Multiplicação por 0: 7*0 = 7*0*0 = 7*0*0*0 … = 0
○ DELETE FROM users WHERE users.id = 186
40. Segundo requisito: Idempotência
● Cada evento em nossa arquitetura tem um UUID aleatório
● Cada evento derivado usa o UUID do evento anterior (origem) como chave
única (chave de idempotência)
● Serviços garantem consistência interna: banco de dados local valida a chave
única
● Resultado: Criar um evento a partir de outro é uma operação idempotente
Liquidacao
ID: 78
Origem: PedidoDeEnvio:32
PedidoDeEnvio
ID: 32
48. Dados distribuídos = muitos requests
Envios
Pedido de envio
Envio
Recebimentos Recebimento
Saldos
Depósito
Liquidação
49. Evento de envio no feed
● Valor
● Data
● Status: pendente | falha | sucesso
Modelo do backend != visão do cliente
Liquidação Envio
404 | 404
404
Envios
Pedido de envio
Envio
Saldos
Liquidação
50. ● Lançar uma nova versão de um aplicativo numa app store pode demorar dias
● Muitos usuários continuam com versões antigas por muito tempo
● Bugfixes e otimizações demoram para chegar
● Frontend acoplado impede evoluções no backend
Ciclos de atualização lentos
52. "GraphQL is a query language designed to build client
applications by providing an intuitive and flexible syntax
and system for describing their data requirements and
interactions."
(GraphQL spec: http://facebook.github.io/graphql/)
53. Schema é o modelo disponível para o frontend
schema {
query: Query
}
type Query {
saldo(accountId: ID!): Float
feed(accountId: ID!):
[Envio | Recebimento]
}
type Recebimento {
data: Date
valor: Float
}
enum StatusEnvio {
PENDENTE, FALHA, SUCESSO
}
type Envio {
data: Date
valor: Float
status: StatusEnvio
}
Envios
Pedido de envio
Envio
Recebimentos Recebimento
Saldos
Depósito
Liquidação
54. Query define os campos que o client precisa
schema {
query: Query
}
type Query {
saldo(accountId: ID!): Float
feed(accountId: ID!):
[Envio | Recebimento]
}
type Recebimento {
data: Date
valor: Float
}
enum StatusEnvio {
PENDENTE, FALHA, SUCESSO
}
type Envio {
data: Date
valor: Float
status: StatusEnvio
}
query feedScreen($accountId: ID!) {
feed(accountId: $accountId) {
... on Envio {
data
valor
status
}
... on Recebimento {
data
valor
}
}
}
POST /api/query