Conceitos do framework Rails e de performance de aplicações explicados a fundo, um de cada vez.
Uma migration que roda em 40ms em dev pode segurar um lock ACCESS EXCLUSIVE em uma tabela de produção por minutos; este conceito cobre exatamente qual DDL trava o quê, como o strong_migrations pega isso antes de ir para produção, e o padrão de múltiplos deploys para mudanças que são inseguras não importa como você as escreva.
Uma réplica de leitura tira carga de query mas não faz nada pela vazão de escrita ou armazenamento no primário; sharding é o passo muito maior e muito mais difícil para quando o próprio primário é o gargalo. O Rails 6+ te dá connects_to, connected_to, e middleware automático de DatabaseSelector/ShardSelector para os dois, mas a janela de defasagem de 2 segundos e joins entre shards carregam cada um modos de falha reais e fáceis de perder.
Quais índices um schema Rails de fato precisa, por que a ordem de colunas de um índice composto decide tudo, e como confirmar a partir de um console Rails que o Postgres está de fato usando o índice que você adicionou.
includes não é uma estratégia, é uma escolha entre preload e eager_load, e eager loading aninhado pode multiplicar objetos instanciados até ficar mais lento que o N+1 que substituiu. Mais: agregação em SQL, e activerecord-import para escritas em massa.
A aritmética de processos x threads x hosts que seu pool de banco de dados precisa caber, por que a sobreposição no momento do deploy é o risco real, e como o tamanho do pool no pgbouncer significa algo diferente.
A fonte mais comum de N+1s escondidos não é um includes faltando, é um método de query do ActiveRecord morando silenciosamente dentro de um método de instância.
O Rails 8 usa por padrão adaptadores de job, cache e pubsub apoiados em banco de dados em vez de Redis; a 37signals cortou o custo de cache do Basecamp em 80% e sua latência P95 pela metade fazendo isso, mas polling não é push, e o teto honesto de cada adaptador é documentado, não presumido.
O Rails custa ~28ms por requisição sobre o Rack puro; um erro de arredondamento contra um carregamento de página de 700ms, mas uma conta real em uma API de alto tráfego; aqui estão as alavancas, e por que um Rails enxuto acabou sendo 25% mais rápido que o Sinatra puro.
instances_needed = arrival_rate x average_response_time, a única equação por trás do dimensionamento de frota, por que 100% de utilização é um incidente esperando uma explosão de tráfego, e por que tempo de fila (não tempo de resposta) é o único sinal honesto para escalar.
Todo servidor de aplicação Ruby escolhe um trade-off entre se defender de um cliente lento e se defender de uma aplicação lenta; saber qual é qual decide a topologia do seu deploy.
A regra de o caminho do arquivo espelhar o namespace do Zeitwerk é um contrato em tempo de execução, não um guia de estilo; violá-la te dá um Zeitwerk::NameError, muitas vezes no primeiro eager load em CI ou produção em vez de em desenvolvimento local. Este conceito cobre o próprio contrato, as colisões de sigla e nomenclatura STI que o quebram em escala, e as duas ferramentas reais para desenhar fronteiras de módulo, Rails Engines e Packwerk, com os trade-offs concretos entre elas.
Tenancy baseada em linha, em schema, e em banco de dados compram garantias de isolamento muito diferentes a custos operacionais muito diferentes, e a mais barata (um schema compartilhado com uma coluna tenant_id) impõe isolamento inteiramente em código de aplicação, onde um único scope esquecido é um vazamento completo de dados entre tenants.
Os padrões do rack-attack parecem prontos no momento em que inicializam, mas um cache store por processo em um deploy Puma multiworker subconta requisições silenciosamente e torna um limite de throttle sem sentido. Este conceito cobre a DSL, o requisito de cache store compartilhado que de fato faz o throttling funcionar, a explosão de borda do algoritmo de janela fixa, e por que bloquear por IP é um risco de falso positivo atrás de NAT compartilhado.
Pundit vs CanCanCan é uma escolha arquitetural, permit! é um buraco de mass assignment com um nome de um caractere, e cookies_serializer = :marshal transforma um secret_key_base vazado em execução remota de código em vez de só falsificação de sessão.