Icon ruby The 2026 Ruby on Rails Community Survey is open. Add your voice!

Article  |  Development

Uma História de Upgrade para Rails 8: Ganhando Tração Sem Reescrever Tudo

Reading time: ~ 9 minutes

Uma História de Upgrade para Rails 8: Ganhando Tração Sem Reescrever Tudo

For our Brazilian community, here's a Portuguese version of the original post written by Jaison Coelho.

Evoluir sua aplicação Rails não é sobre recomeçar do zero- é sobre escrever o próximo capítulo com confiança.

Se você tem uma aplicação Rails com mais de 5 anos, ela pode começar a parecer uma bomba-relógio. Quando você abre o codebase e vê gems desatualizadas, warnings e features escritas por desenvolvedores que saíram há muito tempo, é fácil pensar: "A gente está atrasado demais. Talvez a melhor saída seja reconstruir tudo do zero."

É uma reação comum, mas reescritas costumam acabar sendo mais caras, mais disruptivas e mais lentas para entregar resultados do que se imagina. Além disso, aplicações legadas ainda guardam o coração do negócio- lógica central, dados de clientes, integrações e fluxos de trabalho que merecem cuidado, não substituição.

A boa notícia? Você não precisa começar do zero para se preparar para o Rails 8. Dá para evoluir o que você já tem- modernizando passo a passo, sem perder o valor construído ao longo dos anos. É esse tipo de cuidado que levamos para os projetos: ajudar bons softwares a encontrar seu segundo ato.

Recentemente, ajudamos um cliente a modernizar uma aplicação em Rails 5.2, fazendo o upgrade incremental até o Rails 7.1, com um caminho claro e de baixo risco até o Rails 8. A aplicação se manteve no ar, o negócio continuou rodando e o time recuperou a confiança no próprio codebase. Aqui vai como fizemos isso.

O Problema: Quando se Manter Atualizado Parece Inalcançável

Aplicações Rails legadas existem há tempo suficiente para já terem provado seu valor para o negócio- mas também há tempo suficiente para terem acumulado complexidade. Com o passar dos anos, o que antes era cutting-edge começa a parecer complicado ou frágil. Talvez você reconheça alguns destes padrões:

  • Sua aplicação tem mais de 7 anos, com contribuições de vários desenvolvedores ao longo do tempo.
  • As gems estão congeladas no tempo, algumas sem updates há anos.
  • O technical debt vai se acumulando em camadas, fácil de ignorar- até começar a te atrasar.
  • Códigos frágeis "simplesmente funcionam", e qualquer mudança parece arriscada.
  • Existe pressão competitiva de aplicações mais novas e ágeis.

Nosso cliente vivia todos esses cenários. A aplicação Rails 5.2 deles vinha sustentando o negócio de forma confiável havia anos. Os clientes dependiam dela todos os dias, mas o lançamento do Rails 8 criou urgência. Eles sabiam que ficar ainda mais para trás poderia colocá-los em risco; mas a ideia de uma reescrita completa parecia avassaladora: custos altos, prazo longo e uma disrupção enorme para os usuários.

A pergunta que eles trouxeram pra gente foi: "Dá para avançar sem começar tudo de novo?"

A Abordagem: Audit First, Panic Never

A pior maneira de tocar um upgrade de Rails é entrar de cabeça, mudando versões e torcendo para os testes pegarem o que quebrar. É daí que vem o medo — os times não sabem o que está escondido no codebase. Nossa filosofia é simples: upgrades não são tarefas chatas, são oportunidades de ganhar clareza.

Por isso, começamos com uma auditoria técnica completa. Em vez de adivinhar onde estavam os riscos, mapeamos o ecossistema inteiro da aplicação: dependências, perfil de segurança, problemas de performance e tolerância a mudanças. Essa visão ajudou o time a sair do "estamos travados" para o "temos controle do futuro da nossa aplicação".

O Que Auditamos

Olhamos para a aplicação por vários ângulos:

