2 pontos por GN⁺ 2023-08-30 | 1 comentários | Compartilhar no WhatsApp
  • Plataforma de banking-as-a-service que permite a fintechs integrar diretamente abertura de contas, pagamentos e onboarding como se estivessem conectando APIs bancárias; em março de 2023, recebeu licença bancária no Reino Unido e se tornou um banco regulado
  • O sistema roda em Clojure on Kubernetes on AWS e combina uma arquitetura de event sourcing, que transforma a maior parte das entradas em eventos, com armazenamento em FoundationDB
  • O FoundationDB é um armazenamento key-value strict-serializable que oferece suporte a transações e escritas concorrentes; a Griffin construiu leituras e escritas atômicas com uma camada semelhante ao Datomic, baseada em um port do Datascript
  • A lógica de negócio é separada em pequenos log processors centrados em receber um map em Clojure e retornar outro map em Clojure, enquanto o acesso a sistemas externos é limitado por protocolos e procs dedicados
  • A imutabilidade do Clojure e sua afinidade com trilhas de auditoria combinam com os requisitos de serviços financeiros e, junto com contratação remota, a empresa acredita ser mais fácil encontrar engenheiros de alta qualidade mesmo com um grupo menor de candidatos

Plataforma bancária regulada oferecida por API

  • A Griffin é uma plataforma de banking-as-a-service que ajuda empresas de fintech a integrar funcionalidades bancárias com rapidez e segurança
  • Em março de 2023, recebeu uma UK banking license da Financial Conduct Authority e se tornou um banco totalmente regulado no Reino Unido
  • A Griffin se define como “the bank you can build on” e quer ser uma base para bancos, como a AWS é para infraestrutura
    • API de onboarding de clientes
    • API de criação de contas bancárias
    • API de pagamentos
  • Para oferecer essas funções, fintechs precisam legalmente trabalhar com um banco, e hoje isso frequentemente significa lidar com bancos tradicionais high street que ainda usam mainframes
  • A Griffin quer oferecer ao mesmo tempo a licença bancária e a plataforma tecnológica, tornando-se a base sobre a qual as fintechs do futuro possam construir serviços
  • Embora já tivesse obtido a licença, naquela época ainda estava na fase de mobilization, que terminaria após a conclusão da auditoria, nova captação de recursos e finalização do código
    • A meta era concluir isso no Q3 ou Q4 daquele ano

Por que escolheram Clojure

  • O Clojure foi escolhido como linguagem da plataforma por sua imutabilidade, expressividade e adequação a serviços financeiros que exigem trilhas de auditoria
  • Allen Rohner viu uma apresentação de Rich Hickey sobre Clojure por volta de 2007 e concluiu que era melhor do que o Lisp que ele próprio estava criando
  • Depois de fundar a CircleCI em 2011, usou Clojure por muito tempo; a linguagem funcionou bem lá e ele entendeu que também se encaixava em serviços financeiros
  • Sobre a JVM, nos primeiros anos ele não percebeu plenamente as vantagens, mas depois passou a vê-la como um grande benefício
    • Outras linguagens nichadas para startups podem sofrer com falta de bibliotecas e problemas de desempenho de compilador ou runtime
    • A JVM reduz esses riscos
  • A escolha da linguagem revela o perfil da empresa, e eles avaliaram que Clojure era uma aposta mais forte do que Python ou Java
  • Também acreditam que usar uma linguagem de nicho pode reduzir o número de candidatos, mas aumentar a proporção de talentos de alto nível

