DEV Community

Guilherme Marcial
Guilherme Marcial

Posted on • Updated on

Core Pay: System Design

Index


Introdução

Este artigo é a abertura e explicação da solução inicial do projeto Core Pay 💰, uma iniciativa pessoal CoreLab 📦.

Um sistema central(core) para soluções financeiras(vulgo fintechs) comuns ou disruptivas, servindo como a interface principal para operações financeiras base 💰.


O Problema

Com o boom das fintechs, sempre tenho visto uma nova que não conhecia, indo des de negócios comuns e de contextos genéricos como contas digitais, e-wallets, pagamentos, plataformas de moeda eletrónica, crédito até disruptivos, aplicados em contextos e setores específicos como imobiliário, automobilístico, logística, beneficios, autopeças e por assim vai, mas no final todos têm em comum operações financeiras para realizar e dar vida a suas soluções.

Para cada uma dessas soluções é necessário o desenvolvimento dessa base, ao invés de apenas focar no desenvolvimento da solução principal, utilizando um sistema pronto para essa responsabilidade.


A Solução

Expectativa de uso

A ideia é que novas soluções financeiras genéricas ou disruptivas possam ter como alternativa utilizar um sistema open-source central para realizar as operações financeiras base, podendo assim focar no desenvolvimento das soluções específicas do negócio.

Pensado para que seja implantado internamente como a principal interface para operações financeiras, onde os demais sistemas integrariam com flexibilidade e configurabilidade ao mesmo para compor a solução como um todo.

Atuando principalmente como domínio financeiro das soluções.


Atributos de qualidade

Representam as capacidades necessárias identificadas que a arquitetura precisa ter para poder suportar e atender o produto concebido, tornando uma solução que atende ao negócio.

Para que isso aconteça, essas capacidades serviram de guia da concepção e evolução da arquitetura no seu alto a baixo nível, refletindo diretamente nas implementações e o que se espera das funcionalidades, para que esteja alinhada e continue alinhada como uma solução para o negócio.

O objetivo é deixar expresso e registrado as capacidades identificadas, resumidamente expressar o conceito e uma breve justificativa, que estará aprofundada, expressa detalhadamente no ciclo de desenvolvimento e medidas continuamente.

Base

Capacidades base para contribuir para a vida útil da aplicação, possibilitando ser continuamente funcional, mantida e evoluída, sem estar presa aos criadores, possibilitando também por novos contribuidores e mantenedores.

  • Readability
  • Testability
  • Evolvability
    • Modifiability
    • Modularity
    • Simplicity

Negócio

Capacidades requisitadas para que o negócio possa ser suportado além do produto ser funcional, é preciso que além da entrega da funcionalidade, a aplicação opere essa funcionalidade conforme a demanda e dentro do contexto do negócio.

  • Auditability
  • Atomicity
  • Isolability
  • Consistency
  • Durability
  • Integrity
  • Security
  • Availability

Infraestrutura

Capacidades requisitadas para que a aplicação possa ser suportada, para conforme as necessidades a aplicação operar.

  • Observabiltity
  • Configurability
  • Fault Tolerance
  • Scalability
  • Performance
Mais detalhes na documentação do projeto.

Features

Algumas das features relacionas ao core business:

Transaction account

  • Check balance
  • Deposit
  • Withdraw
  • Pay
  • Transfer
  • Account statement and receipt
  • Open
  • Close
  • Block
  • Unlock

Lending/Loan

  • Overdraft
  • Active
  • Desactive
  • Adjust limit
  • Pay back

Credit

  • Active
  • Desactive
  • Check limit
  • Adjust limit
  • Adjust use limit
  • Pay
  • Instalment pay
  • Credit statement and receipt
  • Invoice
  • Pay Invoice

Ledger

  • ...

Algumas das features relacionas a plataforma/infraestrutura:

  • Autenticação e autorização segregada para o provedor OIDC, atraves de uma interface configurável.
  • Aspectos arquiteturais de event-driven, onde os comportamentos do sistema produzem eventos, permitindo interfaces flexíveis para implementar e aplicar diferentes comportamentos necessários.
  • Possibilidade de integração com a API, optando entre interfaces REST, GRPC ou ambas.
  • Agnóstico aos sistemas integrados que compõem a arquitetura, acionados por portas e adaptadores, definindo interfaces que expressam bem o que se espera de possíveis implementações, permitindo a utilização de outras soluções ao invés do padrão.
  • Auditoria de todos os comportamentos do sistema.
  • Observabilidade em diferentes níveis e formas, configurável e flexível sobre interfaces bem definidas, possibilitando substituir as implementações padrão.
    • Structured logging
    • Monitoring
    • Tracing
    • Metrics
    • APM
  • Escolher entre comunicação insegura ou segura autenticando apenas o servidor ou mútua, incluindo o cliente.
  • Flexível para compor e se encaixar em sua arquitetura como uma interface interna central de operações financeiras downstream, suportando suas soluções / produtos que possuem regras de negócios específicas, como e-wallets, bank, etc.
  • Uso da estratégia de "in-memory database" para operações financeiras.
  • Uso inicial de sharing como padrão para escalar horizontalmente o in-memory data, de forma configuravel.

