<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: 3X Pay</title>
    <description>The latest articles on DEV Community by 3X Pay (@3x_pay).</description>
    <link>https://dev.to/3x_pay</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Forganization%2Fprofile_image%2F9471%2F93e7d78e-bfbe-4c3a-8a6a-ecc60535cabb.png</url>
      <title>DEV Community: 3X Pay</title>
      <link>https://dev.to/3x_pay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/3x_pay"/>
    <language>en</language>
    <item>
      <title>Migrando do RDS PostgreSQL para Aurora Serverless</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Thu, 20 Mar 2025 17:44:09 +0000</pubDate>
      <link>https://dev.to/3x_pay/migrando-do-rds-postgresql-para-aurora-serverless-5827</link>
      <guid>https://dev.to/3x_pay/migrando-do-rds-postgresql-para-aurora-serverless-5827</guid>
      <description>&lt;p&gt;No cenário dinâmico das fintechs, a escalabilidade e a otimização de custos são desafios constantes. Recentemente, realizamos a migração do nosso banco de dados de um &lt;strong&gt;RDS PostgreSQL&lt;/strong&gt; tradicional para o &lt;strong&gt;Aurora Serverless&lt;/strong&gt;, e os benefícios foram significativos.&lt;/p&gt;

&lt;h2&gt;
  
  
  O Problema: Escalabilidade e Custos em um Ambiente Imprevisível
&lt;/h2&gt;

&lt;p&gt;Nossa fintech lida com um volume de transações que pode variar drasticamente ao longo do dia. Em determinados momentos, o tráfego aumenta exponencialmente, exigindo mais recursos computacionais. No modelo tradicional do RDS PostgreSQL, enfrentávamos dois grandes desafios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Capacidade Fixa ou Superdimensionamento&lt;/strong&gt;: Precisávamos escolher entre manter uma instância com capacidade suficiente para os picos (o que gerava altos custos quando a carga era baixa) ou correr o risco de não suportar momentos de alta demanda.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidade Manual&lt;/strong&gt;: Mesmo com o recurso de escalabilidade do RDS, o ajuste de capacidade não era instantâneo, o que poderia impactar a performance durante os períodos de alta transação.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alto Uso de CPU e Excesso de Conexões&lt;/strong&gt;: Durante picos de tráfego, frequentemente atingíamos níveis elevados de uso de CPU, o que causava degradação do banco de dados. Além disso, a aplicação tentava abrir muitas conexões simultâneas para compensar a lentidão, sobrecarregando ainda mais o banco e, em alguns casos, levando-o a cair completamente.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Diante disso, buscamos uma solução que permitisse maior flexibilidade sem comprometer a confiabilidade do sistema.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Solução: Aurora Serverless
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;Aurora Serverless&lt;/strong&gt; se destacou como a melhor opção por alguns motivos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Escalabilidade Automática&lt;/strong&gt;: Ele ajusta a capacidade automaticamente conforme a demanda, sem necessidade de intervenção manual.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custo Proporcional ao Uso&lt;/strong&gt;: Diferente do RDS tradicional, onde pagamos por instâncias ativas independentemente do uso, o Aurora Serverless cobra apenas pelos recursos efetivamente utilizados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alta Disponibilidade e Performance&lt;/strong&gt;: Como parte do ecossistema AWS, ele mantém alta disponibilidade e replica automaticamente os dados para garantir resiliência.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  O Processo de Migração
&lt;/h3&gt;

&lt;p&gt;A migração envolveu algumas etapas essenciais:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Testes em Homologação&lt;/strong&gt;: Subimos um banco Aurora Serverless em ambiente de homologação para realização de testes de carga, para entendermos se o problema seria resolvido, após esse teste tivemos a certeza que esse seria o melhor caminho.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Criação da Read Replica no Aurora&lt;/strong&gt;: Durante o dia, configuramos uma read replica do RDS no Aurora para manter a sincronização contínua com a base original.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fechamento do Security Group do RDS&lt;/strong&gt;: Para garantir que não houvesse mais acessos à instância antiga, restringimos as conexões no Security Group do RDS.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Promoção da Read Replica para Master&lt;/strong&gt;: Elevamos a read replica para a instância principal do banco no Aurora.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ajuste do Endpoint&lt;/strong&gt;: Atualizamos o endpoint do banco para apontar para a nova instância.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provisionamento dos Novos Containers&lt;/strong&gt;: Rodamos a pipeline para que a mudança fosse feita em todos os containers.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Os Resultados
&lt;/h2&gt;

&lt;p&gt;Após a migração, observamos melhorias significativas:&lt;/p&gt;

&lt;p&gt;✅ &lt;strong&gt;Redução de Custos&lt;/strong&gt;: Conseguimos uma economia expressiva de &lt;strong&gt;mais de 70%&lt;/strong&gt; no custo diário do banco de dados, graças ao modelo de cobrança baseado no uso real.&lt;br&gt;
✅ &lt;strong&gt;Melhor Resiliência a Picos&lt;/strong&gt;: A aplicação se tornou mais robusta e responsiva, suportando picos sem necessidade de intervenção manual.&lt;br&gt;
✅ &lt;strong&gt;Menos Sobrecarga Operacional&lt;/strong&gt;: Não precisamos mais ajustar a capacidade manualmente, permitindo que a equipe foque em outras melhorias.&lt;br&gt;
✅ &lt;strong&gt;Transição Rápida e Segura&lt;/strong&gt;: O processo de troca foi concluído em apenas &lt;strong&gt;3 minutos de downtime&lt;/strong&gt;, minimizando impactos para os usuários.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;Para fintechs e outras empresas que lidam com demandas variáveis, o &lt;strong&gt;Aurora Serverless&lt;/strong&gt; provou ser uma excelente escolha. A capacidade de escalar automaticamente e o modelo de custo baseado no uso real fazem toda a diferença em um ambiente onde previsibilidade é um desafio.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ACID Transactions em uma Aplicação Fintech:</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Wed, 29 Jan 2025 13:11:46 +0000</pubDate>
      <link>https://dev.to/3x_pay/acid-transactions-em-uma-aplicacao-fintech-35aa</link>
      <guid>https://dev.to/3x_pay/acid-transactions-em-uma-aplicacao-fintech-35aa</guid>
      <description>&lt;h2&gt;
  
  
  Introdução
&lt;/h2&gt;

&lt;p&gt;Em aplicações de fintech, garantir a integridade das transações financeiras é essencial. Problemas como transações incompletas ou dados inconsistentes podem comprometer a confiança dos usuários e a segurança do sistema. Para mitigar esses riscos, podemos usar os conceitos de transações ACID, que garantem operações confiáveis e robustas.&lt;/p&gt;