Compatibilidade da versão do Ruby. Em qual versão estávamos rodando? Que versões existiam entre o Ruby 2.6 (a base do cliente) e o 3.2 moderno que precisaríamos para Rails 8+? Cada salto tinha que ser planejado com cuidado para evitar quebra de gems.

Dependências de gems. Identificamos gems que estavam perigosamente desatualizadas, incompatíveis com Rails 6/7 ou totalmente abandonadas. Eram potenciais bloqueios e precisavam de estratégias de substituição.

Cobertura de testes. Avaliamos quanto da aplicação tinha rede de proteção. Onde havia lacunas, escrevemos testes para a lógica de negócio crítica primeiro, garantindo que os upgrades não quebrassem silenciosamente features que geravam receita.

Vulnerabilidades de segurança. Rodamos scans para detectar riscos escondidos em dependências antigas e em pontos do código onde entradas não recebem tratamento adequado. Um upgrade é a hora ideal para fechar essas portas.

Problemas de performance. Usando ferramentas de profiling, sinalizamos pontos onde a aplicação já estava lenta — para que o upgrade não piorasse o problema.

Padrões deprecated. O Rails é famoso por ter caminhos de deprecation claros, mas só funciona se você pegar cedo. Caçamos métodos e configurações que iriam quebrar assim que o Rails 6+ entrasse em cena.

Nossas Ferramentas de Auditoria (e Por Que Importaram)

Integramos um conjunto de ferramentas em uma pipeline de CI, cada uma mirando uma área específica de risco- dando aos desenvolvedores e stakeholders uma imagem clara do estado da aplicação.

bundle outdated → Risco de Dependências

Essa ferramenta lista gems desatualizadas, destacando patches de segurança e problemas de compatibilidade. Rodamos bundle outdated --strict na pipeline de CI, cruzando informações com bancos de CVEs para priorizar updates críticos. Isso evitou falhas em produção ao pegar problemas de compatibilidade cedo, economizando semanas de debugging.

Brakeman → Risco de Segurança

O Brakeman escaneia código Rails em busca de vulnerabilidades como SQL injection ou XSS. Configuramos com um arquivo de ignore customizado para filtrar falsos positivos, rodando antes do upgrade para fortalecer a aplicação. Resolver vulnerabilidades cedo significou que o upgrade melhorou a segurança, não só a compatibilidade — tranquilizando os stakeholders sobre a segurança dos dados.

RubyCritic → Risco de Manutenibilidade

O RubyCritic pontua a qualidade do código, sinalizando complexidade (notas Flog > 30) e code smells. Usamos para priorizar refactors antes dos upgrades. Isso deixou o codebase mais fácil de manter, reduzindo o technical debt futuro para os desenvolvedores.

Ferramentas de Performance Profiling → Risco para a Experiência do Usuário

Ferramentas como Bullet e Rack Mini Profiler, rodadas em staging, identificaram gargalos como N+1 queries. Estabelecemos uma baseline de performance para garantir que os upgrades não degradassem a experiência do usuário. Páginas mais rápidas melhoraram a satisfação dos usuários, sustentando diretamente metas de negócio como retenção.

Combinando essas ferramentas em uma pipeline em estágios- primeiro dependências, depois segurança, manutenibilidade e performance — eliminamos pontos cegos, tornando viável um upgrade sem reescrita.

O Plano: Mapeando uma Estratégia de Upgrade Sem Reescrita

Desenhamos um roadmap incremental, dividindo o upgrade em quatro fases. Cada uma garantia estabilidade para milhares de usuários enquanto preparava o caminho para o Rails 8. Não era uma missão de resgate- era um roteiro de evolução.

Cada fase construiu confiança e reduziu risco, provando que modernização não precisa significar disrupção. Aqui vai um resumo de cada fase e como trabalhamos no nosso plano.

Fase 1: Trabalho de Fundação

