In this lesson, you will learn how to avoid performance bottlenecks when performing database operations inside loops by batching your relationship data.
When working with ORMs, it is common to iterate over a collection of records and perform an action for each one. However, if that action involves querying a related model or saving a new record for every iteration, you introduce the "N+1 performance trap." Every single loop iteration sends a separate query to your database, causing massive latency as your dataset grows.
The Problem: Sequential Database Requests
Imagine you have a list of Users and you want to create a Profile for each one. A naive approach looks like this:
for (const user of users) {
// This triggers a database round-trip for every user
await Profile.create({ userId: user.id, bio: 'Hello!' });
}
If you have 1,000 users, your application makes 1,000 individual network requests to the database. This is slow and puts unnecessary stress on your connection pool.
The Solution: Bulk Operations
Instead of performing operations one-by-one inside a loop, you should collect your data and execute a single "bulk" command. Most ORMs provide a way to pass an array of objects to a creation or update method, which the database engine handles in one efficient transaction.
// Prepare the array of data first
const profiles = users.map(user => ({
userId: user.id,
bio: 'Hello!'
}));
// Perform one single database operation
await Profile.bulkCreate(profiles);
By decoupling the data preparation from the database persistence, you shift from having network requests to just one. If you need to fetch related data inside a loop, do not use find methods inside the forEach. Instead, use the Eager Loading techniques you learned previously to bring all necessary associations into memory before you start your loop. If you must process data, perform your calculations or transformations on the loaded objects in memory, then perform a single update or insert command at the end.
Key Takeaway: Never execute database queries inside a loop; instead, collect your data in memory and perform a single bulk operation to keep your application fast and scalable.