Understanding Eager and Lazy Loading in Sequelize

Understanding the Problem

We need to implement two different approaches for loading associated data in Sequelize: eager loading and lazy loading. Our database has Bands and Musicians in a one-to-many relationship, where we need to:

The database schema shows:

Devising a Plan

  1. Understand the existing endpoint implementations for single band queries
  2. Implement lazy loading for all bands by using getMusicians() for each band
  3. Implement eager loading for all bands using include and proper ordering
  4. Compare both approaches in terms of query count and performance

Step by Step Solution

Step 1: Understanding Lazy vs Eager Loading

Let's look at the existing implementations for single band queries:

Lazy Loading Example:

// Lazy loading makes separate queries as needed
app.get('/bands-lazy/:id', async (req, res, next) => {
    // First query - get the band
    const band = await Band.findByPk(req.params.id);
    
    // Second query - get the musicians
    const bandMembers = await band.getMusicians({ 
        order: [ ['firstName'] ] 
    });
    
    const payload = {
        id: band.id,
        name: band.name,
        createdAt: band.createdAt,
        updatedAt: band.updatedAt,
        Musicians: bandMembers
    }
    res.json(payload);
});

Eager Loading Example:

// Eager loading gets everything in one query
app.get('/bands-eager/:id', async (req, res, next) => {
    const payload = await Band.findByPk(req.params.id, {
        include: { model: Musician },
        order: [ [Musician, 'firstName'] ]
    });
    res.json(payload);
});

Step 2: Implementing All Bands Lazy Loading

Here's how we implement lazy loading for all bands:

app.get('/bands-lazy', async (req, res, next) => {
    // Get all bands first
    const allBands = await Band.findAll({ 
        order: [ ['name'] ] 
    });
    
    const payload = [];
    for(let i = 0; i < allBands.length; i++) {
        const band = allBands[i];
        // Get musicians for each band separately
        const musicians = await band.getMusicians({
            order: [['firstName']]
        });
        
        const bandData = {
            id: band.id,
            name: band.name,
            createdAt: band.createdAt,
            updatedAt: band.updatedAt,
            Musicians: musicians
        };
        payload.push(bandData);
    }
    res.json(payload);
});

Step 3: Implementing All Bands Eager Loading

Here's the eager loading implementation:

app.get('/bands-eager', async (req, res, next) => {
    const payload = await Band.findAll({
        include: { model: Musician },
        order: [
            ['name'],
            [Musician, 'firstName']
        ]
    });
    res.json(payload);
});

Understanding the Solutions

Real World Analogy

Think of lazy loading vs eager loading like shopping at a grocery store:

Performance Implications

Let's compare both approaches:

Lazy Loading:

Eager Loading:

Further Learning

To deepen your understanding, try these exercises:

  1. Add error handling to both approaches
  2. Implement pagination with both loading strategies
  3. Add the instruments relationship to see how nested associations work
  4. Create a hybrid approach where you eager load some relationships and lazy load others

Common Pitfalls

Watch out for these common issues: