Eager Loading

Efficiently load related data in a single query to avoid N+1 problems.

The N+1 Problem

Without eager loading, fetching related data requires multiple queries:

n-plus-one.ts
// Bad: N+1 queries
const users = await db.query(cook`main:users slay:*`);  // 1 query

for (const user of users) {
  // N additional queries!
  user.posts = await db.query(cook`main:posts slay:* sus:user_id=${user.id}`);
}

// Good: Single query with eager loading
const users = await db.query(cook`main:users slay:* fam:posts`);  // 1-2 queries total

Basic Eager Loading

basic.ts
// Load single relation
const users = await db.query(
  cook`main:users slay:* fam:profile`
);

// Load multiple relations
const users = await db.query(
  cook`main:users slay:* fam:profile,posts`
);

Nested Eager Loading

nested.ts
// Load nested relations with dot notation
const users = await db.query(
  cook`main:users slay:* fam:posts.comments`
);
// Result: users → posts → comments

// Multiple levels deep
const users = await db.query(
  cook`main:users slay:* fam:posts.comments.author`
);
// Result: users → posts → comments → author

Constrained Eager Loading

constrained.ts
// Filter related records
const users = await db.query(
  cook`main:users slay:* fam:posts(sus:published=true)`
);
// Only loads published posts

// Order related records
const users = await db.query(
  cook`main:users slay:* fam:posts(vibe:created_at/desc)`
);
// Posts ordered by date

// Limit related records
const users = await db.query(
  cook`main:users slay:* fam:posts(bet:5 vibe:created_at/desc)`
);
// Only latest 5 posts per user

Select Specific Columns

select-columns.ts
// Select only needed columns from relations
const users = await db.query(
  cook`main:users slay:id,name fam:posts(slay:id,title)`
);
// { id: 1, name: "John", posts: [{ id: 1, title: "Hello" }] }

Loading Strategies

Subquery (Default)

Uses separate queries for each relation. Best for hasMany relations to avoid row multiplication.

Join

Uses SQL JOINs. More efficient for hasOne/belongsTo but can cause row duplication with hasMany.

strategies.ts
// Force join strategy
const users = await db.query(
  cook`main:users slay:* fam:profile/join`
);

// Force subquery strategy
const users = await db.query(
  cook`main:users slay:* fam:posts/subquery`
);

Performance Tip

Only eager load what you need. Loading unnecessary relations wastes database resources and memory. Use constrained loading to limit data.