Camada de dados construída sobre FoundationDB

  • A arquitetura da Griffin roda sobre Clojure, Kubernetes e AWS, e é quase toda baseada em event sourcing
  • O banco de dados utilizado é o FoundationDB
  • O FoundationDB é um armazenamento key-value strict-serializable com suporte a transações
    • Começou como uma startup do Vale do Silício
    • Foi adquirida pela Apple em 2015
    • Por volta de 2018, a Apple o liberou novamente como open source
    • A Apple o utiliza em produção no iCloud
  • A Apple fez benchmarks em que o FoundationDB opera em cerca de 1 milhão de transações por segundo
  • Strict serializable corresponde ao nível mais alto de consistência de banco de dados
  • A API básica é mais próxima de get a key e set a key do que de SQL
  • A Griffin portou o Datascript para o FoundationDB e construiu uma camada semelhante ao Datomic
    • Isso permite consultas atômicas sobre um armazenamento strict-serializable
    • Há suporte a leituras e escritas baseadas em transações
  • O FoundationDB não trabalha com single writer; ele suporta concurrent writes
  • A Griffin precisa de mais de 1.000 transações por segundo, e essa exigência está sendo atendida

Event sourcing e log processor

  • Todas as entradas do sistema da Griffin viram eventos
    • Requisições de API
    • Webhooks de terceiros
  • Os eventos entram em um message log; na Griffin, um evento é um map em Clojure com campo type, pares de chave/valor e spec
  • O sistema inteiro é construído como reação a eventos
  • Eles chamam os pequenos log processors de proc
    • Um proc funciona mais ou menos como “escute mensagens do tipo A e, em resposta, emita B ou C”
    • Cada proc tem seu próprio estado privado
  • O fluxo de mensagens pode ser organizado como um grafo, e os eventos se movem até alcançar um nó terminal
  • Por exemplo, o servidor web recebe um evento HTTP, registra uma requisição de pagamento e depois espera um evento payment created ou payment rejected antes de responder ao cliente
    • Esse fluxo usa um handler HTTP assíncrono em Netty
  • Todos os eventos são gravados no FoundationDB
    • Cada log processor tem seus próprios dados privados, como se fossem um namespace dentro do FoundationDB
    • O proc observa a gravação de certos tipos de evento e volta a registrar seus próprios eventos no FoundationDB
  • O FoundationDB oferece recursos para observar alterações de chave no banco, o que ajuda a construir sistemas reativos com eficiência
  • Usar o banco de dados junto com um sistema de mensageria separado pode introduzir race conditions
    • Por exemplo, uma mensagem pode ir para disco e outra para a rede, e um observador pode vê-las em ordens diferentes
    • A Griffin simplifica isso gravando tudo no FoundationDB como caminho único

Monorepo e isolamento da lógica de negócio

  • A Griffin usa monorepo
  • Hoje, por eficiência, muitos log processors rodam na mesma JVM
    • Como cada um é independente, também poderiam rodar como processos JVM separados
    • Atualmente, há algo na casa de algumas centenas baixas de procs executando em uma única JVM
  • A lógica de negócio é mantida o mais simples e limpa possível
    • Namespaces de log processor individuais são quase inteiramente Clojure puro
    • Quase não há bibliotecas de terceiros
    • Há muito poucos side effects
  • Um log processor se parece bastante com uma função que recebe um map em Clojure e retorna um ou mais maps em Clojure
  • O estado do proc tem protocolos, então a implementação do outro lado não precisa ser conhecida
    • Em testes, pode usar um banco em memória
    • Em execução real, pode escrever no FoundationDB
  • A interface com o mundo externo é mantida o menor possível
  • A maioria dos procs só pode escrever no próprio estado interno e emitir mensagens
    • Não pode fazer chamadas de rede
    • Não pode fazer chamadas à AWS
    • Nem executar outras ações externas
  • Quando é necessário falar com sistemas externos, usam um proc especial com dispatch handler dedicado
    • Proc que fala com a AWS
    • Proc que fala com o clearing bank
    • Proc que fala com outras APIs

