In this lesson, you will learn how to design your observability pipeline to segment telemetry data by tenant, ensuring you can isolate performance issues to a specific client rather than the entire infrastructure.
The Challenge of Multi-tenancy
In a multi-tenant Node.js application, multiple clients share the same compute resources, databases, and event loops. If your monitoring tools only show aggregate metrics, you might see a "spike in CPU usage" without knowing which client is triggering the load. To resolve this, you must decorate every log, trace, and metric with a tenant_id.
Contextualizing Telemetry
The most effective way to implement this in Node.js is through AsyncLocalStorage. This allows you to store the tenant_id at the start of a request and have it automatically available to every service, utility, or database driver within that request’s execution chain.
When you emit a log or a metric, you pull the ID from the store and inject it as a dimension or attribute:
const { AsyncLocalStorage } = require('node:async_hooks');
const tenantStorage = new AsyncLocalStorage();
// Middleware to set the context
app.use((req, res, next) => {
const tenantId = req.headers['x-tenant-id'];
tenantStorage.run({ tenantId }, () => next());
});
// Inside your business logic
function processRequest() {
const { tenantId } = tenantStorage.getStore();
// Custom metric with tenant dimension
metrics.increment('api.request.count', { tenant_id: tenantId });
logger.info('Processing request', { tenantId });
}
Leveraging Dimensions
Once your telemetry is tagged, your observability platform becomes significantly more powerful. You are no longer looking at global averages; you can now generate a dashboard showing "P99 Latency per Tenant."
This level of visibility allows you to distinguish between a global platform degradation and a "noisy neighbor" incident where one specific client is overwhelming the system with complex queries. By tagging data at the source, you move from reactive troubleshooting to proactive capacity management for your highest-value clients.
Key Takeaway: Injecting a tenant_id into your telemetry via AsyncLocalStorage is essential for isolating performance bottlenecks and ensuring fair resource allocation in shared Node.js environments.