&lt;p&gt;Neste artigo, vou mostrar as propriedades ACID e uma implementação usando NestJS, Prisma e PostgreSQL, utilizando o seguinte modelo de transação:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model Transaction {
  id                Int      @id @default(autoincrement())
  userId            Int
  subTotal          Decimal  @default(0) @db.Decimal(10, 2)
  total             Decimal  @default(0) @db.Decimal(10, 2)
  transactionId     String?  @unique
  order_processor_id String
  payment_method    PaymentMethod
  status            TransactionStatus
  external_id       String
  e2e_id            String?
  error_message     String?
  created_at        DateTime? @default(now())
  updated_at        DateTime? @updatedAt
  customerId        Int?
  callback_url      String?
  typeTransaction   TypeTransaction
  future_balance    Decimal  @default(0) @db.Decimal(10, 2)
  previous_balance  Decimal  @default(0) @db.Decimal(10, 2)

  Customers         Customer? @relation(fields: [customerId], references: [id])
  user              User      @relation(fields: [userId], references: [id])
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Entendendo as Propriedades ACID
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Atomicidade (Atomicity)
&lt;/h3&gt;

&lt;p&gt;A atomicidade garante que uma transação seja tratada como uma unidade indivisível. Ou todas as operações dentro da transação são executadas com sucesso, ou nenhuma é aplicada. Isso é crucial em aplicações fintech para evitar cenários como debitar uma conta sem creditar o destinatário.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;br&gt;
Imagine transferir fundos entre duas contas:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fromUserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;subTotal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PENDING&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toUserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;subTotal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;COMPLETED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se a criação de qualquer uma das transações falhar, o sistema garante que nenhuma alteração seja persistida.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Consistência (Consistency)
&lt;/h3&gt;

&lt;p&gt;A consistência assegura que o banco de dados transite de um estado válido para outro, sempre preservando regras e restrições definidas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;br&gt;
Ao criar uma nova transação, todos os campos obrigatórios, como &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;subTotal&lt;/code&gt; e &lt;code&gt;status&lt;/code&gt;, devem ser válidos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model Transaction {
  id         Int      @id @default(autoincrement())
  userId     Int
  subTotal   Decimal  @default(0) @db.Decimal(10, 2)
  total      Decimal  @default(0) @db.Decimal(10, 2)
  status     String
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se qualquer campo obrigatório estiver ausente ou contiver dados inválidos, o banco de dados rejeita a transação, mantendo a consistência.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Isolamento (Isolation)
&lt;/h3&gt;

&lt;p&gt;O isolamento garante que transações concorrentes não interfiram umas com as outras. Cada transação é executada como se fosse a única operando no sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;br&gt;
Se dois usuários iniciam transações simultaneamente, a propriedade de isolamento garante que os cálculos de saldo permaneçam precisos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$transaction&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;operation1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;operation2&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O PostgreSQL lida com diferentes níveis de isolamento (&lt;code&gt;READ COMMITTED&lt;/code&gt;, &lt;code&gt;SERIALIZABLE&lt;/code&gt;, etc.) para gerenciar operações concorrentes.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Durabilidade (Durability)
&lt;/h3&gt;

&lt;p&gt;A durabilidade garante que, uma vez que uma transação é confirmada, ela permanece persistente, mesmo em caso de falha do sistema.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Exemplo:&lt;/strong&gt;&lt;br&gt;
Após registrar com sucesso uma transação financeira, os dados permanecem intactos e disponíveis, independentemente de falhas no servidor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prisma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transaction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;subTotal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;total&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PROCESSED&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uma vez confirmada, o PostgreSQL garante que a transação persista no disco.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;As transações ACID são essenciais para garantir a confiabilidade e integridade das operações financeiras em aplicações fintech. Compreender e implementar corretamente as propriedades de Atomicidade, Consistência, Isolamento e Durabilidade é fundamental para construir serviços financeiros seguros e escaláveis.&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>fintech</category>
      <category>postgres</category>
      <category>acid</category>
    </item>
    <item>
      <title>Solving Performance Issues with Redis and Bull</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Tue, 10 Sep 2024 01:00:36 +0000</pubDate>
      <link>https://dev.to/3x_pay/solving-performance-issues-with-redis-and-bull-4766</link>
      <guid>https://dev.to/3x_pay/solving-performance-issues-with-redis-and-bull-4766</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;In a fintech environment, system performance is crucial to ensuring that financial transactions are quick and secure. The ability to process a large volume of simultaneous requests without compromising user experience or overloading infrastructure is one of the main challenges. To achieve this, tools like Redis and Bull have played a fundamental role in our fintech.&lt;/p&gt;

&lt;p&gt;In this article, I will share how we used Redis and Bull to solve performance problems, improve transaction response times, and ensure that our financial system remains scalable and efficient. I will also include a practical guide on how to implement Redis and Bull in NestJS.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem: Slowness and System Overload
&lt;/h3&gt;

&lt;p&gt;With the growth of our user base and the increase in daily transactions, we began to notice a drop in system performance, especially during peak hours. Operations such as payment processing, report generation, and notifications were starting to slow down, and server overload was becoming a real threat.&lt;/p&gt;

&lt;p&gt;Additionally, the need to process each transaction synchronously was beginning to create bottlenecks, increasing response times for end users. We needed a way to optimize the processing of these tasks to avoid service degradation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 1: Optimization with Redis
&lt;/h3&gt;

&lt;p&gt;To enhance performance and reduce latency in read and write operations, we implemented Redis as a caching solution. Redis is an in-memory database that allows for extremely fast access and writes, making it ideal for storing temporary or frequently accessed data.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Redis in Our Infrastructure
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Session and Authentication Cache:&lt;/strong&gt; Instead of making constant database queries to check active sessions, we started storing authentication tokens in Redis. This significantly reduced latency in user authentications and transaction processing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Transaction Cache:&lt;/strong&gt; During payment processing, transaction data is temporarily stored in Redis before being written to the main database. This allowed us to process transactions much faster while the system handled critical operations asynchronously.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Reduction of Database Queries:&lt;/strong&gt; We stored frequently accessed data in Redis, such as configuration information, payment states, and temporary logs. This reduced the load on the relational database and improved response times for end users.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Results
&lt;/h4&gt;

&lt;p&gt;The implementation of Redis significantly reduced latency in several critical parts of our system, especially in operations that rely on quick and repeated queries. The improvement was noticeable on both the front-end, with faster response times, and the back-end, which handled the increased requests better.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution 2: Asynchronous Processing with Bull
&lt;/h3&gt;

&lt;p&gt;Even with optimization through Redis, we found that some operations needed to be decoupled from the main flow, particularly tasks that required more processing time, such as transaction notifications, report generation, and integration with external systems.&lt;/p&gt;

&lt;p&gt;This is where we implemented Bull, a queue management library based on Redis, which allowed us to process tasks asynchronously without blocking the main execution flow.&lt;/p&gt;

&lt;h4&gt;
  
  
  Using Bull for Queue Management
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Asynchronous Transaction Processing:&lt;/strong&gt; Instead of processing all transactions synchronously, we moved parts of the process to a task queue with Bull. This allowed our application to continue responding quickly to users while longer tasks were processed in the background.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Real-Time Notifications:&lt;/strong&gt; One of the first applications of Bull was in the queue for sending notifications. Since sending notifications via email or push can be time-consuming and involves calls to external APIs, we moved this process to a queue, ensuring that users received their updates without impacting the overall platform performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Retry and Failure Management:&lt;/strong&gt; Bull also allowed us to manage task failures efficiently. When a task failed, it was automatically reprocessed after a configured time, without the need for manual intervention, ensuring greater system resilience.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Results
&lt;/h4&gt;

&lt;p&gt;By introducing Bull, we were able to distribute the workload more efficiently and avoid blocking the main application flow. This resulted in a significant improvement in response times, even during peak usage times. Furthermore, we were able to scale more predictably, as tasks were processed according to the system's capacity.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical Implementation: Integrating Redis and Bull in NestJS
&lt;/h3&gt;

&lt;p&gt;Below, I present a step-by-step guide on how to integrate Redis and Bull into a NestJS application, based on the lessons learned from our practical experience.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. Installing Dependencies
&lt;/h4&gt;

&lt;p&gt;First, install the Bull and Redis packages in your NestJS project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/bull bull redis
npm &lt;span class="nb"&gt;install&lt;/span&gt; @types/redis &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. Configuring the Bull Module
&lt;/h4&gt;

&lt;p&gt;Create a module to configure Bull with Redis. In &lt;code&gt;queue.module.ts&lt;/code&gt;, register Bull:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BullModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueProcessor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.processor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BullModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;BullModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerQueue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Name of the queue&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;QueueProcessor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. Creating the Queue Processor
&lt;/h4&gt;

&lt;p&gt;Create &lt;code&gt;queue.processor.ts&lt;/code&gt; to process tasks in the queue:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Process&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Name of the queue we will process&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Here we handle the processing of each job&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processing job #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; with data:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Simulate sending email&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email sent successfully&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simulate sending email (place your logic here)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Email sent to: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, with subject: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. Service for Adding Tasks to the Queue
&lt;/h4&gt;

&lt;p&gt;Create a service to add new tasks to the queue in &lt;code&gt;queue.service.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InjectQueue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;InjectQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;addEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. Using the Service in the Controller
&lt;/h4&gt;

&lt;p&gt;Create a controller to expose this functionality. In &lt;code&gt;email.controller.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;queueService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queueService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email added to the queue!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing the Implementation
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start Redis Locally:&lt;/strong&gt;
Ensure that Redis is running locally. You can use Docker to easily start Redis:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Run the Application:&lt;/strong&gt;
With Redis running, execute the NestJS application with the command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Send a Request:&lt;/strong&gt;
Now you can test the API using a tool like Postman or cURL, sending a POST request to &lt;code&gt;http://localhost:3000/email/send&lt;/code&gt; with the following body:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"user@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Email Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"This is a test email."&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If everything is configured correctly, you will see console logs showing that the job was added to the queue and that the processor handled it.&lt;/p&gt;

&lt;h3&gt;
  
  
  General Benefits of the Implementation
&lt;/h3&gt;

&lt;p&gt;This is a practical example of how to integrate Redis and Bull in NestJS to manage asynchronous tasks effectively. We use Redis as a foundation for Bull, which is responsible for efficiently managing task queues.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In this example, we demonstrated how to integrate Redis and Bull into a NestJS project to create a robust queue system where lengthy tasks are processed asynchronously. This approach is ideal for systems that need to manage large volumes of transactions or other operations requiring high performance and resilience.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Resolvendo Problemas de Performance com Redis e Bull</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Tue, 10 Sep 2024 00:58:52 +0000</pubDate>
      <link>https://dev.to/3x_pay/resolvendo-problemas-de-performance-com-redis-e-bull-8a3</link>
      <guid>https://dev.to/3x_pay/resolvendo-problemas-de-performance-com-redis-e-bull-8a3</guid>
      <description>&lt;p&gt;Em um ambiente de fintech, a performance do sistema é crucial para garantir que transações financeiras sejam rápidas e seguras. A capacidade de processar um grande volume de requisições simultaneamente, sem prejudicar a experiência do usuário ou sobrecarregar a infraestrutura, é um dos principais desafios. Para alcançar isso, ferramentas como &lt;strong&gt;Redis&lt;/strong&gt; e &lt;strong&gt;Bull&lt;/strong&gt; têm desempenhado um papel fundamental na nossa fintech.&lt;/p&gt;

&lt;p&gt;Neste artigo, vou compartilhar como usamos Redis e Bull para resolver problemas de performance, melhorar o tempo de resposta das transações e garantir que nosso sistema financeiro continue escalável e eficiente. Também incluirei um guia prático sobre como implementar Redis e Bull no NestJS.&lt;/p&gt;




&lt;h3&gt;
  
  
  O Problema: Lentidão e Sobrecarga do Sistema
&lt;/h3&gt;

&lt;p&gt;Com o crescimento da nossa base de usuários e o aumento no número de transações diárias, começamos a perceber uma queda na performance do sistema, especialmente durante os horários de pico. Operações como processamento de pagamentos, geração de relatórios e notificações estavam começando a ficar mais lentas, e a sobrecarga nos servidores estava se tornando uma ameaça real.&lt;/p&gt;

&lt;p&gt;Além disso, a necessidade de processar cada transação de forma síncrona estava começando a causar gargalos, aumentando o tempo de resposta para o usuário final. Precisávamos de uma maneira de otimizar o processamento dessas tarefas para evitar a degradação do serviço.&lt;/p&gt;




&lt;h3&gt;
  
  
  Solução 1: Otimização com Redis
&lt;/h3&gt;

&lt;p&gt;Para melhorar o desempenho e diminuir a latência nas operações de leitura e gravação, implementamos &lt;strong&gt;Redis&lt;/strong&gt; como solução de cache. Redis é um banco de dados em memória que permite acessos e gravações extremamente rápidos, ideal para armazenar dados temporários ou frequentemente acessados.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Uso de Redis na Nossa Infraestrutura&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache de Sessão e Autenticação&lt;/strong&gt;: Em vez de fazer consultas constantes ao banco de dados para verificar sessões ativas, passamos a armazenar tokens de autenticação no Redis. Isso reduziu significativamente a latência nas autenticações de usuários e no processamento de transações.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cache de Transações Temporárias&lt;/strong&gt;: Durante o processamento de pagamentos, os dados da transação são armazenados temporariamente no Redis antes de serem gravados no banco de dados principal. Isso nos permitiu processar as transações de forma muito mais rápida, enquanto o sistema lida com operações críticas de forma assíncrona.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Redução de Consultas ao Banco de Dados&lt;/strong&gt;: Armazenamos dados frequentemente acessados no Redis, como informações de configuração, estados de pagamentos e logs temporários. Isso reduziu a carga no banco de dados relacional e melhorou o tempo de resposta para os usuários finais.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Resultados&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A implementação de Redis reduziu significativamente a latência em várias partes críticas do nosso sistema, especialmente nas operações que dependem de consultas rápidas e repetidas. A melhora foi perceptível tanto no front-end, com tempos de resposta mais rápidos, quanto no back-end, que suportava melhor o aumento de requisições.&lt;/p&gt;




&lt;h3&gt;
  
  
  Solução 2: Processamento Assíncrono com Bull
&lt;/h3&gt;

&lt;p&gt;Mesmo com a otimização via Redis, percebemos que algumas operações precisavam ser desacopladas do fluxo principal, especialmente tarefas que demandavam mais tempo de processamento, como notificações de transações, geração de relatórios e integração com sistemas externos.&lt;/p&gt;

&lt;p&gt;Foi aí que implementamos &lt;strong&gt;Bull&lt;/strong&gt;, uma biblioteca de gerenciamento de filas baseada em Redis, que nos permitiu processar tarefas de maneira assíncrona, sem bloquear o fluxo principal de execução.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Uso de Bull para Gerenciamento de Filas&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Processamento de Transações Assíncronas&lt;/strong&gt;: Em vez de processar todas as transações de forma síncrona, movemos partes do processo para uma fila de tarefas com Bull. Isso permitiu que nossa aplicação continuasse respondendo rapidamente aos usuários, enquanto tarefas mais demoradas eram processadas em segundo plano.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Notificações em Tempo Real&lt;/strong&gt;: Uma das primeiras aplicações de Bull foi na fila de envio de notificações. Como o envio de notificações por e-mail ou push pode ser demorado e envolvem chamadas a APIs externas, movemos esse processo para uma fila, garantindo que os usuários recebessem suas atualizações sem impactar o desempenho geral da plataforma.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Gerenciamento de Retries e Falhas&lt;/strong&gt;: Bull também nos permitiu gerenciar falhas em tarefas de forma eficiente. Quando uma tarefa falhava, era reprocessada automaticamente após um tempo configurado, sem necessidade de intervenção manual, garantindo maior resiliência do sistema.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Resultados&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Ao introduzir Bull, conseguimos distribuir a carga de trabalho de maneira mais eficiente e evitar o bloqueio do fluxo principal da aplicação. Isso resultou em uma melhoria significativa no tempo de resposta, mesmo em momentos de pico de uso. Além disso, conseguimos escalar de forma mais previsível, já que as tarefas eram processadas conforme a capacidade do sistema.&lt;/p&gt;




&lt;h3&gt;
  
  
  Implementação Prática: Integrando Redis e Bull no NestJS
&lt;/h3&gt;

&lt;p&gt;Abaixo, apresento um guia passo a passo sobre como integrar Redis e Bull em uma aplicação NestJS, a partir das lições aprendidas na nossa experiência prática.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Instalação das Dependências&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Primeiro, instale os pacotes do Bull e Redis no seu projeto NestJS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @nestjs/bull bull redis
npm &lt;span class="nb"&gt;install&lt;/span&gt; @types/redis &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  2. &lt;strong&gt;Configuração do Módulo Bull&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Crie um módulo para configurar Bull com Redis. No &lt;code&gt;queue.module.ts&lt;/code&gt;, registre o Bull:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;BullModule&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Module&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueProcessor&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.processor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;imports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;BullModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forRoot&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;localhost&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="nx"&gt;BullModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;registerQueue&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Nome da fila&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;providers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;QueueProcessor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueModule&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  3. &lt;strong&gt;Criar o Processador de Filas&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Crie o &lt;code&gt;queue.processor.ts&lt;/code&gt; para processar as tarefas na fila:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Process&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Processor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Nome da fila que vamos processar&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueProcessor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Process&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// Aqui lidamos com o processamento de cada job&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;handleEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Job&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Processando job #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; com os dados:`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Simular envio de e-mail&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;job&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email enviado com sucesso&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Simulação de envio de e-mail (coloque sua lógica aqui)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Email enviado para: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, com assunto: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  4. &lt;strong&gt;Serviço para Adicionar Tarefas à Fila&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Crie um serviço para adicionar novas tarefas na fila em &lt;code&gt;queue.service.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;InjectQueue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bull&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(@&lt;/span&gt;&lt;span class="nd"&gt;InjectQueue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Queue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;addEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;emailQueue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  5. &lt;strong&gt;Usando o Serviço no Controller&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Crie um controlador para expor essa funcionalidade. No &lt;code&gt;email.controller.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nestjs/common&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./queue.service&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EmailController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;queueService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueueService&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

  &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;send&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;sendEmail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;to&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subject&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queueService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEmailJob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;subject&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Email adicionado à fila!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testando a Implementação
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Suba o Redis localmente&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para testar, certifique-se de que o Redis esteja rodando localmente. Você pode usar o Docker para iniciar o Redis facilmente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 6379:6379 redis
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Execute o aplicativo&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com o Redis rodando, execute o NestJS com o comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   npm run start:dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Envie uma requisição&lt;/strong&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agora, você pode testar a API com uma ferramenta como o Postman ou cURL, enviando uma requisição &lt;code&gt;POST&lt;/code&gt; para &lt;code&gt;http://localhost:3000/email/send&lt;/code&gt; com o seguinte body:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"usuario@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"subject"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Teste de Email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Esse é um email de teste."&lt;/span&gt;&lt;span class="w"&gt;
   &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Se tudo estiver configurado corretamente, você verá no console logs mostrando que o job foi adicionado à fila e que o processador lidou com ele.&lt;/p&gt;




&lt;h3&gt;
  
  
  Benefícios Gerais das Implementação
&lt;/h3&gt;

&lt;p&gt;Aqui está um exemplo prático de como integrar &lt;strong&gt;Redis&lt;/strong&gt; e &lt;strong&gt;Bull&lt;/strong&gt; no &lt;strong&gt;NestJS&lt;/strong&gt; para gerenciar tarefas assíncronas. Vamos usar o Redis como uma base para o Bull, que será responsável por gerenciar filas de tarefas de forma eficiente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Neste exemplo, mostramos como integrar &lt;strong&gt;Redis&lt;/strong&gt; e &lt;strong&gt;Bull&lt;/strong&gt; em um projeto &lt;strong&gt;NestJS&lt;/strong&gt; para criar um sistema de filas robusto, onde tarefas demoradas são processadas de forma assíncrona. Essa abordagem é ideal para sistemas que precisam gerenciar grandes volumes de transações ou outras operações que exigem alta performance e resiliência.&lt;/p&gt;

</description>
      <category>redis</category>
      <category>bullmq</category>
      <category>queue</category>
      <category>nestjs</category>
    </item>
    <item>
      <title>The Challenges of Managing a Successful Fintech: Revenue of R$9,643,141.49 in 30 Days</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Mon, 09 Sep 2024 22:53:30 +0000</pubDate>
      <link>https://dev.to/3x_pay/the-challenges-of-managing-a-successful-fintech-revenue-of-r964314149-in-30-days-4hjb</link>
      <guid>https://dev.to/3x_pay/the-challenges-of-managing-a-successful-fintech-revenue-of-r964314149-in-30-days-4hjb</guid>
      <description>&lt;p&gt;Running a fintech that generated over R$9.6 million in just 30 days comes with a range of complex challenges. From the perspective of a senior developer, each day is marked by decisions that can profoundly impact the business. When working with a tech stack comprised of &lt;strong&gt;NestJS&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt;, and &lt;strong&gt;NextJS&lt;/strong&gt;, the focus is on ensuring that the system is scalable, performant, and secure. However, the reality extends far beyond simply choosing the right tools.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Constant Pressure: No Room for Error&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In an environment where millions of reais are at stake, the margin for error is virtually nonexistent. Every technical decision, whether in the architecture or in implementing a new feature, can directly affect the business and its customers. The pressure to ensure that every transaction is processed flawlessly is constant. A simple mistake, such as an inefficient query or a misconfigured cache, can result in significant financial loss.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NestJS&lt;/strong&gt;, being modular and efficient, helps in organizing the code, but the pressure to maintain everything running smoothly forces an extremely careful approach to each new deployment. Every line of code undergoes thorough reviews and automated testing before being applied, ensuring that there is no impact on transactions.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Continuous Monitoring and Maintenance&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Real-time monitoring is essential for ensuring that the fintech operates efficiently. Tools like &lt;strong&gt;Sentry&lt;/strong&gt; for error tracking and &lt;strong&gt;Grafana&lt;/strong&gt; for performance metrics are critical in daily operations. They provide a detailed view of how the system is behaving and help detect potential failures before they escalate into larger problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redis&lt;/strong&gt; plays a vital role in handling high transaction volumes by offloading some of the processing through queues and caching. However, the technical team must always be vigilant to ensure that no transaction queue gets stuck, as this could directly affect the user experience and lead to significant delays.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Scalability and Data Consistency&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Maintaining scalability in a system processing millions of reais requires a well-thought-out architecture. &lt;strong&gt;PostgreSQL&lt;/strong&gt;, our database, needs continuous optimization, including &lt;strong&gt;table partitioning&lt;/strong&gt; and &lt;strong&gt;well-defined indexes&lt;/strong&gt; to handle the growing data volume without compromising performance. Every query must be optimized, and backup routines are constant to prevent data loss.&lt;/p&gt;

&lt;p&gt;The combination of &lt;strong&gt;NestJS&lt;/strong&gt; and &lt;strong&gt;PostgreSQL&lt;/strong&gt; allows for a scalable backend structure, but ensuring data consistency in complex financial transactions is an ongoing challenge. We need to handle concurrency and distributed transactions, which adds a layer of complexity to the development process.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Frontend Development with NextJS&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;The frontend, built with &lt;strong&gt;NextJS&lt;/strong&gt;, must be fast and intuitive, providing real-time dashboards that display critical financial data to clients. User experience is paramount, and leveraging server-side rendering (SSR) with NextJS ensures a fast interface, even when dealing with a high volume of data exchanged between frontend and backend.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Decision-Making Under Pressure&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;In a fintech environment, quick decision-making is part of the daily routine. When an issue is detected, there is little time for deliberation. Immediate action is required to mitigate any damage. A simple few-minute downtime can have a direct financial impact on clients and damage the platform's reputation. This is why we have strict protocols in place to handle failures, including deploy rollbacks and immediate recovery procedures.&lt;/p&gt;

&lt;p&gt;Setting up alerts to monitor API performance and potential bottlenecks is critical. If an endpoint starts to show issues, we receive instant notifications and often have to resolve the problem in a matter of minutes—or even seconds.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. &lt;strong&gt;Balancing Productivity and Quality of Life&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Handling large financial volumes and the constant pressure to keep the platform running smoothly can be exhausting. However, it's essential to maintain a balance between productivity and quality of life to avoid burnout. Collaboration between teams is key, and we strive to foster a culture of mutual support, where challenges are shared and solved together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;Managing a fintech with such significant revenue requires not only advanced technical skills but also the ability to handle pressure and make swift decisions. The stack of &lt;strong&gt;NestJS&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt;, and &lt;strong&gt;NextJS&lt;/strong&gt; allows us to build a solid and scalable architecture, but the responsibility of keeping everything running without failure is a continuous challenge. In the end, the reward lies in knowing we are building a reliable platform that simplifies financial life for thousands of users, all while continuing to grow and innovate.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>javascript</category>
      <category>startup</category>
    </item>
    <item>
      <title>Os Desafios de Gerenciar uma Fintech de Sucesso: Faturamento de R$9.643.141,49 em 30 Dias</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Mon, 09 Sep 2024 22:49:58 +0000</pubDate>
      <link>https://dev.to/3x_pay/os-desafios-de-gerenciar-uma-fintech-de-sucesso-faturamento-de-r964314149-em-30-dias-2510</link>
      <guid>https://dev.to/3x_pay/os-desafios-de-gerenciar-uma-fintech-de-sucesso-faturamento-de-r964314149-em-30-dias-2510</guid>
      <description>&lt;p&gt;Gerenciar uma fintech que faturou mais de R$9,6 milhões em apenas 30 dias traz uma série de desafios complexos. Para quem está do lado técnico, especialmente como desenvolvedor sênior, cada dia é marcado por decisões que podem impactar profundamente a empresa. Quando estamos trabalhando com uma stack composta por &lt;strong&gt;NestJS&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt; e &lt;strong&gt;NextJS&lt;/strong&gt;, o foco está sempre em garantir que o sistema seja escalável, performático e seguro, mas a realidade vai muito além da escolha de boas ferramentas.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;A Pressão Constante de Não Poder Errar&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Em um ambiente onde se movimentam milhões de reais, a margem para erro é praticamente inexistente. Cada pequena decisão técnica, seja na arquitetura ou na implementação de uma nova funcionalidade, pode afetar diretamente o negócio e, por consequência, os clientes e parceiros. A pressão de garantir que todas as transações sejam processadas corretamente, sem falhas, é constante. Um erro simples, como uma consulta mal otimizada ou uma configuração errada de cache, pode significar prejuízos consideráveis.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;NestJS&lt;/strong&gt;, sendo modular e eficiente, ajuda na organização de código, mas a pressão de manter tudo funcionando sem falhas leva a uma abordagem extremamente cuidadosa para cada novo deploy. Cada linha de código passa por revisões rigorosas e testes automatizados antes de ser aplicada, garantindo que não haja impacto nas transações.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Monitoramento e Manutenção Contínuos&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;O monitoramento em tempo real é outro fator crucial para garantir que a fintech funcione de maneira eficiente. Ferramentas como &lt;strong&gt;Sentry&lt;/strong&gt; para captura de erros e &lt;strong&gt;Grafana&lt;/strong&gt; para métricas de performance são essenciais no dia a dia. Elas nos permitem ter uma visão detalhada de como o sistema está se comportando e detectar potenciais falhas antes que causem um problema maior.&lt;/p&gt;

&lt;p&gt;O uso de &lt;strong&gt;Redis&lt;/strong&gt; para filas de processamento e cache é estratégico para lidar com o alto volume de transações. Ele ajuda a aliviar a carga no banco de dados e distribui o processamento de eventos de maneira eficiente, mas a equipe técnica precisa estar sempre atenta para garantir que nenhuma fila de transação trave, pois isso pode afetar diretamente a experiência dos usuários e causar grandes atrasos.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Escalabilidade e Consistência de Dados&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Manter a escalabilidade de um sistema que processa milhões de reais exige uma arquitetura bem planejada. &lt;strong&gt;PostgreSQL&lt;/strong&gt;, o banco de dados que usamos, requer otimizações contínuas, como &lt;strong&gt;particionamento de tabelas&lt;/strong&gt; e &lt;strong&gt;índices bem definidos&lt;/strong&gt;, para lidar com o crescente volume de dados sem comprometer a performance. Cada consulta precisa ser otimizada, e as rotinas de backup são constantes para evitar qualquer perda de dados.&lt;/p&gt;

&lt;p&gt;A combinação de &lt;strong&gt;NestJS&lt;/strong&gt; e &lt;strong&gt;PostgreSQL&lt;/strong&gt; permite que a estrutura do backend seja escalável, mas garantir a consistência dos dados em transações financeiras complexas é um desafio constante. Precisamos lidar com cenários de concorrência e transações distribuídas, o que torna o desenvolvimento ainda mais desafiador.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Desenvolvimento de Frontend com NextJS&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;O frontend, desenvolvido com &lt;strong&gt;NextJS&lt;/strong&gt;, precisa ser rápido e intuitivo, fornecendo dashboards em tempo real que mostram dados financeiros críticos para os clientes. A experiência do usuário é fundamental, e o uso de SSR (server-side rendering) no NextJS ajuda a garantir uma interface rápida, mesmo com um volume elevado de dados sendo trocado entre o frontend e o backend.&lt;/p&gt;

&lt;h4&gt;
  
  
  5. &lt;strong&gt;Tomada de Decisões Sob Pressão&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;No ambiente de uma fintech, a tomada de decisões rápidas é parte do dia a dia. Quando um problema é detectado, não há tempo para muita deliberação. É preciso agir imediatamente para mitigar os danos. Um simples downtime de minutos pode ter um impacto direto nas finanças dos clientes e prejudicar a confiança na plataforma. Por isso, temos protocolos rígidos para lidar com falhas, incluindo rollback de deploys e procedimentos de recuperação imediata.&lt;/p&gt;

&lt;p&gt;Ter alertas configurados para monitorar a performance das APIs e possíveis gargalos é fundamental. Se um endpoint começa a apresentar problemas, recebemos notificações instantâneas e, muitas vezes, temos que resolver o problema em questão de minutos, ou até segundos.&lt;/p&gt;

&lt;h4&gt;
  
  
  6. &lt;strong&gt;Manter o Equilíbrio: Produtividade e Qualidade de Vida&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Lidar com grandes volumes financeiros e a constante pressão para manter a plataforma operando com eficiência pode ser exaustivo. No entanto, é essencial manter um equilíbrio entre produtividade e qualidade de vida para evitar o desgaste excessivo da equipe. A colaboração entre os times é fundamental, e buscamos ter uma cultura de suporte mútuo, onde as dificuldades são compartilhadas e resolvidas em conjunto.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Gerenciar uma fintech com um faturamento expressivo como o nosso exige não apenas habilidades técnicas avançadas, mas também uma forte capacidade de lidar com pressão e tomar decisões rapidamente. A stack composta por &lt;strong&gt;NestJS&lt;/strong&gt;, &lt;strong&gt;Redis&lt;/strong&gt;, &lt;strong&gt;PostgreSQL&lt;/strong&gt; e &lt;strong&gt;NextJS&lt;/strong&gt; nos permite criar uma arquitetura sólida e escalável, mas a responsabilidade de manter tudo funcionando sem falhas é um desafio constante. No final, a recompensa é saber que estamos construindo uma plataforma confiável, que facilita a vida financeira de milhares de usuários, ao mesmo tempo em que continuamos crescendo e inovando.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>javascript</category>
      <category>startup</category>
      <category>programming</category>
    </item>
    <item>
      <title>Certificados RSA e a Segurança na 3XPay</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Thu, 05 Sep 2024 12:52:14 +0000</pubDate>
      <link>https://dev.to/3x_pay/certificados-rsa-e-a-seguranca-na-3xpay-4po5</link>
      <guid>https://dev.to/3x_pay/certificados-rsa-e-a-seguranca-na-3xpay-4po5</guid>
      <description>&lt;h2&gt;
  
  
  Certificados RSA e a Segurança na 3XPay
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Introdução
&lt;/h3&gt;

&lt;p&gt;Em um mundo digital onde as transações financeiras estão cada vez mais vulneráveis a ataques cibernéticos, garantir a segurança dos dados é essencial, especialmente para fintechs. Na &lt;a href="https://3xpay.co/" rel="noopener noreferrer"&gt;3XPay&lt;/a&gt;, a segurança sempre foi uma prioridade, e para proteger as comunicações entre os usuários e nossa API, adotamos o &lt;strong&gt;RSA&lt;/strong&gt; como parte fundamental da nossa estratégia de criptografia. Neste artigo, vamos explorar o que são certificados RSA, como funcionam e como foram implementados na &lt;a href="https://3xpay.co/" rel="noopener noreferrer"&gt;3XPay&lt;/a&gt; para garantir a proteção dos nossos usuários.&lt;/p&gt;

&lt;h3&gt;
  
  
  O Que é o RSA?
&lt;/h3&gt;

&lt;p&gt;O &lt;strong&gt;RSA (Rivest-Shamir-Adleman)&lt;/strong&gt; é um dos algoritmos de criptografia mais utilizados para proteger comunicações na web. Ele é um método de criptografia de chave pública, o que significa que utiliza duas chaves distintas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Chave pública&lt;/strong&gt;: usada para criptografar os dados.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chave privada&lt;/strong&gt;: usada para descriptografar os dados.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O grande benefício do RSA é que, mesmo que a chave pública seja compartilhada com qualquer pessoa, apenas a chave privada correspondente pode descriptografar os dados, garantindo que a informação permaneça segura durante a transmissão.&lt;/p&gt;

&lt;h3&gt;
  
  
  Como o RSA Funciona?
&lt;/h3&gt;

&lt;p&gt;A segurança do RSA baseia-se em conceitos de &lt;strong&gt;teoria dos números&lt;/strong&gt;, especificamente na dificuldade de fatorar grandes números primos. O processo pode ser resumido em três etapas principais:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Geração de Chaves&lt;/strong&gt;: Dois números primos grandes são selecionados e multiplicados para criar uma chave pública e uma chave privada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Criptografia&lt;/strong&gt;: Os dados são criptografados com a chave pública, tornando-os ilegíveis para qualquer pessoa que não tenha a chave privada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Descriptografia&lt;/strong&gt;: Somente o proprietário da chave privada pode descriptografar e acessar os dados originais.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  A Importância do RSA na 3XPay
&lt;/h3&gt;

&lt;p&gt;A &lt;a href="https://3xpay.co/" rel="noopener noreferrer"&gt;3XPay&lt;/a&gt;lida diariamente com um grande volume de transações financeiras entre nossos usuários e a API. Garantir que essas transações sejam seguras é essencial, pois qualquer vazamento de dados pode comprometer informações sensíveis, como detalhes de cartões de crédito e dados pessoais dos clientes.&lt;/p&gt;

&lt;p&gt;Ao implementar o &lt;strong&gt;RSA&lt;/strong&gt;, conseguimos garantir que todas as comunicações entre os nossos usuários e a nossa API sejam criptografadas, protegendo os dados em trânsito contra ataques de &lt;strong&gt;man-in-the-middle (MitM)&lt;/strong&gt; e interceptações maliciosas.&lt;/p&gt;

&lt;h4&gt;
  
  
  Como o RSA foi Aplicado
&lt;/h4&gt;

&lt;p&gt;Na &lt;a href="https://3xpay.co/" rel="noopener noreferrer"&gt;3XPay&lt;/a&gt;, aplicamos a criptografia RSA em diversos pontos do nosso sistema para garantir a máxima segurança. Aqui estão algumas formas de como o RSA é utilizado:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Criptografia de Dados em Trânsito&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Todas as requisições feitas pelos usuários para nossa API passam por um processo de criptografia. Usamos o &lt;strong&gt;SSL/TLS&lt;/strong&gt; com certificados RSA para criptografar essas comunicações, garantindo que qualquer dado transmitido entre o cliente e os servidores da 3XPay permaneça seguro.&lt;/li&gt;
&lt;li&gt;Mesmo que alguém consiga interceptar os pacotes de dados, eles não serão capazes de descriptografá-los sem a chave privada.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Autenticação Segura&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O RSA também é usado para autenticar a identidade dos nossos servidores e garantir que os usuários estão realmente se conectando à gente, e não a um site malicioso. Isso é feito por meio de certificados digitais emitidos por &lt;strong&gt;autoridades certificadoras (CAs)&lt;/strong&gt; confiáveis, que garantem que o domínio e a chave pública pertencem realmente à nós.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Proteção de Dados Sensíveis&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dados altamente sensíveis, como informações financeiras e pessoais, são criptografados utilizando RSA antes de serem armazenados. Assim, mesmo em caso de uma violação de dados, as informações estariam protegidas.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Benefícios da Criptografia RSA na 3XPay
&lt;/h3&gt;

&lt;p&gt;A implementação do RSA trouxe vários benefícios para a plataforma:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Segurança Aumentada&lt;/strong&gt;: Com o uso de RSA, a comunicação entre usuários e a API é protegida contra interceptações. Mesmo que um atacante capture os dados, ele não conseguirá descriptografá-los sem a chave privada.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Confiança do Cliente&lt;/strong&gt;: Ao garantir a segurança das transações, conquistamos a confiança dos nossos usuários, que podem realizar pagamentos sabendo que suas informações estão protegidas.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Compliance&lt;/strong&gt;: A plataforma também cumpre regulamentações de segurança, como &lt;strong&gt;PCI-DSS&lt;/strong&gt;, exigidas em transações financeiras. O uso de criptografia RSA faz parte das melhores práticas para proteção de dados financeiros.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;O uso de &lt;strong&gt;RSA&lt;/strong&gt; foi fundamental para garantir a segurança das transações na. A criptografia de ponta a ponta, somada à autenticação confiável, assegura que nossos usuários podem confiar na proteção de seus dados, desde o momento em que inserem suas informações até a confirmação da transação.&lt;/p&gt;

&lt;p&gt;Ao investir em criptografia RSA e em certificados digitais, fortalecemos ainda mais como uma plataforma de pagamentos segura e confiável, pronta para atender às demandas crescentes do mercado de fintechs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Próximos Passos
&lt;/h3&gt;

&lt;p&gt;Na &lt;a href="https://3xpay.co/" rel="noopener noreferrer"&gt;3XPay&lt;/a&gt;, continuamos a evoluir nossas práticas de segurança, garantindo que nossos usuários tenham sempre o mais alto nível de proteção. Se você deseja saber mais sobre como implementamos criptografia RSA ou sobre outras medidas de segurança que adotamos, entre em contato conosco!&lt;/p&gt;

</description>
      <category>security</category>
      <category>fintech</category>
      <category>rsa</category>
    </item>
    <item>
      <title>Por que escolhi AWS ECS para uma fintech e não o Serveless</title>
      <dc:creator>fael</dc:creator>
      <pubDate>Thu, 05 Sep 2024 12:00:19 +0000</pubDate>
      <link>https://dev.to/3x_pay/por-que-escolhi-aws-ecs-para-uma-fintech-e-nao-o-serveless-2d69</link>
      <guid>https://dev.to/3x_pay/por-que-escolhi-aws-ecs-para-uma-fintech-e-nao-o-serveless-2d69</guid>
      <description>&lt;p&gt;Fintechs operam em um ambiente altamente dinâmico e regulamentado, onde velocidade, segurança e escalabilidade são essenciais. A escolha da infraestrutura correta pode determinar o sucesso ou fracasso de uma aplicação financeira. Enquanto muitas startups optam por soluções &lt;strong&gt;serverless&lt;/strong&gt;, como AWS Lambda, há situações onde o &lt;strong&gt;AWS ECS Fargate&lt;/strong&gt; se destaca como uma escolha mais adequada. Neste artigo, destacamos por que uma fintech deveria optar pelo &lt;strong&gt;ECS Fargate&lt;/strong&gt; em vez de uma arquitetura serverless, com base em minha experiência prática de enfrentamento de problemas como &lt;strong&gt;cold starts&lt;/strong&gt; e &lt;strong&gt;limitações no tamanho do deploy&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Minha experiência com o serveless
&lt;/h3&gt;

&lt;p&gt;Em um projeto recente de uma &lt;strong&gt;fintech&lt;/strong&gt;, onde construí uma plataforma de pagamentos, inicialmente adotamos uma arquitetura &lt;strong&gt;serverless&lt;/strong&gt; usando o &lt;strong&gt;AWS Lambda&lt;/strong&gt; por sua promessa de escalabilidade automática e gerenciamento simplificado. A ideia de pagar apenas pelo tempo de execução era atraente, mas logo nos deparamos com desafios críticos que afetaram a performance e a experiência do usuário.&lt;/p&gt;

&lt;h4&gt;
  
  
  O Problema do Cold Start
&lt;/h4&gt;

&lt;p&gt;Nosso sistema precisava processar transações em tempo real, respondendo a requisições de pagamento de forma imediata. No entanto, o &lt;strong&gt;cold start&lt;/strong&gt; do serverless tornou-se um gargalo significativo. A cada vez que uma função Lambda era invocada pela primeira vez ou após um período de inatividade, o tempo de resposta da requisição aumentava drasticamente. Essa latência era inaceitável em uma fintech, onde cada segundo conta, especialmente em transações financeiras sensíveis.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; O cold start, particularmente durante picos de atividade, causava atrasos perceptíveis. Tínhamos que implementar soluções de aquecimento (warming) para manter as funções "quentes", mas isso aumentava a complexidade e não eliminava completamente o problema. Em um cenário onde a confiabilidade e velocidade são essenciais, o serverless falhou em oferecer a consistência de performance que precisávamos.&lt;/p&gt;

&lt;h4&gt;
  
  
  Limitações no Tamanho do Deploy
&lt;/h4&gt;

&lt;p&gt;Outro problema surgiu com o crescimento da aplicação. Com a expansão da plataforma, as bibliotecas e dependências do sistema cresceram em complexidade, e as limitações de tamanho de deploy no &lt;strong&gt;Serverless Framework&lt;/strong&gt; começaram a ser um obstáculo. Tínhamos que reestruturar pacotes e eliminar funcionalidades essenciais para caber no limite permitido.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; Essa limitação de tamanho obrigou nossa equipe a buscar soluções alternativas, como dividir funções ou reduzir o uso de bibliotecas pesadas, mas isso comprometia a agilidade no desenvolvimento. A fintech precisava de um sistema robusto que suportasse suas dependências sem restrições.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Mudança para AWS ECS Fargate
&lt;/h3&gt;

&lt;p&gt;Com os desafios de &lt;strong&gt;cold start&lt;/strong&gt; e limitações de deploy no serverless, decidimos migrar nossa plataforma de pagamento para o &lt;strong&gt;AWS ECS Fargate&lt;/strong&gt;. Essa mudança trouxe uma série de benefícios para a arquitetura da fintech.&lt;/p&gt;

&lt;h4&gt;
  
  
  1. &lt;strong&gt;Eliminação do Cold Start&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;No ECS Fargate, os containers podem ser mantidos em execução por longos períodos, eliminando a latência de inicialização que tanto afetava nossa plataforma no serverless. Isso trouxe uma melhoria imediata na performance, especialmente em transações de pagamento que exigiam respostas rápidas e consistentes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; Após a migração para o Fargate, notamos uma drástica redução na latência das requisições. As transações passaram a ser processadas quase instantaneamente, e o problema de cold start desapareceu completamente. A consistência de resposta foi crucial para a confiança dos nossos usuários.&lt;/p&gt;

&lt;h4&gt;
  
  
  2. &lt;strong&gt;Escalabilidade Automática e Controle de Custos&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Assim como o serverless, o ECS Fargate oferece &lt;strong&gt;escalabilidade automática&lt;/strong&gt;, mas com o benefício adicional de maior controle sobre os recursos alocados (CPU e memória). Em uma fintech, onde o volume de transações pode variar ao longo do dia, a capacidade de ajustar a infraestrutura com precisão foi um ponto positivo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; Com o Fargate, conseguimos escalar nossa aplicação de forma dinâmica, ajustando os containers com base na demanda. Além disso, a opção de usar &lt;strong&gt;Spot Instances&lt;/strong&gt; no Fargate nos permitiu reduzir custos sem sacrificar o desempenho.&lt;/p&gt;

&lt;h4&gt;
  
  
  3. &lt;strong&gt;Flexibilidade no Tamanho do Deploy&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;A principal vantagem do ECS Fargate em relação ao serverless foi a liberdade em termos de deploy. Não havia mais as rígidas limitações de tamanho, permitindo que nossa aplicação mantivesse todas as suas dependências e bibliotecas intactas, sem a necessidade de comprometer funcionalidades.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; A migração para containers eliminou a frustração de lidar com limites de tamanho de pacote. Agora, podíamos fazer deploy de atualizações complexas sem nos preocupar com restrições, acelerando o ciclo de desenvolvimento e entregando novas funcionalidades mais rapidamente.&lt;/p&gt;

&lt;h4&gt;
  
  
  4. &lt;strong&gt;Ambiente Controlado e Seguro&lt;/strong&gt;
&lt;/h4&gt;

&lt;p&gt;Com o ECS Fargate, também ganhamos controle granular sobre o ambiente de execução, algo crítico para garantir &lt;strong&gt;conformidade com normas regulatórias&lt;/strong&gt;, como PCI DSS. A capacidade de configurar redes privadas, grupos de segurança e políticas de acesso específicas nos deu maior controle sobre a segurança da plataforma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Experiência:&lt;/strong&gt; Para uma fintech, a segurança é primordial. O controle oferecido pelo Fargate nos permitiu isolar partes críticas da aplicação e garantir que todos os dados fossem processados em um ambiente seguro e conforme as exigências regulatórias.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusão
&lt;/h3&gt;

&lt;p&gt;Para fintechs, a escolha entre &lt;strong&gt;Serverless&lt;/strong&gt; e &lt;strong&gt;ECS Fargate&lt;/strong&gt; depende das necessidades específicas do projeto. Enquanto o serverless pode ser adequado para cargas de trabalho simples e intermitentes, enfrentamos desafios com &lt;strong&gt;cold starts&lt;/strong&gt; e &lt;strong&gt;limitações de deploy&lt;/strong&gt; que prejudicaram a performance e a escalabilidade da nossa plataforma de pagamentos.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;AWS ECS Fargate&lt;/strong&gt; emergiu como a solução ideal, oferecendo maior controle, escalabilidade sem comprometimentos e eliminação dos problemas de latência. Para fintechs que lidam com operações financeiras críticas, a consistência e a flexibilidade do Fargate fazem dele a escolha superior.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>fintec</category>
      <category>ecs</category>
      <category>serverless</category>
    </item>
  </channel>
</rss>
