🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)
🕵️ SicherheitslückenHak5: Hackers Just Poisoned the Rust Supply Chain | Threat Wire(01.09.2026 um 14:00 Uhr)
🕵️ SicherheitslückenHak5: Hackers Found a Way Into Humanoid Robots | Threat Wire(04.09.2026 um 15:04 Uhr)
🔧 AI Nachrichten Bits und so #1021 (Passwort für Laufwerk)(31.08.2026 um 22:15 Uhr)
🔧 AI Nachrichten Bits und so #1022 (Wie Weißbier)(06.09.2026 um 20:39 Uhr)
🍏 iOS / Mac OSHue-App 6.0 ist da: das sind die Neuerungen(07.09.2026 um 17:21 Uhr)

🔧 Programmierung 🕛 kürzlich 5 Min Lesezeit
0

N+1: o bug silencioso que trava seu Laravel em produção

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




Sua tela demora 8 segundos e o servidor não tem culpa



O cliente manda a mensagem: "o painel tá travando".



Você abre em produção. Conta os segundos. Um... dois... oito. A tela de listagem de pedidos, que tem 50 linhas, demora uma eternidade pra carregar.



Primeiro palpite: servidor fraco. Você já tá quase abrindo um chamado pra subir o plano da VPS.



Segura o dedo. Na esmagadora maioria das vezes, não é o servidor. É o N+1 query — o bug mais silencioso e mais comum do Eloquent. Ele não quebra nada, não estoura erro, não aparece no log. Só deixa tudo lento e finge que a culpa é de outro.






O código parece inofensivo (e é aí que mora o problema)



Olha esse trecho. Aposto que tem um igualzinho no seu projeto agora:




CODE
$pedidos = Pedido::all(); // 1 query pra buscar os pedidos

foreach ($pedidos as $pedido) {
// e aqui... +1 query POR pedido, toda vez que você toca no cliente
echo $pedido->cliente->nome;
}






Bonito, limpo, legível. E secretamente fazendo o banco chorar.



Cada vez que o loop acessa $pedido->cliente, o Eloquent dispara uma nova consulta pra buscar aquele cliente. São 50 pedidos? 1 query dos pedidos + 50 dos clientes = 51 queries numa tela só.



Agora imagina uma listagem com 500 registros e três relações (cliente, produtos, endereço). O número explode. Já vi tela abrir o Debugbar e mostrar mais de 3.000 queries. Cada uma custa alguns milissegundos de ida e volta ao banco. Some tudo: sua tela de 8 segundos.






Por que "N+1"? O nome entrega o problema



É matemática simples e meio cruel.





  • 1 query pra buscar a lista principal (os N pedidos).


  • N queries extras, uma pra cada item, quando você acessa a relação dentro do loop.



Total: N + 1. Quanto mais dados, pior fica — e o ambiente de dev, com 5 registros de teste, nunca te avisa. O bug só acorda em produção, com dado de verdade. Traiçoeiro.






A solução cabe em uma palavra: with()



Aqui vem o $pedido->restore() dessa história. Uma linha e você vira o herói do dia:




CODE
// Eager loading: já traz os clientes junto, de uma vez
$pedidos = Pedido::with('cliente')->get();

foreach ($pedidos as $pedido) {
echo $pedido->cliente->nome; // já tá na memória, ZERO query nova
}






O que mudou? Em vez de buscar cliente por cliente dentro do loop (lazy loading), o with() faz o Eloquent buscar todos os clientes de uma vez só, com um WHERE IN, antes do loop começar. Isso é eager loading — "carregamento adiantado".



De 51 queries pra 2. Sempre 2, tanto faz se são 50 ou 5.000 pedidos. A tela de 8 segundos vira 200 milissegundos.



Não mexeu no servidor. Não instalou nada. Uma palavra.






Como usar na prática



O with() é mais flexível do que parece:




CODE
// Várias relações de uma vez
Pedido::with(['cliente', 'itens'])->get();

// Relação aninhada: o item e o produto de cada item
Pedido::with('itens.produto')->get();

// Já filtrou a query? Carrega depois, na collection que você já tem
$pedidos = Pedido::all();
$pedidos->load('cliente'); // mesmo efeito, pra collection pronta

// Só quer a CONTAGEM, não os dados? withCount é seu amigo
Pedido::withCount('itens')->get(); // vira a coluna itens_count






with() você usa na query. load() quando a collection já foi buscada. withCount() quando só precisa do número, sem carregar os registros.






A pegadinha: eager loading não é "coloca em tudo"



Antes de sair jogando with() em toda query, cuidado com o outro extremo.



Se você carrega uma relação que não vai usar naquela tela, tá trazendo dados à toa — gastando memória e banda pra nada. O with('itens.produto.fornecedor.endereco') que ninguém lê é tão ruim quanto o N+1.



A régua é simples: carregue o que você vai acessar no loop. Nada além disso.



E tem a confusão clássica: with() não é a mesma coisa que has() ou whereHas(). O with() traz a relação junto. O whereHas() filtra pela existência dela. Um carrega, o outro filtra. Já vi muita gente usar um esperando o comportamento do outro.






Bônus: faça o Laravel gritar quando você esquecer



O melhor jeito de nunca mais deixar um N+1 passar é pedir pro próprio Laravel te avisar. No AppServiceProvider:




CODE
use Illuminate\Database\Eloquent\Model;

public function boot(): void
{
// Em dev, estoura exceção sempre que uma relação
// for carregada de forma lazy (o gatilho do N+1)
Model::preventLazyLoading(! app()->isProduction());
}






Agora, se você esquecer um with(), o Laravel lança uma exceção na sua cara em desenvolvimento — muito antes de virar tela travada em produção. Deixa ligado só fora de produção pra não derrubar o app do cliente por um esquecimento.






Antes de você fechar a aba



O N+1 é aquele bug que a gente escreve sem perceber e só descobre quando alguém reclama. A boa notícia: achar e matar é fácil quando você sabe o que procurar.



Abre o Laravel Debugbar (ou o Telescope) numa tela lenta do seu projeto e olha a contagem de queries. Achou uma listagem com dezenas ou centenas? É N+1 quase na certa. Um with() e você resolve.



Me conta nos comentários: qual foi a tela mais absurda de queries que você já pegou? Aposto que tem gente com número maior que 3.000. 👀

Vollständiger Original-Bericht
Ausführliche Details, Code-Beispiele & Hersteller-Stellungnahme auf dev.to.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Hackers Just Poisoned the Rust Supply Chain | Threat Wire
1 Quelle
Hackers Found a Way Into Humanoid Robots | Threat Wire
1 Quelle
Bits und so #1021 (Passwort für Laufwerk)