Ecossistema Clojure utilizado

  • Dentro da lógica de negócio, quase não usam bibliotecas
  • Nas áreas que encostam no mundo externo, como o servidor web da API ou o service gateway, usam:
    • ring
    • netty
    • reitit
  • Usam Clojure spec extensivamente
  • Para integração com AWS, usam a biblioteca Cognitect aws-api
  • A configuração da aplicação e o gerenciamento de recursos seguem uma abordagem baseada no post closeable
    • A ideia é que with-open basta, sem Component ou Integrant
    • Isso fornece escopo léxico, e a ordem das declarações de binding impõe a ordem de composição
    • Eles usam um pequeno helper para declarar no bloco with-open objetos de estado ou objetos stateless que não implementam Closeable

Contratação e composição da equipe

  • A Griffin entende que contratar para Clojure reduz a quantidade de candidatos, mas aumenta a proporção de bons candidatos
    • Em vagas Java, podem chegar 1.000 CVs e apenas 10 serem bons
    • Em vagas Clojure, podem chegar 13 CVs e 10 serem bons
  • Em um pool de contratação pequeno, trabalho remoto é importante
    • Reduzir restrições geográficas permite formar um pool maior: global, dentro de 3 fusos horários, ou ao longo da Europa
  • Eles consideram um anti-pattern a situação em que é preciso contratar 100 engenheiros em pouco tempo
  • A empresa inteira tem cerca de 70 pessoas
  • A engenharia tem cerca de 22 a 24 pessoas
    • Aproximadamente dois terços estão no Reino Unido
    • Cerca de um terço está na UE
    • Há por volta de 4 pessoas na Alemanha, 4 na Suécia e 1 na Irlanda
    • A sede fica em Londres, mas a maioria dos desenvolvedores está fora de Londres, no Reino Unido

Testes de resiliência operacional em nível bancário

  • Como banco, a Griffin precisa ser operationally resilient, algo que eles tratam quase como uma exigência de não ter downtime
  • Como lidam com dinheiro, precisam demonstrar na prática que, mesmo quando há problemas, o dinheiro do cliente não será perdido
  • A direção de testes que mais lhes interessa é semelhante à abordagem da equipe do FoundationDB
    • A equipe do FoundationDB construiu um simulador de banco de dados
    • Escreveu cerca de 20 tipos de processo, ou seja, papéis internos do cluster, como um aplicativo C++ single-threaded
    • Construiu sobre C++ um compilador de concorrência em modelo de atores
    • Fez com que toda system call e network call passasse por protocolos, para permitir injeção de falhas
    • Até o multi-threading é tratado por meio de um modelo de atores baseado em envio de mensagens
  • Nesse ambiente, é possível injetar falhas de forma determinística
    • Casos em que as mensagens A e B são enviadas, mas chegam do outro lado na ordem B, A
    • Casos em que ocorre um erro de escrita em disco durante o processamento de uma mensagem
  • Isso pode ser visto como algo parecido com o generative testing do test.check, em que toda a não determinismo do sistema é semeada a partir de um único número aleatório controlável
  • O que eles querem controlar são erros de disco, erros de rede e reordenação de mensagens
  • O problema atual é que não há uma forma de controlar o comportamento das bibliotecas de threading em Java, do NIO e das escritas em disco
  • A ideia compartilha o espírito do Jepsen, mas com diferenças
    • Eles veem o Jepsen como algo mais próximo de brute force, com múltiplas VMs e encerramento de processos
    • Como é difícil inspecionar internamente o estado do banco, também é difícil saber qual é a cobertura
    • Em um ambiente totalmente controlável, dá para enumerar system calls e interleavings de mensagens, e verificar tudo muito rapidamente em memória
  • A equipe do FoundationDB construiu esse ambiente de testes cedo, e isso é um dos fatores que reforçam a confiança no FoundationDB
  • A Griffin está contratando, e mais informações podem ser encontradas na página de carreiras da Griffin

