Managing Model Instance Identity
In this lesson, you will learn how to maintain a single "source of truth" for your database records within a single request by caching model instances.
The Problem: Fragmented State
When building complex Node.js applications, you often fetch the same database record multiple times across different services, middleware, or helper functions during a single request. If you perform these fetches independently, your ORM might create two distinct JavaScript objects representing the exact same row in your database.
If you update one object but not the other, your application enters an inconsistent state. For example, if you change a user's email in one service, a different service holding an older instance of that same user might continue processing outdated data.
The Solution: Identity Maps
To solve this, we use an "Identity Map" pattern. The goal is to ensure that for any given database row (usually identified by a primary key like id), the application only ever holds one instance in memory for the duration of the request.
You can implement this by creating a simple Map object attached to your request context (often via an async_hooks store or a request-scoped container). Before querying the database, check the map:
// A simplified conceptual example
async function getUserById(id, context) {
// 1. Check if we already have this instance in our cache
if (context.identityMap.has(id)) {
return context.identityMap.get(id);
}
// 2. Fetch from DB if not present
const user = await db.users.findByPk(id);
// 3. Store in the identity map for future reference
context.identityMap.set(id, user);
return user;
}
By doing this, every part of your code that calls getUserById for a specific ID will receive the exact same object reference. If you modify user.email, that change is immediately reflected everywhere else in the request, preventing bugs caused by stale, duplicated model instances.
Key Takeaway: By using an identity map to cache model instances within a request context, you ensure that multiple lookups for the same record return the same object reference, maintaining data consistency throughout your application logic.