Proteger a aplicação, economizar tempo de debugging e garantir uptime.

  • Upgrade do Ruby 2.6 para 3.2, testando com rbenv (por exemplo, resolvemos problemas com nokogiri).
  • Atualização de gems como Devise via bundle outdated para compatibilidade com Rails 7.
  • Correção de vulnerabilidades XSS apontadas pelo Brakeman com strong_parameters.
  • Aumento da cobertura de testes da lógica de pagamento de 60% para 85%.

Fase 2: Rails Minor Upgrades

Limpar deprecations e facilitar major upgrades.

  • Patch para Rails 5.2.8 por questões de segurança.
  • Upgrade para Rails 6.0, depois 6.1, corrigindo queries where.not por causa da deprecation de NOR para NAND.
  • Atualização do database.yml para múltiplos bancos de dados.

Fase 3: Rails Major Upgrades

Modernizar a infraestrutura e aumentar a eficiência.

  • Upgrade para Rails 7.0 e depois 7.1, corrigindo problemas de autoloading do Zeitwerk ao alinhar nomes de arquivo com nomes de classe/módulo (por exemplo, user.rbclass User, em vez de nomes desalinhados como user_model.rbclass User).
  • Migração para o Propshaft, resolvendo 404s de assets.
  • Adoção do importmap-rails, reescrevendo jQuery para Stimulus.

Fase 4: Preparação para Rails 8

Preparar para o Rails 8 e manter a performance.

  • Testamos features beta do Rails 8 em staging, incluindo o Solid Queue para processamento de background jobs nativo.
  • Garantimos compatibilidade de gems (testando, por exemplo, a branch main do Devise) com bundle update.
  • Caching para queries de relatórios; documentamos Turbo streams para facilitar o onboarding.

Framework de Priorização

Pontuamos as tarefas em três fatores:

  1. Impacto: melhora performance, segurança ou produtividade dos desenvolvedores?
  2. Esforço: quantas horas de desenvolvedor ou complexidade envolve?
  3. Risco: pode causar regressões ou downtime?

Tarefas de alto Impacto e baixo Esforço (como o upgrade do Ruby 3.2) vieram primeiro, enquanto tarefas de alto Risco (como refatorações de ActiveRecord) precisaram de testes extras. Por exemplo, o upgrade do Ruby pontuou alto em Impacto (destravou features do Rails 7) e moderado em Esforço (updates de gems), com baixo Risco graças à cobertura de testes. Quando conflitos de gems atrasaram features não críticas, adiamos para fases posteriores, equilibrando velocidade e estabilidade.

Complicações Que Encontramos

Mudanças no ActiveRecord: A deprecation do where.not no Rails 6 (de NOR para NAND) quebrou queries de relatórios (por exemplo, Post.where.not(source_type: "Feed", source_id: 100)). Refatoramos para chamadas where.not encadeadas (por exemplo, Post.where.not(source_type: "Feed").where.not(source_id: 100)), garantindo a precisão dos dados.

Conflitos de Gems: will_paginate não era compatível com Rails 7. Migramos para o pagy, reescrevendo as views- mas ganhamos eficiência de memória.

Código Deprecated: As deprecations do ActionController no Rails 5.2 (como sintaxe antiga de render) viraram erros no Rails 6. O deprecation_toolkit na CI ajudou a corrigir a maioria de forma proativa.

Mudanças no Fingerprinting do Sprockets: O regex do Rails 6.1 quebrou assets com nomes não padrão (por exemplo, image-1.2.3.js), causando 404s. Definimos config.assets.unknown_asset_fallback = true temporariamente e renomeamos os assets, evitando erros visíveis para os usuários.

O Resultado: Pronto para Rails 8, Sem Precisar de Reescrita

No fim do projeto, a aplicação do cliente estava rodando com confiança em Rails 7.1, com um caminho claro até o Rails 8- entregue sem reescrita e sem downtime. Ao longo de três meses, mantivemos o serviço no ar para milhares de usuários diários enquanto modernizávamos o codebase de forma constante.

O retorno do upgrade veio rápido: dashboards que antes levavam quase quatro segundos para carregar agora renderizam em menos de dois, suítes de testes que arrastavam por quinze minutos agora terminam em cinco, e cada vulnerabilidade crítica encontrada na auditoria foi corrigida.