1 comentários

 
GN⁺ 2023-08-30
Opiniões no Hacker News
  • James Trunk, atual VP of Engineering da Griffin, fez a apresentação de introdução técnica a Clojure mais clara e divertida que já vi. Recomendo
    https://youtu.be/C-kF25fWTO8?si=PnjMNLdBLJ8zqSu-

  • O problema agora é que não há como controlar as bibliotecas Java de threading subjacentes, NIO e o comportamento de escrita em disco; pela natureza desse tipo de sistema, acho que isso continuará sendo impossível
    Não dá para obter execução determinística em sistemas que usam ordem de requisições ou escalonamento de tarefas não determinísticos. Isso acontece quando se usa sempre várias threads do OS ou se sobem vários processos separados nos testes
    Até seria possível forçar algo determinístico, mas seria muito difícil, porque seria preciso inserir pontos de sincronização controláveis pelos testes em todas as transições da máquina de estados da aplicação
    Na prática, parece que a única saída é projetar o núcleo do sistema de forma totalmente síncrona e acrescentar concorrência em uma camada superior no momento da execução

    • É difícil, mas possível. O mais importante é reduzir a área de superfície da aplicação. Nossa lógica de negócios é quase toda composta por funções puras, e procs não tem efeitos colaterais, exceto pelo que acontece além dos protocolos Clojure (interfaces Java)
      Por isso, durante os testes, conseguimos substituir todos os efeitos colaterais por stubs. Nosso código de “usuário” não tem acesso a bibliotecas de threading; o threading acontece no código do “kernel”
      Um bom exemplo real em que isso já foi implementado pode ser visto em https://www.youtube.com/watch?v=4fFDFbi3toc
    • Não vou dizer que é absolutamente impossível. Acho que talvez dê para fazer modificando o missionary, que é uma DSL de concorrência estruturada para Clojure/ClojureScript e implementa supervisão de processos
      O próprio missionary já instrumenta fluxos do missionary e verifica transições de estado para seus testes
  • É bem legal que os dois fundadores tenham escrito juntos um livro chamado Learning ClojureScript
    https://www.packtpub.com/product/learning-clojurescript/9781...

    • Vi que o terceiro autor do livro é Allen Rohner. Trabalhei com ele na Compass Labs, e ele era um desenvolvedor incrivelmente talentoso. Ele também fundou a CircleCI
  • A frase “costumamos brincar que somos uma empresa de tecnologia com licença bancária” é uma citação que pode pegar muito mal mais tarde se algo der errado

    • Acho que eu não usaria um banco com essa atitude. O rótulo de empresa de tecnologia muitas vezes vem acompanhado de uma arrogância injustificada de achar que se é bom em tudo só porque se escreve código
      Meu empregador se descrevia como uma empresa de pesquisa educacional que comercializava resultados de pesquisa por meio de software, e isso fazia muito mais sentido para mim e também gerava uma cultura melhor
    • Uma das coisas que aprendi em fintech é que, embora o código COBOL executado pelos bancos seja antigo e difícil de manter, ele contém bastante conhecimento valioso que teria de ser reaprendido se fosse reconstruído
      No setor bancário, o custo de reaprender esse conhecimento pode ser muito alto
  • Pergunta sincera, e desculpem o tom áspero, mas por que eu deveria me importar com a linguagem em que um serviço que uso foi escrito? Por que importa que tenha sido escrito em Clojure? Profissionalmente, sou desenvolvedor Clojure, então é legal ver algo assim escrito em Clojure, mas não entendo por que eu deveria me importar com isso
    Essa é uma das partes da comunidade de que eu realmente não gosto. Clojure é uma linguagem poderosa e eu gosto de usá-la, mas é estranho: sinto que há na comunidade algo como uma síndrome do impostor, uma necessidade de contar aos outros e justificar que determinado projeto usa essa linguagem

    • Este é um post de blog em que uma empresa de Clojure entrevista outra empresa de Clojure, com foco na stack tecnológica. Esse tipo de texto não é raro em nenhum ecossistema de linguagem e, naturalmente, é escrito e lido por pessoas interessadas naquela tecnologia
      Não entendi bem o ponto. Isso é algum comportamento inadequado em uma sociedade civilizada?
      Soa bastante ignorante. Se você “não se importa”, não precisa se envolver; deixe o autor escrever o que quiser
    • Normalmente, esse tipo de história se torna mais importante para linguagens que ainda não são suficientemente aceitas e para as quais é preciso se preocupar em obter permissão de uso
      Lembro que, nos anos 90, desenvolvedores PHP e Python compartilhavam exemplos assim para responder a perguntas de negócios como “por que não usar Microsoft ASP?”
    • Se a arquitetura permite enviar código para ser executado dentro de uma transação no lado do servidor, talvez os desenvolvedores também precisem programar em Clojure para usar essa API
      Ou talvez seja uma tentativa de atrair desenvolvedores para trabalhar na empresa deles
  • Por que esses bancos de API ficam sempre no Reino Unido? Há anos eu queria fazer operações bancárias via curl, mas ninguém oferece isso nos EUA

    • O setor bancário dos EUA é surpreendentemente atrasado e, do ponto de vista de tecnologia ou inovação, não lidera o mundo há décadas.
      Já o Reino Unido vem incentivando ativamente novos bancos e novas tecnologias. Transferências instantâneas e gratuitas entre contas pessoais existem há quase 20 anos, pagamentos por aproximação há pelo menos 10, mobile banking há décadas, e as APIs bancárias exigidas pelo governo existem há quase 5 anos.
      Em resumo, o Reino Unido tem um setor bancário muito ativo que, pelos padrões bancários, vem inovando rapidamente, e conta com um ambiente e um ecossistema bem desenvolvidos para uma inovação ainda mais rápida.
      Nos EUA, parece que os bancos desistiram da inovação tecnológica décadas atrás e preferiram inovar em tarifas e em tratamento punitivo aos clientes. Por isso não há um novo ambiente de inovação, e para os bancos estabelecidos é muito mais fácil esmagar concorrentes do que competir.
      Até recentemente, o Reino Unido também tinha um número surpreendentemente pequeno de bancos independentes; o motivo de isso não ter acontecido lá provavelmente tem a ver com a natureza das leis e regulações, que garantem muitos direitos aos clientes e punem ativamente bancos que não os respeitam.
    • É difícil conseguir uma nova licença bancária nos EUA, mas no Reino Unido há um caminho relativamente claro para se tornar um banco challenger. Jarvis também se mudou de volta de SF para Londres para começar a Griffin.
      Nos EUA, os bancos que têm APIs tendem a focar em parcerias com grandes fintechs, então até uma API simples provavelmente será cara em comparação com uma conta bancária comum. Por exemplo, o Grasshopper Bank, nos EUA, é um dos poucos bancos que oferecem uma API em cima de uma conta bancária comercial comum.
      Eu trabalho na Treasury Prime, que dá suporte a vários bancos dos EUA que oferecem APIs.
    • Depois da crise financeira de 2008 e dos escândalos bancários que se seguiram, foi preciso resgatar vários bancos famosos com dinheiro dos contribuintes, e o governo britânico da época introduziu uma série de medidas para promover bancos menores.
      No lado das contas pessoais, Monzo e Starling são os mais conhecidos entre os chamados bancos challenger[1].
      [1]: https://en.wikipedia.org/wiki/Challenger_bank
    • No Reino Unido, o governo impôs requisitos de API aos bancos. Nos EUA, isso é deixado ao “livre mercado”, o que na prática significa que é preciso confiar em terceiros pouco confiáveis como Yodlee ou Plaid.
    • Agora existe https://column.com. Também foi discutido aqui no ano passado.
      Column – um banco licenciado para desenvolvedores
      https://news.ycombinator.com/item?id=31109170
  • “Há mais uma tecnologia proprietária que deveríamos tornar open source. Fizemos o port do Datascript para o FoundationDB” — por favor, publiquem isso.
    Estou curioso para saber como funcionaria como alternativa ao Datomic.

    • O texto inteiro parecia um guia de “como fazer overengineering em um projeto por diversão”.
  • A frase “Legalmente, fintechs precisam trabalhar com bancos para fazer esse tipo de coisa, e hoje isso significa grandes bancos tradicionais que usam mainframes. A Griffin é o banco e a plataforma tecnológica sobre a qual todas as fintechs do futuro serão construídas” parece ter sido escrita em 2016.
    O mercado já se moveu. A Griffin parece boa, mas está alguns anos atrás de muita gente, e players estabelecidos como a ClearBank já oferecem APIs bancárias muito bem.
    Há espaço para mais empresas entrarem, então é bom ver a Griffin chegando ao mercado, mas eu gostaria que o pitch não fosse tão fraco.

    • Ainda não há tantas opções assim no mercado. A ClearBank é, de fato, um dos três bancos com um produto decente.
      E uma boa API por si só não basta. É preciso todo um modelo operacional que combine com a base de clientes, e construir isso é muito mais difícil.
    • A expressão “sobre a qual todas as fintechs do futuro serão construídas” soa como um ponto único de falha, e parece mostrar exatamente o problema do capitalismo tardio, em que a concorrência vira pouco mais que uma fantasia.
  • Ainda não. O texto diz: “Quando concluirmos a auditoria, levantarmos mais capital e terminarmos de escrever o código, tiraremos as rodinhas. Isso deve acontecer por volta do 3º ou 4º trimestre deste ano”.

  • Eu detesto quando um texto começa com “em uma startup, você deve usar a linguagem mais poderosa disponível, e essa linguagem é Clojure”.
    Isso é só a sua opinião. Em uma startup, você deve usar a linguagem que permita à equipe criar e lançar o MVP o mais rápido possível para conseguir os primeiros clientes ou investimento. Para uma startup comum, isso pode até ser uma plataforma low-code ou no-code, embora em fintech isso provavelmente não se aplique.
    Se fosse para argumentar, também daria para dizer que Python é a linguagem mais poderosa por causa de LLMs e machine learning, e eu normalmente sou desenvolvedor PHP. Python talvez fique ainda mais poderosa graças ao Mojo, que supostamente torna Python 36.000 vezes mais rápido.
    Mas eu jamais diria que alguma linguagem X é a única e mais poderosa linguagem a ser usada em startups. Isso é uma falsidade total e apenas uma opinião.

    • Claro que é uma opinião. Sempre que alguém diz alguma coisa, aquilo é a opinião dessa pessoa.
      Por exemplo, na minha opinião, eu concordo com essa opinião :-) Meu negócio solo não teria sido possível sem Clojure e ClojureScript, e isso mostra o “poder” dessa linguagem.
      Eu considero a linguagem “poderosa” porque ela permite que um único desenvolvedor escreva e mantenha apps complexos por anos. Ela me dá poder.
    • Essa frase faz muito mais sentido quando se considera que a JUXT, com exceção do Nubank, é uma das empresas especializadas em Clojure mais conhecidas, e que coloca seu logo no rodapé de praticamente toda conferência minimamente relacionada a Clojure.
      Clojure tem uma comunidade bastante voltada para dentro, mais sobreposta a outros Lisps do que a linguagens mais populares como Python ou PHP. Por isso, o clichê de que Clojure é a linguagem mais poderosa pode soar surpreendente para quem não a usa, embora tenha seu fundo de verdade.
      Nós, desenvolvedores Clojure, já estamos acostumados, e hoje falar partindo da premissa de superioridade virou quase uma forma de cumprimento.
    • Python é realmente poderoso, especialmente em 2023. Mas, estranhamente, eu orquestro LLMs e modelos de difusão em Clojure.
      Também prefiro Clojure para lidar com saídas de LLMs. Claro que continuo usando Python nos lugares em que Python é a ferramenta certa.