2 min. de lectura (aproximado)

Lazy loading vs eager loading en Laravel

(2 min. de lectura) En Laravel, cuando se trabaja con relaciones entre modelos (hasMany, belongsTo, etc.), Eloquent ofrece dos formas principales de cargar los datos relacionados: Lazy Loading (carga perezosa) y Eager Loading (carga ansiosa o precarga). La diferencia principal está en cuándo y cómo se ejecutan las consultas a la base de datos. Una mala elección puede causar el famoso problema N+1.
  • Lazy Loading: Es el comportamiento por defecto y es lo que pasa cuando se accede a una relación como si fuera una propiedad normal:

    // Modelo Post tiene relación comments() hasMany
    $posts = Post::all();  // 1 sola consulta
    
    foreach ($posts as $post) {
    echo $post->comments->count();  // ← Aquí se dispara una consulta POR CADA post
    }
    
    Se produce 1 consulta para obtener los posts y por cada post una consulta por cada post cuando se accede a "$post->comments". Resultado: Si se obtienen 100 posts → 101 consultas (1 + 100) → Problema N+1.

    Ventajas: Es simple y automático. No se cargan datos que quizás no se usen y es ideal para 1 solo registro o cuando no se se sabe si se va a necesitar la relación.

    Desventajas: Muy fácil caer en N+1 en listas, loops, vistas con foreach y Mal rendimiento con muchos registros.

  • Eager Loading: Se cargan las relaciones de una vez junto con el modelo principal, usando "with()":

    // Carga posts + todos sus comments en solo 2 consultas
    $posts = Post::with('comments')->get();
    
    // O con varias relaciones
    $posts = Post::with(['comments', 'author', 'tags'])->get();
    
    foreach ($posts as $post) {
    echo $post->comments->count();  // ← ¡No dispara consultas nuevas!
    }
    
    Se produce 1 consulta para posts y 1 consulta para todos los comments de esos posts (usa WHERE IN). Total: 2 consultas aunque haya 1000 posts.

    Ventajas: Elimina (casi siempre) el problema N+1. Es mucho más rápido en listas y vistas y se tiene Control total sobre qué relaciones cargar.

    Desventajas: Si se cargan relaciones que no se usan → desperdicio de memoria y tiempo y saber de antemano qué se va a necesitar.

Tabla resumen

Aspecto Lazy Loading Eager Loading
Cuándo se carga Solo al acceder (on-demand) Al inicio, junto con el modelo principal
Número de consultas 1 + N (N = número de registros) Generalmente 1 o pocas (independiente de N)
Problema N+1 Sí, muy común No (lo previene)
Sintaxis principal $model->relacion Model::with('relacion')->get()
Mejor para 1 registro o relaciones opcionales Listas, loops, vistas con datos relacionados
Rendimiento Malo en colecciones grandes Excelente en colecciones grandes
Por defecto en Eloquent Sí No (hay que indicarlo)