E não menos importante: a aplicação agora segue as convenções atuais do Rails, tornando o onboarding de novos desenvolvedores mais rápido e menos doloroso. O time recuperou a confiança no próprio sistema. O que antes parecia uma aplicação legada e frágil agora parece uma fundação para crescer- um verdadeiro segundo ato.

Impactos no Negócio

O upgrade significou menos tempo apagando incêndio e mais tempo construindo. Com menos problemas em produção, os desenvolvedores do cliente puderam focar em entregar novas features em vez de remendar antigas. Padrões modernos do Rails e testes mais rápidos encurtaram os ciclos de release de semanas para dias, dando à empresa uma vantagem competitiva real. E mais importante: ao evitar uma reescrita custosa, o cliente preservou o orçamento e ainda assim garantiu uma plataforma mais rápida, mais segura e pronta para adotar features do Rails 8 quando chegar a hora.

Feedback do Cliente

"Achávamos que reconstruir do zero era nossa única opção. No fim, modernizamos de forma incremental enquanto o negócio continuava rodando. O processo foi bem menos disruptivo do que temíamos."

Como Você Também Pode se Preparar para o Rails 8

  1. Não reescreva, revise: audite sua aplicação para descobrir os pontos fortes e os riscos. Boa parte do seu código "legado" carrega valor de negócio que vale a pena preservar.
  2. Audite antes de agir: use ferramentas para mapear dependências, segurança e performance antes de planejar.
  3. Quebre o trabalho em pedaços: upgrades incrementais entregam valor de forma segura, fase por fase.
  4. Trabalhe com quem tem experiência: escolha um time que já tenha ajudado outras organizações a modernizar sem dar pause no negócio.
  5. Conecte upgrades com valor de negócio: amarre cada passo a resultados tangíveis — mais performance, mais segurança, usuários mais satisfeitos.

Toda aplicação Rails que sobreviveu ao tempo tem uma história que vale a pena continuar.

O Rails 8 é só o próximo capítulo. Com o plano certo e os parceiros certos, o segundo ato da sua aplicação pode ser ainda mais forte do que o primeiro.

Perguntas Frequentes

Dá para fazer upgrade para Rails 8 sem reescrever a aplicação?

Sim. Na maioria dos casos, uma reescrita completa não é necessária. Dá para modernizar sua aplicação atual com upgrades incrementais e bem pensados, que mantêm o negócio rodando enquanto você se prepara para o futuro.

Qual a vantagem de fazer upgrade em vez de começar do zero?

Fazer o upgrade permite construir sobre a fundação que você já tem- seu código, o conhecimento do seu time e a confiança dos seus clientes. Uma reescrita costuma resetar tudo isso, enquanto um upgrade preserva o investimento e adiciona novas capacidades.

Quanto tempo leva um upgrade para Rails 8?

Cada aplicação é diferente. Costumamos recomendar começar com uma auditoria técnica curta para identificar dependências, riscos e oportunidades. A partir daí, montamos um plano em fases- geralmente algo entre algumas semanas e alguns meses, dependendo da complexidade.

Qual versão do Ruby preciso usar para o Rails 8?

O Rails 8 exige Ruby 3.2 ou superior. Se sua aplicação ainda está em Ruby 2.x, o upgrade do Ruby é um passo essencial- e que já traz ganhos imediatos em performance e segurança.

Como saber se minha aplicação está pronta para o Rails 8?

Se sua aplicação roda em Rails 6 ou 7 com Ruby e gems atualizados recentemente, você está em ótima forma. Se você está várias versões atrás, uma auditoria técnica vai esclarecer o que precisa de atenção primeiro.

Não dá para ficar numa versão mais antiga?

Dá- mas com o tempo isso fica mais caro e mais arriscado. Versões fora de suporte param de receber patches de segurança, e os upgrades vão ficando mais difíceis. Updates incrementais mantêm sua aplicação saudável e adaptável.

Have a project that needs help?