Treblle Node.js SDK v3.0.0
- Unified core architecture - one payload builder, one transport, one config layer, shared by every framework. Every integration now emits a byte-for-byte identical envelope.
- Native
fetch+ gzip transport - no morenode-fetchfallback, non-blocking fire-and-forget sends, automatic compression, and a hard 5s timeout that can never stall your app. - Fastify support - plus a proper fix for NestJS-on-Fastify, implemented natively through Fastify's lifecycle hooks.
- Query tracking - record the database queries behind each request with
trackQuery(), with automatic SQL sanitization. - Custom metadata - attach searchable key/value tags to any request with
setMetadata(). - Per-framework imports -
treblle/express,treblle/fastify,treblle/koa,treblle/honoso bundlers only pull in what you use. - Safer by default - masking is now on everywhere, uploaded files and binary bodies are redacted automatically, and internal deep imports are locked down.
Performance & reliability
Observability should be invisible to your users. v3 was engineered so the SDK never gets in the way of a response.
- Never blocks the request path. Payloads are built and sent fire-and-forget, after the response is on its way to the client. Nothing your users wait on runs through Treblle.
- Native global
fetch. We dropped thenode-fetchdependency entirely and now use Node's built-infetch(Node 18+). One less dependency, one less thing to keep patched. - Automatic gzip compression. Payloads over 1 KB are gzipped before sending; smaller ones are sent as-is to avoid wasting CPU on compression that wouldn't pay off.
- Hard 5-second timeout. Every send is wrapped in an
AbortController- a slow or hung ingress can never keep your request path or process alive longer than necessary. - Fast size checks. Request/response bodies are measured with an allocation-light estimator that exits early once it crosses the 2 MB cap, instead of serializing the whole body just to check its size.
- Cached at startup. OS, Node version, and timezone lookups are computed once at module load rather than per request.
- Smaller bundles. Per-framework subpath imports mean your bundler only includes the adapter you actually use.
New features
Fastify (and a real NestJS-on-Fastify fix)
Fastify is now a first-class integration, implemented natively through Fastify's onRequest / onSend / onError / onResponse lifecycle hooks - the right way to do it in a framework that has no next() boundary.
const Fastify = require("fastify");
const { useFastifyTreblle } = require("treblle/fastify");
const app = Fastify();
useFastifyTreblle(app, {
sdkToken: "_YOUR_SDK_TOKEN_",
apiKey: "_YOUR_API_KEY_",
});This also fixes NestJS running on the Fastify platform (useNestFastifyTreblle), which previously assumed an Express underneath.
Query tracking
See the database queries behind every request, right alongside it in Treblle. trackQuery() records into the correct request automatically via AsyncLocalStorage - call it from anywhere, including deep inside your data layer.
const { trackQuery } = require("treblle");
trackQuery("SELECT * FROM users WHERE id = ?", 12.4); // sql, time in msQuery strings are sanitized (inline literals stripped) and only the parameterized SQL is ever sent - never the bindings - so sensitive values stay out of your payloads.
Custom metadata
Tag any request with your own key/value pairs for searching and filtering in Treblle - user IDs, plan tiers, feature flags, tenant, region, anything.
const { setMetadata } = require("treblle");
setMetadata("plan", "premium");
setMetadata({ region: "eu", tenant: "acme" });Values are length-limited and capped per request to keep payloads small. Metadata is not masked, so keep secrets out of it.
Smarter body handling
-
Uploaded files are redacted automatically. Files from
multer,formidable,koa-body,@fastify/multipart, and web-standardFile/Blobare collapsed to a{ name, type, size }descriptor - the bytes never leave your server. -
Binary bodies are redacted. Raw
Bufferbodies become a compact descriptor instead of being serialized into a giant byte-index blob. -
Oversized payloads are dropped gracefully. Bodies over 2 MB (which the ingress would strip anyway) are replaced with a small marker noting the real size.
-
Region-specific ingress. Route your data to a specific region with
ingressEndpoint, supported by every framework.useTreblle(app, { sdkToken: "_YOUR_SDK_TOKEN_", apiKey: "_YOUR_API_KEY_", ingressEndpoint: "https://ingress-eu.treblle.com", });
Security & privacy improvements
- Masking is on by default, everywhere. In v2, Koa, Strapi, and Hono accidentally disabled masking when
maskedKeywordswas omitted. v3 fixes this - every integration masks the default keywords unless you explicitly passmaskedKeywords: []. - URL query strings are masked too. A value like
/login?token=abcnow has its sensitive query params masked in the recorded URL, not just in the parsed body. - Default blocked paths always apply and can no longer be accidentally disabled.
- Deep imports locked down. A strict
exportsmap means internal files (e.g.treblle/src/sender) can't be imported - only the root and the documented framework subpaths - so we can evolve internals without breaking you.
Migrating from v2
Most apps upgrade by installing v3, renaming a few options, and confirming data still flows. Full details live in the README migration guide.
1. Cloudflare Workers support removed (breaking).
moduleWorkerTreblle and serviceWorkerTreblle are gone. If you run Treblle in Cloudflare Workers, stay on treblle@2.x for now - a dedicated web-standards edge SDK (Cloudflare Workers, Deno, Fastly, Vercel Edge, Bun) is coming as a separate package.
2. Renamed options (breaking).
| v2 option | v3 option | Notes |
|---|---|---|
additionalFieldsToMask |
maskedKeywords |
Same behavior; [] turns masking off |
blocklistPaths |
blockedPaths |
Same behavior |
endpoint |
ingressEndpoint |
Same behavior |
ignoreDefaultBlockedPaths |
removed | Defaults now always apply |
sdkToken and apiKey keep their names.
3. Node.js >=18 required. v3 relies on the built-in global fetch and drops the node-fetch fallback.
4. Masking-on-by-default fix. If you were relying on the old Koa/Strapi/Hono behavior where masking was off, pass maskedKeywords: [] explicitly.
Install
npm install treblle@^3.0.0// Root import - works for every framework
const { useTreblle } = require("treblle");
// Or the framework subpath - bundles only what you use
const { useTreblle } = require("treblle/express");Supported: Express 4/5 · NestJS 9/10/11 · Koa 2/3 · Hono 4 · Fastify 4/5 · Strapi 4/5 · Node.js 18+
Full documentation: docs.treblle.com · Questions or issues: open an issue
Discover, govern, and secure every API you ship.