Course contentsShow
← Node.js
Lesson 196 of 1,9803. Asynchronous Patterns and Flow ControlFree lesson

Lazy Asynchronous Initialization

You will defer the execution of costly promises until the moment their results are required for a operation.

Lazy Asynchronous Initialization

In this lesson, you will learn how to improve application performance by deferring the execution of expensive asynchronous operations until the precise moment their results are needed.

The Problem: Pre-emptive Cost

In many Node.js applications, we often instantiate connections to databases, cloud storage, or external APIs at the very start of the script. If your application has multiple modules that might not be used in every request, loading them all immediately wastes memory and increases your "time to first byte."

The Solution: The Lazy Promise

Instead of executing an asynchronous task immediately, we store a Promise (or a function that returns one) and wait. We only "kick off" the work when we call await on that promise for the first time.

Consider a database service that is heavy to initialize:

let dbPromise = null;

function getDatabase() {
  // If we haven't started the connection yet, start it now
  if (!dbPromise) {
    dbPromise = connectToDatabaseExpensive(); 
  }
  // If it's already started, we just return the existing promise
  return dbPromise;
}

async function handleRequest() {
  // Only now do we care about the result
  const db = await getDatabase();
  return db.query('SELECT * FROM users');
}

Why This Matters

By using this pattern, your application startup remains lightning-fast. If handleRequest is never called, the connectToDatabaseExpensive function is never invoked, saving your system resources.

Even if multiple parts of your code call getDatabase() simultaneously, they will all receive the same dbPromise. Node.js handles this elegantly: the first caller triggers the operation, and subsequent callers simply wait for the same underlying promise to resolve. This ensures you aren't opening multiple redundant connections while still maintaining the flexibility of waiting until the last possible second.

Key Takeaway: Lazy Asynchronous Initialization saves resources by ensuring expensive operations only trigger when actually required, rather than assuming they are needed at startup.