Casos de uso: Modernização de Mainframe, Camada de Dados Operacionais
Setores: Serviços financeiros
Produtos MongoDB: MongoDB Atlas, MongoDB pipeline de agregação, Change Streams
Visão Geral da Solução
O core banking é o mecanismo que executa o banco. Ele gerencia clientes, contas, saldos, pagamentos e eventos financeiros, e todos os canais, produtos e sistemas de relatório downstream dependem dele.
Essa centralidade é o que torna o núcleo tão difícil de modernizar. Muitos bancos ainda dependem de dados fragmentados, esquemas fixos, janelas de lote e integrações ponto a ponto. À medida que novos produtos, canais e requisitos regulatórios surgem, a complexidade geralmente aumenta.
A solução? Modernize o core banking com a Banking Industry Architecture Network (BIAN) e o MongoDB.
BIAN define a arquitetura de negócios. MongoDB a implementa como uma plataforma de dados componível, orientada a eventos e de propriedade do domínio.
BIAN: A arquitetura de destino
A Banking Industry Architecture Network (BIAN) define o framework BIAN— um padrão do setor bancário que modela a funcionalidade como domínios de serviço.
A definição de operações bancárias como domínios de serviço oferece a cada equipe um conjunto de responsabilidades bem definidas para possuir, o que produz:
Contextos delimitados mais claros: cada domínio de serviço tem um escopo e uma finalidade definidos.
Propriedade de dados mais clara: um domínio possui cada objeto de negócio e seus dados.
Limites de API mais claros: os domínios têm interação por meio de contratos padrão, em vez de acesso compartilhado ao banco de dados.
Menos desvio semântico: um vocabulário compartilhado mantém os termos consistentes em todas as equipes e sistemas.
MongoDB: A plataforma de dados de implementação
O MongoDB implementa o modelo de domínio de serviço BIAN na prática. Cada necessidade bancária mapeia para uma funcionalidade nativa do MongoDB:
O document model se encaixa em dados bancários hierárquicos, como registros de clientes, contas e KYC aninhados.
As transações ACID de vários documentos executam a movimentação síncrona de dinheiro em um único commit.
Os fluxos de alteração propagam eventos financeiros em tempo real, sem pesquisa.
Os validadores de esquema e os pipelines de agregação impõem regras de contabilidade próximas aos dados.
Esta solução mostra como modernizar o sistema bancário principal incrementalmente sem interromper os pipelines de entrega.
Arquiteturas de referência
A solução é dividida em três serviços de backend FastAPI. Cada serviço possui uma responsabilidade distinta no fluxo de dinheiro de ponta a ponta.
O serviço de contas possui o estado do cliente e da conta. Ele expõe operações alinhadas ao BIAN para dados de referência de partes e funcionalidades de conta corrente.
Serviço de transações é responsável pela iniciação e execução de pagamentos. Ele grava o resultado do pagamento operacional de forma síncrona como uma transação ACID do MongoDB.
Serviço de Razão gerencia o pipeline de contabilidade. Ele reage assincronamente a transações executadas e gera os registros do lado financeiro necessários para lançamento em sub-razão e diário.
Essa separação é fundamental para a arquitetura. A execução de pagamentos, o estado da conta e a verdade contábil estão relacionados, mas não são a mesma preocupação. O design os mantém conectados por meio da linhagem de dados, permitindo que cada serviço evolua dentro de seus próprios limites.
Figura 1. Arquitetura de alto nível: Core Banking com BIAN e MongoDB.
Os canais entram através do aplicativo e do limite de serviço.
Os usuários interagem com a solução por meio da IU da Web. O frontend atua como a camada de canal e roteia solicitações para o serviço de backend relevante por meio de roteamento baseado em caminho. Os serviços expõem pontos de extremidade no estilo BIAN, para que a camada de interface permaneça alinhada às funcionalidades de negócios em vez de vazar a estrutura do banco de dados.
O serviço de contas possui a verdade do cliente e da conta.
O serviço de contas lê e grava as coleções
customerseaccounts. Ele atua como a fonte da verdade para dados mestre de clientes, contexto de conta relacionado a KYC, saldos e operações de ciclo de vida da conta. Este é o caminho de leitura síncrona para recuperação de conta e saldo.O serviço de transações executa o pagamento de forma síncrona.
Quando um pagamento é iniciado, o serviço de transações o processa como uma ACID transaction de vários documentos do MongoDB. Na solução, essa unidade de trabalho debita o saldo da conta de origem, credita o saldo da conta de destino, insere o registro da transação, atualiza o status do pagamento e grava notificações ou alterações de status relacionadas em um commit.
Os saldos das contas operacionais são atualizados imediatamente no fluxo de transações, enquanto o fluxo do ledger atualiza o ledger geral de forma assíncrona. O ledger geral é publicado separadamente, em lote, ao final da janela de publicação.
O MongoDB se torna a fonte de eventos para propagação contábil.
O caminho do ledger não pesquisa alterações e não depende de um barramento de mensagens externo na solução. Em vez disso, o serviço de ledger observa a coleção
transactionspor meio de streams de alteração do MongoDB. Cada transação recém-inserida se torna o trigger para processamento contábil assíncrono.Esta é a transferência arquitetônica entre a execução operacional e o financeiro em processamento.
Figura 2. O serviço de livro-razão.
clique para ampliarO estágio 1 do Ledger Service grava o objeto de limite contábil.
O primeiro trabalhador do livro-razão consome o fluxo de alterações da transação e grava um documento
ledgerEventpara cada pagamento. Esse documento carrega a interpretação contábil do evento de negócios, incluindo as pernas de débito e crédito e o contexto de lançamento necessário a jusante. Antes que o evento seja gravado, o trabalhador verifica se as pernas de débito e crédito estão equilibradas.Esse controle é importante porque
ledgerEventsé a primeira coleção de contabilidade imutável no fluxo. Os dados gravados aqui devem ser precisos antes de se propagarem parasubLedgerEntriesejournalEntries.Arquitetonicamente,
ledgerEventsé a coleção de limites entre o domínio de pagamento e o domínio financeiro. Ele desvincula a velocidade de pagamento da velocidade de contabilidade, preservando a linhagem de volta ao pagamento de origem.O estágio 2 do Ledger Service projeta entradas de contabilidade em nível de entidade.
O segundo trabalhador do livro-razão observa
ledgerEventse projeta cada evento em doissubLedgerEntries: um débito e um crédito. Ele grava essas entradas juntas em uma ACID transaction e revalida que o evento está equilibrado e que ambas as contas GL são folhas de lançamento válidas no gráfico de contas.Este estágio cria a verdade contábil de nível de entidade usada para declaração do cliente e visualizações de posição intradiária.
O Estágio 3 do Serviço de Razão publica o razão geral.
Um trabalhador em lote reconcilia periodicamente as entradas pendentes do sub-razão e as transforma em
journalEntriesequilibrados. Se a reconciliação falhar, o ciclo ignora a postagem. Se for bem-sucedido, o trabalhador grava as entradas do diário, carimba o identificador do diário resultante de volta nos registros de origem e inverte seu status de postagem.Mesmo para pagamentos em tempo real, o livro-razão geral é publicado em lote. O sub-razão, não o GL, é a fonte precisa para saldos intradiários. O esquema suporta um modo de publicação REALTIME para instituições que optam por publicar por transação, mas esta solução usa publicação GL em lote, consistente com a prática padrão do setor.
A plataforma preserva a rastreabilidade de ponta a ponta, bidirecionalmente, tornando o design auditável.
O fluxo de dados é totalmente rastreável nas camadas de negócios e contabilidade, em ambas as direções. Um pagamento passa de pagamentos para transações, depois para
ledgerEvents, depois parasubLedgerEntriese, finalmente, parajournalEntries. Cada lançamento de diário pode ser rastreado através da mesma cadeia até o pagamento de origem. Essa linhagem bidirecional oferece suporte à IU de rastreamento de pipeline, auditabilidade e clareza arquitetônica para consumidores downstream.
Abordagem do modelo de dados
O modelo de dados segue a mesma separação arquitetônica dos serviços. Cada coleção existe porque serve a um propósito comercial ou contábil distinto no fluxo.
Coleções operacionais
customersarmazena o registro mestre do cliente e o contexto KYC aninhado.accountsarmazena o estado da conta corrente e atua como a fonte da verdade para saldos.paymentsarmazena instruções de pagamento e estado do ciclo de vida, como PENDING e SETTLED.transactionsarmazena fatos de pagamento e se torna a fonte de eventos para o pipeline do livro-razão.
Essas coleções dão suporte ao lado operacional da arquitetura. Eles servem diretamente aos fluxos de trabalho de clientes e contas e são atualizados de forma síncrona pelos serviços de contas e transações.
Coleções de contabilidade
glAccountsarmazena o gráfico de contas e valida o que pode ser publicação.ledgerEventsarmazena um registro de limite contábil por transação.subLedgerEntriesarmazena os lançamentos de débito e crédito no nível da entidade.journalEntriesarmazena as entradas equilibradas do livro-razão geral.
Fluxo de dados
O fluxo é deliberado, as etapas a seguir resumem como as coleções participam do fluxo do processo:
Uma instrução de pagamento chega em pagamentos.
A execução de pagamento síncrona grava o fato da transação executada resultante em
transactionse atualiza os saldos da conta operacional.Um fluxo de alterações nas transações aciona o pipeline do livro-razão.
O estágio de ingestão do ledger grava um
ledgerEventpor transação.Um evento de ledger contém ambas as pernas e o modo de postagem que decide seu caminho downstream.
Documento de amostra: evento de livro-razão
{ "eventId": "LE-20260415-000042", "idempotencyKey": "PAY-20260415-0042", "groupId": "GRP-20260415-000042", "eventType": "PAYMENT_PRINCIPAL", "debitLeg": { "glAccountCode": "1001", "controlAccountCode": "1000", "amount": { "$numberLong": "100000" }, "currency": "USD", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001234" } }, "creditLeg": { "glAccountCode": "2100", "controlAccountCode": "2000", "amount": { "$numberLong": "100000" }, "currency": "USD", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001235" } }, "postingMode": { "type": "BATCH" }, "postingStatus": "PENDING", "sourceReference": { "sourceCollection": "transactions", "sourceId": "PAY-20260415-0042", "sourceSystem": "LEDGER_PIPELINE" } } O estágio de projeção grava dois
subLedgerEntriespor evento.O trabalhador de projeção transforma um
ledgerEventem doissubLedgerEntries, um por perna, gravados juntos em uma ACID transaction. Cada um é uma perna de publicação completa;journalEntryIdcarrega o sentinela""até quegl_batchcarimbe o ID real.Documento de amostra: entrada de sub-razão
{ "subLedgerId": "SLE-20260415-000042-D", "idempotencyKey": "LE-20260415-000042:DEBIT", "controlAccountCode": "1000", "side": "DEBIT", "amount": { "$numberLong": "100000" }, "currency": "USD", "periodCode": "2026-04", "status": "POSTED", "journalEntryId": "", "entityReference": { "entityType": "ACCOUNT", "entityId": "ACC-001234" }, "sourceReference": { "sourceCollection": "ledgerEvents", "sourceId": "LE-20260415-000042", "sourceSystem": "LEDGER_PIPELINE" } } Seu crédito de balanceamento é um segundo documento — mesmo
sourceId, opostosideecontrolAccountCode,entityId:ACC-001235. O índice parcial emjournalEntryId($gt: "") exclui ambos até que o lote preencha o ID real do registro no diário.O caminho do lote grava
journalEntriesbalanceados.O lote agrega entradas de sub-razão em um diário cujas linhas balanceadas vivem em um array incorporado.
Documento de amostra: entrada no diário
{ "journalId": "JNL-20260623-EOD-1001", "idempotencyKey": "BATCH-20260623-EOD:1000:2026-06", "periodCode": "2026-06", "journalType": "LEDGER_EVENT_POSTING", "status": "POSTED", "totalAmount": { "$numberLong": "1000000" }, "entries": [ { "lineNumber": 1, "accountCode": "1000", "side": "DEBIT", "amount": { "$numberLong": "1000000" }, "currency": "USD" }, { "lineNumber": 2, "accountCode": "2000", "side": "CREDIT", "amount": { "$numberLong": "1000000" }, "currency": "USD" } ] } Os validadores impõem as invariantes contábeis
Três validadores de coleção empurram as regras contábeis para o banco de dados, de modo que uma gravação que ignora a camada de serviço ainda não pode corromper os livros. O validador
ledgerEventsexige os campos de negócios e aplica um bloqueio apostingStatusem umenumconhecido._LEDGER_EVENTS_VALIDATOR = {"$jsonSchema": { "bsonType": "object", "required": ["eventId", "idempotencyKey", "groupId", "occurredAt", "valueDate", "eventType", "debitLeg", "creditLeg", "postingStatus", "sourceReference", "mappingVersion"], "properties": { "postingStatus": {"bsonType": "string", "enum":["PENDING", "POSTED", "FAILED"]}, "debitLeg": _LEG_SCHEMA, "creditLeg": _LEG_SCHEMA, }, }} O validador
subLedgerEntriesbloqueiasideparaDEBITouCREDITestatusparaPOSTEDouFAILED, e exigejournalEntryIdem cada documento — o sentinela""satisfaz isso até quegl_batchcarimbe o ID real, para que uma entrada nunca possa ficar fora desse ciclo de vida.O validador
journalEntriesimpõe o invariante de saldo Pacioli diretamente: a soma das linhas de débito deve ser igual à soma das linhas de crédito, verificada com$exprem cada gravação._JOURNAL_BALANCE_VALIDATOR = {"$expr": {"$eq": [ {"$sum": {"$map": {"input": {"$filter": {"input": "$entries", "as": "e", "cond": {"$eq": ["$$e.side", "DEBIT"]}}}, "as": "e", "in": "$$e.amount"}}}, {"$sum": {"$map": {"input": {"$filter": {"input": "$entries", "as": "e", "cond": {"$eq": ["$$e.side", "CREDIT"]}}}, "as": "e", "in": "$$e.amount"}}}, ]}} As coleções de contabilidade dão suporte ao lado financeiro da arquitetura. Eles são derivados de eventos operacionais, não escritos diretamente pelas contas ou serviços de transações.
Essa cadeia oferece velocidade operacional e controle de contabilidade. A execução do pagamento não aguarda a postagem completa do GL, mas cada pagamento ainda se resolve em um rastro contábil auditável.
Por que o MongoDB é um ajuste natural?
Os dados do cliente e da conta são hierárquicos e evoluem ao longo do tempo. Os registros de pagamento carregam metadados variáveis por trilho e canal. As entradas do livro-razão agrupam fatos contábeis relacionados em documentos comerciais únicos.
No MongoDB, você pode armazenar o estado da conta, detalhes do ciclo de vida, contexto KYC, fatos de pagamento e linhas de postagem incorporadas em formas que correspondem à forma como os serviços produzem e consomem dados. Você evita o nivelamento e a remontagem repetidos que um modelo relacional exigiria.
Construir a solução
Esta seção mostra como implementar o BIAN usando o MongoDB e, em seguida, como replicar a solução BIAN do Leafy Bank. Para o guia de implementação completo, clone o repositório e siga as instruções de configurar no README do Github.
Implementar BIAN com MongoDB
Defina o escopo de implementação de destino.
Comece com um pequeno conjunto de domínios de serviço conectados que suportam uma jornada de negócios de ponta a ponta. O escopo inicial de modernização de um banco típico também pode incluir o onboarding e o serviço completo de conta corrente. Nesta solução, o escopo é prático e restrito, e deliberadamente reduzido a:
Dados de referência de partes e clientes
Estado e saldos da conta corrente
Iniciação e execução de pagamentos
Contabilidade financeira
Isso é importante porque o framework BIAN é mais útil quando define os limites de propriedade antes do início da implementação.
Separe a execução de negócios da execução contábil.
Mantenha a execução de pagamentos e a contabilização financeira como preocupações distintas. Processe o pagamento como um evento operacional primeiro e, em seguida, derive os registros contábeis de forma assíncrona do fluxo de transações executadas.
Isso permite que os pagamentos e a contabilidade sejam executados em sua própria velocidade, mantendo o fluxo contábil totalmente auditável em ambas as direções, do pagamento ao lançamento no diário e vice-versa.
Mapeie domínios de serviço para coleções próprias.
Deixe cada serviço possuir suas coleções e exponha-as por meio de APIs, não acesso compartilhado ao banco de dados.
Contas possui o estado do cliente e da conta.
Transações possui registros de iniciação e execução de pagamento.
O Ledger possui registros do lado financeiro, como eventos de ledger, entradas de sub-ledger e entradas de diário.
Use referências entre domínios quando necessário, mas não compartilhe a propriedade de gravar.
Mantenha a semântica BIAN na camada de contrato.
Exponha nomes de API alinhados ao BIAN e limites de serviço externamente. Internamente, permita que os desenvolvedores trabalhem com nomes de campo simples e familiares: o registro bianMappings contém a única fonte de verdade que vincula cada campo interno ao seu nome canônico BIAN. Isso oferece alinhamento de padrões sem forçar os desenvolvedores a trabalhar com um modelo de persistência excessivamente detalhado.
Forçar regras contábeis na camada de dados.
Não deixe as verificações de integridade financeira apenas para o código de serviço. Use transações, validadores e índices do MongoDB para forçar a idempotência, postagens equilibradas e imutabilidade do diário próximo aos dados.
Este padrão BIAN + MongoDB é o contexto de que você precisa antes de replicar o próprio repositório.
Replique a solução BIAN do Leafy Bank
Faça um clone do repositório e siga as instruções de configurar.
Vá para o repositório do GitHub e siga as instruções no README para:
Prepare os pré-requisitos
Clone o repositório e instale as dependências
Provisione o banco de dados MongoDB
Configurar os serviços de backend
Configurar o proxy de frontend
Crie índices e validadores de ledger
Preencha os dados de amostra
Iniciar os serviços
Validar o fluxo de ponta a ponta
Execute o caminho em contêiner (se necessário)
Principais Aprendizados
Nesta biblioteca de soluções, você aprendeu a:
Use o framework BIAN para definir a arquitetura de destino: os domínios de serviço criam limites de negócios, propriedade de dados e contratos de API mais claros.
Mantenha a execução do pagamento e a publicação do razão separadas: A arquitetura atualiza o estado operacional de forma síncrona e o estado contábil de forma assíncrona.
Use o MongoDB em ambos os fluxos: transações ACID, streams de alterações, validadores e pipelines de agregação suportam o padrão completo em uma plataforma.
Trate ledgerEvents como um limite de controle: valide as pernas de contabilidade equilibradas antes que os dados entrem no fluxo financeiro imutável.
Organize coleções em torno do fluxo de processo: Cada coleção deve suportar um estágio distinto e preservar a linhagem em toda a arquitetura.
Modernize incrementalmente: comece com domínios de alto valor e estenda a plataforma sem uma substituição completa do núcleo.
Autores
Doina Brestoiu
Kiran Tulsulkar
Ainhoa Mugica
Andrea Alaman Calderon