Resumo

Ciclo do pedido da realização de uma operação financeira, foreground a nível do request:

1- Core Pay através de uma das interfaces da api, recebe uma requisição referente a um pedido de operação financeira, junto ao serviço de autorização, utiliza o access token para verificar se quem solicitou tem permissão para realizar essa operação.
2- Caso o solicitante seja autorizado, a partir desse pedido, é feito as validações que forem necessárias, aceitando o pedido caso esteja válido para ser processado, publicando em uma fila de pedidos a serem processados de forma assíncrona.
3- Responde que o pedido foi aceito.


Ciclo do processamento do pedido da realização de uma operação financeira, background:

4- É consumido da fila o pedido de operação financeira.
5- É feita novas validações se necessário.
6- Obtém as contas envolvidas na operação direto do serviço de cache e realiza a operação.
7- Com a operação realizada, persiste as informações no banco, atualiza o estado das contas no serviço de cache e publica no serviço de mensageria os eventos ocorridos dessa operação, necessários para que outros sistemas interessados possam consumir e trabalhar.

Resumidamente sem detalhes técnicos profundos, ainda fica muito obscuro e por parte da engenharia, está aberto muitas dúvidas, mas os design das implementações estarão abertas, documentadas e detalhadas junto ao projeto conforme o ciclo de desenvolvimento vai ocorrendo.


Arquitetura e explicação detalhada

Alt Text

Clique aqui e amplie a imagem para melhor visualização

1- Representação de outros sistemas que compõem a solução como um todo, podendo os mesmos terem contextos e responsabilidades diferentes dentro da solução, mas que são downstream ao Core Pay, pois precisam realizar operações financeiras e elas afetam diretamente a conta que o usuário final possui, que esta no dominio, responsabilidade e especialidade do Core Pay.

Por exemplo, realizar ou receber uma transferência interna ou externa, debito automatico, alguma espécie de cobrança, depósito, saldo, extrato e tudo que envolva diretamente o valores financeiros do usuário final, pode ser que passem diversos outros sistemas, como integrações com órgãos reguladores, mas no final acabaram no Core Pay para aplicação na conta alvo.


2- Representação de onde o sistema Core Pay se propõe se encaixar nas possíveis soluções, sendo um sistema core interno, servindo como a principal interface para operações financeiras, que afetam as contas que estão sob seu domínio.

A comunicação poderá ser feita tanto através da interface REST quanto a GRPC, pois ambas interfaces irão expor as mesmas funcionalidades, possibilitando a flexibilidade de optar por uma ou ambas.

Por se tratar de um sistema crítico, seria ideal estar em uma infraestrutura segura, mas sendo totalmente opcional o como e onde o implementar, como por exemplo utilizar VPN ou VPC e etc.

2.1- Não é uma restrição do projeto obrigar a implementação do Core Pay com outros sistemas com diferentes objetivos agindo na borda como dns, load balancers, proxy reverse, api gateway, WAF e etc, mas sim a premissa da flexibilidade de poder implantar o Core Pay como melhor entender e necessitar, podendo fazer suas próprias escolhas baseado em seu contexto, optando por ter essas soluções na borda ou não.

2.2- Não é uma restrição do projeto ditar a forma como implementar o Core Pay, ficando a critério se haverá apenas uma instância, um cluster, em containers, usando kubernetes e etc, dependendo apenas da solução que deseja alcançar com o contexto que estiver inserido.

Mas é necessário prover a infraestrutura de serviços upstream da qual o Core Pay se integra e são essenciais para sua operação.


3- Representam os serviços upstream necessários que uma infraestrutura provisionada para servir o Core Pay precisa ter, sendo a ideia ilustrar esses serviços como interfaces, representando a premissa do projeto de ter a flexibilidade de ser possível implementar o contrato dessas interfaces e utilizar diferentes diferentes serviços quando possível.

Por exemplo, o comportamento necessário para ser alcançado com o serviço de cache estará definido, por padrão o provider padrão será do redis, mas caso o memcached ou outro sistema de cache também possa atender, novos providers podem ser implementados e utilizados, sendo assim para todos os outros serviços.

