When we talk about observability in Node.js, we usually trace things like:
- HTTP requests
- Database queries
- External API calls
But thereβs a hidden performance layer most tracing setups completely ignore.
π Response compression
Many Express applications use the popular compression middleware to reduce response size and improve latency.
But hereβs the problem.
Nobody traces it.
Why Compression Deserves Tracing
Compression happens after your application logic finishes but before the response is sent to the client.
That means:
HTTP Request
β
βΌ
Express Route
β
βΌ
Application Logic
β
βΌ
Compression (zlib)
β
βΌ
Response Sent
If compression is slow, you may see:
- slower response times
- increased CPU usage
- delayed response delivery
But in most observability setups, this time is invisible.
Your traces might show something like this:
HTTP Request
βββ Route Handler
βββ DB Query
But you never see compression time.
Thatβs exactly the gap I wanted to close.
Introducing Compression Instrumentation
I built a small OpenTelemetry instrumentation package to trace compression operations.
π https://www.npmjs.com/package/@sasikumart/compression-instrumentation
This package instruments Node.js zlib compression calls and exposes them as OpenTelemetry spans.
It allows you to observe:
- compression duration
- compression algorithm used
- impact of compression on request latency
What the Trace Looks Like
Without compression instrumentation:
HTTP GET /users
βββ controller.getUsers
βββ mongodb query
With instrumentation:
HTTP GET /users
βββ controller.getUsers
βββ mongodb query
βββ gzip compression
Now compression becomes a first-class span in your trace.
Installing the Instrumentation
npm install @sasikumart/compression-instrumentation
Basic Setup
Register the instrumentation with OpenTelemetry.
import { NodeSDK } from '@opentelemetry/sdk-node';
import { ZlibInstrumentation } from '@sasikumart/compression-instrumentation';
const sdk = new NodeSDK({
instrumentations: [
new ZlibInstrumentation()
]
});
sdk.start();
Once enabled, any gzip compression performed via Node.js zlib will automatically generate spans.
Example Express Application
Now letβs use Express with the compression middleware.
import express from "express";
import compression from "compression";
const app = express();
app.use(compression());
app.get("/data", (req, res) => {
const payload = Array(1000).fill("OpenTelemetry is awesome");
res.json(payload);
});
app.listen(3000, () => {
console.log("Server running on port 3000");
});
When a request is served, compression will trigger a zlib gzip operation, which will now appear in your traces.
Jaeger Trace Example
Hereβs an example trace captured in Jaeger where the gzip compression span appears alongside the HTTP request span.
The trace typically shows:
- HTTP request span
- route handler span
- gzip compression span generated by the instrumentation
What Gets Captured
Each compression operation becomes its own span, allowing you to observe:
- how long compression takes
- how much latency compression adds to the request
- whether compression becomes a CPU bottleneck
Current Limitation
At the moment, the instrumentation only captures gzip compression.
This is because most Express applications using the compression middleware default to gzip via Node's zlib module.
Future versions may add support for additional algorithms such as:
- deflate
- brotli
Why This Matters
Compression is one of those performance optimizations everyone enables but rarely measures.
Observability should show everything that affects latency, including middleware and runtime operations.
Tracing compression helps you:
- identify CPU bottlenecks
- understand hidden latency in responses
- gain deeper insight into the full request lifecycle
Real Use Cases
- High traffic APIs: Compression CPU overhead can become significant under heavy load.
- Large JSON responses: You can verify whether compression is actually helping reduce payload sizes.
- Performance tuning: You can determine whether compression should happen at the application layer or a reverse proxy.
Final Thoughts
Observability often focuses on business logic, but real latency comes from every layer of the request lifecycle.
Compression is one of those layers that has remained invisible for too long.
Now it doesnβt have to be.
If you're interested in Node.js observability and OpenTelemetry, you might also like my previous deep dive:
π https://dev.to/sasikumart/tracing-the-part-of-mongoose-nobody-talks-about-3gj2
About Me
Iβm a backend developer with extensive experience in designing and optimizing scalable backend systems. My expertise includes tackling complex performance challenges. Iβve led numerous database performance initiatives and have also been deeply involved in system design and revamping existing systems. My focus is on enhancing efficiency, ensuring reliability, and delivering robust solutions that scale effectively.
Feel free to connect with me on LinkedIn to learn more about my professional journey and projects.

Top comments (0)