# Lazy loading vs eager loading: qual usar em ORM

> Lazy loading e eager loading são estratégias de carregamento de dados em ORM. Lazy loading carrega dados associados sob demanda, reduzindo tráfego inicial, mas pode causar múltiplas consultas. Eager loading trás todos os dados de uma vez, otimizando performance em consultas complexas, mas sobrecarregando a memória. A escolha depende do padrão de acesso e volume de dados.

*Blog Sem Juízo · Novidades · 27 de julho de 2026 · Igor Bastos*

Lazy loading carrega dados sob demanda; eager loading trás tudo de uma vez. A escolha errada gera lentidão ou sobrecarga. Veja critérios práticos para decidir.

## O dilema: carregar tudo agora ou só quando precisar?

Você tem uma entidade Pedido com uma lista de Itens. Se carregar tudo de uma vez (eager loading), pode trazer dados que nunca serão usados. Se carregar sob demanda (lazy loading), arrisca explodir o banco com dezenas de queries em um loop. A escolha entre lazy loading e eager loading é o primeiro passo para não transformar sua aplicação em um carro desgovernado.

A diferença é simples: **lazy loading** adia o carregamento de dados relacionados até o momento em que são acessados (ou seja, só busca quando você toca na propriedade). **Eager loading** resolve todos os relacionamentos em uma única consulta SQL, geralmente com JOINs ou subconsultas. Nenhum é sempre melhor. Ambos têm custos.

## Quantidade de consultas: o custo escondido

O critério mais imediato é o número de queries geradas. Lazy loading é famoso por causar o problema **N+1**: uma consulta para a entidade principal e uma para cada entidade relacionada. Se você lista 100 pedidos e acessa pedido.Itens dentro de um loop, são 101 consultas. Em um ORM como Hibernate ou Entity Framework, isso derruba a performance.

Eager loading resolve isso com um JOIN. Uma única query traz pedidos e itens juntos. O custo é o tráfego de dados: se cada pedido tem 50 itens, você transfere 5.000 linhas mesmo que só precise dos primeiros. O banco também trabalha mais para montar o resultado.

**Quando usar:** Se você sabe que vai acessar todos os relacionamentos, eager loading. Se o acesso é condicional (ex.: só alguns registros), lazy loading com cuidado.

## Memória e tempo de resposta

Eager loading carrega tudo na memória de uma vez. Para uma tela de relatório que precisa de todos os dados, é eficiente. Para uma API que retorna uma lista paginada, pode ser desastre: você carrega 10.000 registros no servidor para devolver apenas 20.

Lazy loading espalha o custo ao longo do tempo. A primeira query é leve, mas cada acesso subsequente adiciona latência. Em uma interface de usuário com múltiplas abas que disparam acessos em paralelo, lazy loading pode travar o servidor com conexões concorrentes.

**Métrica prática:** Se o volume total de dados relacionados é pequeno (menos de 100 registros por entidade), eager loading não pesa. Se é grande e o acesso é esporádico, lazy loading poupa memória.

## Facilidade de implementação e manutenção

Implementar lazy loading é trivial: no ORM, basta marcar a propriedade como virtual (Entity Framework) ou lazy="true" (Hibernate). O ORM cria proxies que interceptam o acesso. O problema é que o desenvolvedor pode não perceber que está disparando queries. Um simples foreach vira um massacre silencioso no banco.

Eager loading exige explicitar os relacionamentos com Include() (Entity Framework) ou JOIN FETCH (Hibernate). É mais código, mas torna o custo visível. Você vê no código quais dados serão carregados. A manutenção é mais fácil porque o comportamento é previsível.

**Ressalva:** Em projetos legados com lazy loading ativado globalmente, é comum encontrar bugs de performance que só aparecem em produção. Desativar lazy loading por padrão e ativar eager loading explicitamente é uma prática recomendada.

## Tabela comparativa

| Critério | Lazy Loading | Eager Loading | |---|---|---| | Número de queries | N+1 (pode ser alto) | 1 (com JOIN) | | Volume de dados | Baixo inicial, cresce sob demanda | Alto de uma vez | | Memória do servidor | Menos, se dados não acessados | Mais, sempre carrega tudo | | Latência | Distribuída (várias viagens) | Concentrada (uma viagem longa) | | Previsibilidade | Baixa (queries escondidas) | Alta (explícito no código) | | Manutenção | Difícil (bugs silenciosos) | Fácil (comportamento claro) |

## Quando usar cada um (cenários reais)

**Use lazy loading quando:**

- O acesso aos dados relacionados é raro ou condicional (ex.: detalhes de um pedido que o usuário clica para expandir).
- A entidade principal tem muitos relacionamentos opcionais e você não sabe quais serão acessados.
- A aplicação é síncrona e o volume de requisições é baixo (ex.: sistema interno com poucos usuários).

**Use eager loading quando:**

- Você sabe que todos os dados relacionados serão usados (ex.: relatório que exibe pedidos com itens e cliente).
- O volume de dados é pequeno o suficiente para caber em uma query sem estourar memória.
- Você está em um loop ou iteração que acessa propriedades relacionadas (evita N+1).

**Cenário misto:** Em APIs REST, geralmente você define explicitamente quais relacionamentos incluir por endpoint. Use eager loading nos endpoints que retornam dados completos e lazy loading (ou sem carregamento) nos que retornam apenas IDs.

## Veredito

Para quem busca **previsibilidade e performance em loops**, escolha **eager loading** e explicite cada Include. Para quem tem **acesso esporádico e volume variável**, escolha **lazy loading** com o ORM configurado para lançar exceção se uma query não intencional for disparada (Entity Framework permite desabilitar lazy loading globalmente e ativar só onde necessário).

Nenhum dos dois é bala de prata. O melhor é desligar lazy loading por padrão, usar eager loading para relacionamentos obrigatórios e, quando precisar de lazy, fazê-lo de forma explícita e controlada.

## Perguntas frequentes

### Qual é o problema N+1?

É quando o ORM executa uma consulta para a entidade principal e mais uma para cada entidade relacionada. Exemplo: 100 pedidos geram 1 query para pedidos + 100 queries para itens = 101 consultas. Eager loading resolve com um único JOIN.

### Lazy loading é sempre ruim?

Não. É útil quando você não sabe se vai acessar os dados relacionados. Por exemplo, uma lista de usuários em que apenas alguns têm perfil completo. O problema é o uso acidental em loops.

### Como evitar queries acidentais com lazy loading?

No Entity Framework, desabilite lazy loading globalmente (context.Configuration.LazyLoadingEnabled = false) e use Include() explicitamente. No Hibernate, configure lazy="false" apenas nas associações que precisam.

### Eager loading sempre melhora a performance?

Depende. Se o JOIN retorna muitas linhas duplicadas (ex.: um pedido com 100 itens), a query pode ser mais lenta que várias queries pequenas. Use Select para projetar apenas os campos necessários.

### Posso misturar lazy e eager no mesmo código?

Sim. Você pode carregar eager um relacionamento e deixar outro lazy. O ORM permite controle por query. Exemplo: context.Pedidos.Include(p => p.Itens) carrega itens, mas deixa cliente em lazy.

### Qual ORM tem melhor suporte a essas estratégias?

Entity Framework e Hibernate oferecem ambas com configurações similares. Entity Framework Core tem lazy loading via pacote NuGet (Microsoft.EntityFrameworkCore.Proxies). Hibernate usa @OneToMany(fetch = FetchType.LAZY).

---

Fonte (canonical): https://blogsemjuizo.com.br/novidades/lazy-loading-vs-eager-loading-qual-usar-em-orm/