Além da possibilidade de utilizar diferentes providers/adapters para cada serviço, o Core Pay é burro em relação a infraestrutura provisionada e não impõe nenhuma restrição, apenas precisa utilizar dela para funcionar, mas como é configurada, quais suas características e comportamentos, depende da sua necessidade e o que deseja alcançar, para que assim possa atender os diversos contextos e problemas.

Por exemplo, você pode disponibilizar uma simples instância até algo altamente disponível.

3.1- Representa a interface referente ao serviço da camada de identidade da plataforma/solução como um todo, idealmente responsável por autenticar e autorizar os usuários e clientes da plataforma, não somente do Core Pay.

O Core Pay não tem conhecimento sobre quem são os usuários, clientes, identidade e o que cada um está autorizado a fazer, apenas tem domínio das permissões definidas para realização de suas operações, sempre utilizando o serviço responsável por autenticar e autorizar para validar a autenticidade da identidade e se tem autorização/permissão para fazer a operação solicitada.

Inicialmente o provider padrão será baseado em OIDC/OAUTH2 providers.

3.2- Representa a interface referente ao serviço de cache, sendo um dos mais importantes e críticos, base para a estratégia de “in-memory database”, que tem o objetivo de alta performance com baixa latência e alto throughput nas operações financeiras.

O design idealizado lida com problemas de concorrência, consistência e uso otimizado e correto da memória.

No caso do serviço de cache, como uma característica da arquitetura do Core Pay, escalar e alcançar alta disponibilidade será utilizado shards, distribuídos entre diferentes instâncias do serviço, sendo assim necessário provisionar um cluster com as características necessárias para alcançar a escala desejada.

Inicialmente o provider padrão será baseado no Redis.

3.3- Representa a interface referente ao serviço de mensageria, utilizado para processamento e comunicação assíncrona, interface dos eventos ocorridos do Core Pay, sendo um componente muito importante para o processamento sincronizado das operações financeiras.

O Core Pay, na proposta inicial da arquitetura, é tanto o produtor quanto um dos consumidores de suas próprias mensagens, sejam comportamentos primários como operações financeiras ou após, estimulados por eventos próprios de comportamentos que ocorreram, como notificar que uma transação financeira ocorreu com sucesso.

Inicialmente o provider padrão será baseado no RabbitMQ.

3.4- Representa a interface referente ao serviço de armazenamento/persistência, a base de dados do Core Pay, por exemplo, onde é efetivado o resultado das operações financeiras após serem processadas com sucesso.

Inicialmente o provider padrão será baseado no Postgresql.


4- Outros sistemas internos downstream que são consumidores dos eventos publicados pelo Core Pay e precisam fazer alguma operação específica quando eles ocorrem, tendo o serviço de mensageria como base na comunicação de forma flexível.

Por exemplo, uma transação que ocorrera de forma interna para externa, quando ela ocorrer, uma mensagem será publicada como evento para notificar que o montante a ser transferido internamente para outra instituição/banco externo, internamente foi subtraído, agora falta esse valor chegar até a conta beneficiária, sendo usando esse evento como estímulo em um outro sistema que irá consumir e finalizar a transação.


Observabilidade

A observabilidade do sistema e da plataforma é algo crucial, não explícito e ilustrado na big picture da solução, mas é uma característica por design, onde se encaixaria na infraestrutura para suportar o Core Pay como parte do conjunto de serviços necessários, porém é uma parte complexa de alcançar uma flexibilidade da qual possa utilizar diferentes providers como os demais serviços, por existir diversas soluções que funcionam de forma específicas e muitas delas proprietárias.

Com essa situação, o objetivo ainda é alcançar características de observabilidade de forma que seja possível ter uma maior flexibilidade na escolha das soluções de forma que seja vendor-agnostic, para isso a premissa será se apoiar na OpenTelemetry, começando por estudar os componentes que seguem e implementam a especificação e caso ainda não estejam maduros o suficiente, buscar implementar nós mesmos a especificação, contemplando:

  • Structured logging
  • Monitoring
  • Tracing
  • Metrics
  • APM

Pontos de falha

Tratasse de uma sistema muito crítico, onde o contexto para qual está sendo projetado como solução tem metas altíssimas de SLOs e SLAs, sendo assim muito importante entender dos pontos fracos da solução, quais são os comportamentos e características esperadas por parte do sistema em situações de falhas de si ou de uma integração, para avaliar a viabilidade do uso do sistema como uma solução, estar ciente do que o sistema se propõe, estar preparado e tomar as devidas medidas, principalmente para provisionar uma infraestrutura robusta, pensando na disponibilidade, situações de falhas, em estratégias de fallbacks, failover, evitar single point of failure e outros.


