Course contentsShow
← Node.js
Lesson 618 of 1,9807. Web Framework Architecture and MiddlewareFree lesson

Context Encapsulation Patterns

Implement a shared state object that persists data across various stages of the request lifecycle.

In this lesson, you will learn how to create a shared "context" object that travels with a request as it moves through your middleware chain, allowing you to pass data between stages without cluttering the global scope.

The Concept of Shared Context

When building robust web applications, you often perform tasks that need to share information. For example, a "User Auth" middleware might verify a token, and you need that user’s ID to be available later in your database query logic.

In a standard Node.js server, you can attach custom properties directly to the request object. Because the same req object is passed into every function in your middleware chain, it acts as a container for your request's lifecycle state. This is what we call Context Encapsulation.

Implementing the Pattern

Instead of creating global variables—which would lead to race conditions when multiple users hit your server at once—we encapsulate the state within the specific req object for that request.

// Middleware 1: Identify the user
function authenticate(req, res, next) {
  const userId = verifyToken(req.headers.authorization);
  
  // Encapsulate the data into the request object
  req.context = { userId }; 
  next();
}

// Middleware 2: Log the user activity
function logger(req, res, next) {
  // Access the encapsulated data
  console.log(`Processing request for user: ${req.context.userId}`);
  next();
}

By creating a specific property (like req.context or req.locals), you keep the request's state organized. This ensures that every piece of logic in your pipeline knows exactly where to look for shared data, and because the data is local to that specific req object, it remains isolated from concurrent requests occurring at the same time. This is a clean, modular way to build "stages" in your request-response lifecycle.

Key Takeaway: Use the request object as a container for shared state to cleanly pass information across middleware stages without risking data collision between concurrent requests.