Skip to content

3.0.0

Latest

Choose a tag to compare

@cindreta cindreta released this 07 Jul 12:44
0ab1495

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 more node-fetch fallback, 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/hono so 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 the node-fetch dependency entirely and now use Node's built-in fetch (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 ms

Query 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-standard File/Blob are collapsed to a { name, type, size } descriptor - the bytes never leave your server.

  • Binary bodies are redacted. Raw Buffer bodies 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 maskedKeywords was omitted. v3 fixes this - every integration masks the default keywords unless you explicitly pass maskedKeywords: [].
  • URL query strings are masked too. A value like /login?token=abc now 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 exports map 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.