código mais escalável? Nós sempre nos preocupamos com a escalabilidade em termos de infraestrutura, mas muitas vezes negligenciamos a qualidade e a habilidade do código de crescer — seja em termos de funcionalidades, modificações ou mesmo de processamento. Código bem escrito e testado = código mais fácil de modificar e crescer
gerenciamento e envio de campanhas por SMS. - Clientes enviavam listas de dados - Campanhas segmentadas eram criadas para cada uma dessas listas. - A plataforma cobrava um valor mensal.
dados (100M+) 2. Lookup de dados geográficos custoso 3. Processo demorado Criação de campanha 1. Queries relativamente custosas 2. Base de dados grande 3. Processos complexos durante a criação de cada mensagem a ser enviada Envio de mensagem 1. Rápido 2. Número alto de operações por segundo 3. Cálculo do número máximo de mensagens/minuto/conta durante tempo de execução 4. Suporte a diversos serviços de envio
custosa em grande escala 2. Verificações de "stop-words" no banco de dados 3. Possível bloqueio de envios para um número Envio de mensagens de resposta 1. Acontece após o recebimento de uma resposta positive (reply keyword) 2. Acontece como um envio normal de mensagem
Grande parte da aplicação era escrita em Laravel. Para envio de mensagens, existia um worker escrito em Go que buscava mensagens pendentes no banco e as enviava.
de dados de localização a partir do número de telefone custosa • Grande número de queries para cada contato • Número muito alto de contatos sendo criados por minuto
tipos de webhooks: delivery reports e respostas em texto. O número de delivery reports era de 1 pra 1 — ou seja, para cada mensagem enviada, recebíamos ao menos uma requisição de volta. À medida que as campanhas eram iniciadas, o número de requisições por segundo aumentava e começávamos a ter problemas com o tempo de resposta e erros 500.
milhões de registros em cada coleção. O fato de todas as operações de pausa/cancelamento de campanhas basearem-se em mover uma grande quantidade de dados de uma coleção para outra não ajudava.
as mensagens pendentes, não tinha uma UI ou log, o que tornava o monitoramento complicado. Além disso, a adição de novos drivers era também complicada, já que era necessário adicionar código em dois lugares diferentes.
ferramentas e esquecer do essencial, muitas vezes otimizando algo onde nunca houve um problema. • Seu banco de dados tem os índices corretos? • Seu banco tem os tipos corretos? (nada de VARCHAR(255))! • O seu servidor e gerenciador de processos (NGINX e PHP-FPM, por exemplo) estão corretamente configurados? • As suas queries estão otimizadas? • Você tem ferramentas para te informar onde estão os gargalos?
as pequenas coisas. Um exemplo disso é a forma como o Laravel lida com Models como argumentos nos jobs: ele desserializa o model durante o despacho, e serializa ele quando um worker consome o job. Nesse processo, o worker executa uma query para buscar esse model. Isso resulta em 2 coisas: - O estado que você espera nesse model talvez não seja o que o worker tenha - Uma query extra é executada, e fazer isso 1000 vezes por segundo pode ser problemático
300M+ contatos importados por dia • >500M jobs num período de 12 horas • > 30,000 reqs/min • Custo com infraestrutura abaixo de 900 USD • Facilmente escalável horizontalmente • Gerenciamento fácil das filas através do Laravel Horizon • Facilidade de adicionar novos provedores • Código fácil de modificar e estender, além de bem testado
permitem à equipe ter mais segurança e conforto durante o desenvolvimento, e garantem a estabilidade da aplicação no longo prazo. Nunca conseguiríamos adicionar tantos provedores e garantir que tudo funcionava corretamente sem testes.