githublinkedinemail
← /articles

Você NÃO entende Rails até entender o ciclo completo de uma Request

Rails não é mágico. Rails é Rack, TCP, Threads, Middleware, SQL e objetos Ruby na heap. Entenda o que acontece antes e depois do seu controller.

5 minrails

Você NÃO entende Rails até entender o ciclo completo de uma Request

Tem uma mentira que a comunidade Rails contou por muitos anos.

"Rails é mágico."

Não.

Rails não é mágico.

Rails é:

  • Rack
  • TCP
  • Threads
  • Middleware
  • SQL
  • IO
  • Serialização
  • Objetos Ruby na heap

E o problema é que muita gente passa anos escrevendo:

def show
  @user = User.find(params[:id])
end

…sem entender o que acontece antes e depois disso.

Aí quando produção começa a:

  • ficar lenta
  • consumir memória
  • travar thread
  • dar timeout
  • explodir CPU
  • gerar lock no banco

…o debugging vira superstição.

Porque quem não entende o ciclo da request…
…debuga no escuro.


A ilusão do "controller = Rails"

A maioria dos iniciantes acha que Rails é:

  • controller
  • model
  • view

Só isso.

Mas controller é literalmente UMA ETAPA do pipeline inteiro.

Quando você recebe uma request HTTP:

GET /users/1

Existe um ecossistema inteiro acontecendo antes do:

User.find(params[:id])

E é justamente aí que vivem:

  • gargalos
  • concorrência
  • observabilidade
  • autenticação
  • sessões
  • performance real

Tudo começa fora do Rails

Primeira coisa importante:

Rails NÃO recebe conexão TCP.

Quem faz isso é:

  • Puma
  • Unicorn
  • Passenger

O Rails é só uma aplicação Rack.

Isso muda completamente sua percepção da stack.

O fluxo real começa assim:

Browser
   ↓
Kernel Linux
   ↓
Socket TCP
   ↓
Puma
   ↓
Rack
   ↓
Rails

Percebe a diferença?

Rails está LONGE de ser a primeira camada.


O Puma e a realidade de produção

O Puma fica escutando sockets TCP no Linux.

Quando chega uma request:

  1. ele aceita a conexão
  2. pega/reutiliza uma thread
  3. cria o contexto da request
  4. passa isso pra Rack

E aqui já nasce um problema clássico:

"Meu Rails está lento."

Talvez não esteja.

Talvez você:

  • esteja bloqueando thread
  • fazendo IO síncrono demais
  • destruindo concorrência
  • gerando starvation
  • segurando conexão do banco por muito tempo

Rails performance quase nunca é "só Rails".

É o ciclo inteiro.


Rack: a peça invisível do Ruby Web

Se você trabalha com Rails há anos e nunca estudou Rack…
…você provavelmente ainda não entendeu Rails de verdade.

Rack é a interface padrão entre:

  • servidores web Ruby
  • frameworks Ruby

É o equivalente ao:

  • WSGI no Python
  • middleware pipeline no Express
  • interface HTTP do ecossistema Ruby

O Puma basicamente faz isso:

env = { ... }
Rails.application.call(env)

Só isso.

Rails recebe um hash gigante chamado env.

E responde no formato Rack:

[
  status,   # 200, 404, 500...
  headers,  # { "Content-Type" => "text/html" }
  body      # ["<html>...</html>"]
]

É literalmente isso.

Toda "mágica" do Rails existe em cima dessa abstração extremamente simples.


Middleware: o lugar onde metade do Rails acontece

Aqui está uma das partes mais subestimadas da stack.

Antes de chegar no controller…
…a request passa por dezenas de middlewares.

Exemplo:

  • cookies
  • sessão
  • autenticação
  • CSRF
  • compressão
  • logs
  • static files

Tudo middleware.

Fluxo simplificado:

Request
   ↓
Rack::Sendfile
   ↓
Cookies
   ↓
Session
   ↓
Warden/Devise
   ↓
CSRF
   ↓
Rails App

E isso é MUITO importante.

Porque:

  • middleware pode interromper request
  • middleware pode responder direto
  • middleware pode modificar response
  • middleware pode capturar exception

Seu controller nem sempre executa.

Muita gente nunca percebe isso.


Routing não chama controller "direto"

Outra abstração que confunde iniciantes.

Quando você define:

get "/users/:id"

O Rails não "executa o método".

Ele:

  1. faz matching da rota
  2. resolve controller/action
  3. cria um endpoint executável
  4. monta o contexto da request

Routing é muito mais próximo de um dispatcher do que de uma simples tabela de URLs.


Finalmente: o controller

Agora sim chegamos na parte que todo mundo conhece.

O Rails:

  1. instancia controller
  2. executa callbacks
  3. roda action

Exemplo:

before_action :authenticate_user!

def show
  @user = User.find(params[:id])
end

Mas aqui existe outra ilusão.

Esse User.find parece inocente.

Mas internamente:

  1. pega conexão do pool
  2. gera SQL
  3. conversa com Postgres
  4. espera IO
  5. desserializa resultado
  6. instancia objeto Ruby

Uma linha de ActiveRecord pode atravessar:

  • rede
  • banco
  • serialização
  • memória
  • garbage collector

E aí vem a clássica frase:

"Rails não escala."

Não.

Seu código talvez não escale.


Rendering é MUITO mais caro do que parece

Depois da action…
…o Rails ainda precisa gerar resposta.

Se for HTML:

  1. encontra template
  2. processa ERB
  3. aplica layout
  4. renderiza partials
  5. monta HTML final

E isso pode ficar absurdamente caro.

Principalmente quando você:

  • renderiza partial em loop
  • cria helpers demais
  • gera árvore gigante de componentes
  • faz lógica pesada na view

Rails renderiza MUITO objeto Ruby.

E objeto Ruby custa memória.


A response sobe toda a stack novamente

Depois do render:

  • response volta pelos middlewares
  • cookies são serializados
  • sessão é salva
  • gzip pode ser aplicado
  • logs são escritos
  • métricas são coletadas

Ferramentas como:

  • NewRelic
  • Datadog
  • Skylight
  • Sentry

vivem interceptando esse ciclo.

Observabilidade moderna depende totalmente dessa pipeline.


O grande erro dos iniciantes

O erro é achar que web framework é:

Request → Controller → Response

Não é.

Na vida real existe:

kernel → socket → scheduler → thread
   ↓
middleware → pool de conexão → IO
   ↓
serialização → cache → GC → banco
   ↓
render pipeline → response

E Rails abstrai tudo isso MUITO bem.

Tão bem…
…que muita gente nunca aprende.


A grande virada de chave

O dia que você entende request lifecycle…
…você para de "usar Rails".

E começa a entender:

  • aplicações web
  • concorrência
  • throughput
  • observabilidade
  • latência
  • arquitetura
  • trade-offs reais

E aí finalmente:

  • profiling faz sentido
  • logs fazem sentido
  • APM faz sentido
  • pgBadger faz sentido
  • N+1 faz sentido
  • connection pool faz sentido

Porque agora você consegue enxergar a request inteira.

Não só o controller.


Conclusão

Rails nunca foi magia.

A comunidade só romantizou abstrações.

Por baixo:

  • ainda é TCP
  • ainda é IO
  • ainda é SQL
  • ainda é memória
  • ainda é concorrência
  • ainda é Linux
  • ainda é engenharia de sistemas

E honestamente?

Quanto mais senior você fica…
…menos "mágico" Rails parece.

E mais elegante ele se torna.


Você NÃO entende Rails até entender o ciclo completo de uma Request
Você NÃO entende Rails até entender o ciclo completo de uma Request