Core Pay

O sistema tem como base dependências muito críticas que são essenciais para suas funcionalidades, mas pela dinamicidade do contexto a única garantia é que possivelmente em algum momento poderá haver alguma falha por parte do Core Pay ou na infraestrutura de serviços, seja pela a ocorrência de uma degradação, eventual indisponibilidade parcial ou completa , mudança na topologia, algum problema referente a rede e outros.

Tendo isso em mente, fora situações onde o próprio Core Pay é o ponto de falha, o mesmo terá a premissa de por design ser resiliente e tolerar falhas, podendo se manter disponível ou parcialmente, mas de alguma forma degradado, pois em situações onde o ponto de falha é algum dos serviços que é uma forte dependência, possivelmente parte das funcionalidades não poderão ser operadas.


Authentication and Authorization server

Sendo o serviço responsável por identificar os solicitantes e permitir que possa ser feita a operação desejada, todo throughput do sistema passará por ele antes de qualquer operação.

Caso o Core Pay não consiga a garantia sobre a identidade e o que a mesma tem permissão para fazer, seu comportamento padrão será tolerar a falha com o serviço, não operando nenhuma funcionalidade, aceitando novas solicitações, respondendo que não pode processá-las naquele momento, ficando parcialmente disponível, mas mantendo a segurança, confiabilidade e integridade, até que não tenha mais falha e consiga garantir o processo novamente.


Cache service

Sendo o serviço responsável por dar vida a característica de “in-memory database”, que tem o objetivo de alta performance com baixa latência e alto throughput nas operações financeiras, é parte do backbone das funcionalidades referente às operações financeiras e outras.

Caso o Core Pay não consiga utilizar a estratégia de “in-memory database” por padrão, irá tolerar a falha com o serviço de cache, aceitando novas solicitações, respondendo que não pode processá-las naquele momento nas seguintes situações:

Solicitações de operações financeiras que envolvam escrita.
Que por design exija exclusivamente o uso do serviço de cache.

Onde demais operações como operações financeiras que envolvam apenas leitura e outras que por design não exija exclusivamente o uso do serviço de cache, será feito a tentativa de fallback para o banco temporariamente até a resolução do ponto de falha, mas apenas será sucesso caso a latência seja aceitável e o banco disponível, não onerando completamente a disponibilidade, onde do contrário, sem serviço de cache e banco, o sistema ficará praticamente indisponível.

A decisão é em prol de garantir a disponibilidade e performance do sistema.


Queue service

Sendo o serviço responsável pela comunicação e processamento assíncrono do sistema, que tem como um dos usos principais nas operações financeiras de escrita, outras operações processadas assincronamente e a comunicação/notificação de outros sistemas, a outra parte do backbone das operações financeiras, mas o sistema quase todo.

Caso o Corey Pay não consiga utilizar o serviço de mensageria, irá tolerar a falha com o serviço, não operando nenhuma funcionalidade que o envolve, aceitando novas solicitações, respondendo que não pode processá-las naquele momento, ficando parcialmente disponível, mas mantendo a consistência, durabilidade, integridade e confiabilidade.


Database

Sendo o serviço responsável pela persistência, logo a escrita e leitura base do sistema, onde todas suas informações estão armazenadas.

Caso o Corey Pay não consiga utilizar o banco de dados, irá tolerar a falha com o mesmo, não operando nenhuma funcionalidade que exija a comunicação direta com o banco, apenas possíveis leituras que ainda estejam retinas temporariamente e ainda confiáveis no serviço de cache caso o mesmo esteja disponível.

Parcialmente disponível nessa situação, mas mantendo a consistência, durabilidade, integridade, confiabilidade e atomicidade.


Evolutiva

Essa é a solução inicial, que tem como objetivo estar preparada para evoluir com facilidade conforme necessário, logo provavelmente não será exatamente a mesma conforme for ser desenvolvida.

Um dos pontos interessantes é que inicialmente será um monolito modular, mas com possíveis intenções da quebra em diferentes serviços menores dependendo do resultado da primeira versão na fase experimental do projeto, caso seja validada positivamente e venha a amadurecer, em sua versão seguinte isso pode vir a acontecer.


Conclusão

Com a base da solução em mente, o direcionamento agora é para iniciar o desenvolvimento, onde a ideia é que para cada entrega seja feito um novo artigo da engenharia por trás, mas todo ciclo ocorrerá no aberto no github, ferramenta a ser escolhida para colaboração e documentação e demais outras, tendo mais informações no próprio repositório do projeto.

Agradeço por sua atenção, fique a vontade para comentar, inteirar e acompanhar mais sobre o projeto:


Discussion (0)