SDK configuration reference

Every ApiTraffic Node SDK option and environment variable, its default and effect, how code, environment and account settings combine, and the per-request APIs.

This page as Markdown

This page lists every setting the ApiTraffic Node SDK reads, with its type, default and effect, and the functions you can call from your request-handling code. It applies to @apitraffic/node and to the per-framework packages (@apitraffic/express, @apitraffic/fastify, @apitraffic/koa, @apitraffic/hapi), which accept the same options. The Strapi plugin takes them through its plugin configuration; see Strapi.

Most applications need only two values, API_TRAFFIC_TOKEN and API_TRAFFIC_BUCKET. Everything that decides what is captured, redacted or blocked is set in your ApiTraffic account and delivered to the SDK, not configured here.

Where settings come from

The SDK combines three sources:

  1. Options you pass in code, to apitraffic.express({...}), apitraffic.fastify({...}) and the other framework calls.
  2. API_TRAFFIC_* environment variables, read when the SDK starts.
  3. Settings delivered from your ApiTraffic account: redaction rules, exclusions, the firewall policy, APM capture switches and host telemetry. The SDK loads them on startup and receives changes in real time, without a restart.

Precedence

For every option in the tables below: an option passed in code wins over its environment variable, which wins over the built-in default. You can mix the two, for example the token from the environment and debug in code.

A few settings follow a different rule, and each is called out in its table:

Setting Rule
offlineWafMode The environment variable API_TRAFFIC_OFFLINE_WAF_MODE wins over the code option, so you can change it during an incident without a deploy.
Firewall on or off Off if either waf: false is passed or API_TRAFFIC_WAF_ENABLED=false is set. Neither can turn on a firewall your account has not enabled.
captureStatementParams, captureRedisKeys On if either your code or environment turns it on, or the bucket’s APM Capture settings do. The dashboard can add capture, never remove what your code asked for.
captureCallSite, captureStackDepth The bucket’s APM Capture setting applies, unless you set the option in code or the environment, which then wins.
interceptOutbound A blank value ("" or null, or an empty environment variable) turns outbound capture off. For every other option, a blank value counts as not set.

How values are parsed

Options that switch something on or off, and numeric limits, accept strings as well as booleans and numbers, so { captureSpans: process.env.CAPTURE_SPANS } works:

  • Switches accept true/false, yes/no, on/off or 1/0, in any case.
  • Byte caps and counts must be whole numbers greater than 0. captureStackDepth may be 0.
  • Sample rates are numbers from 0 to 1.
  • A blank value ("", spaces, or null) counts as not provided, so the environment variable, then the default, applies. A blank never means 0 or off (except for interceptOutbound).
  • An invalid value ("abc", -5, 1.5 for a rate) is reported once on the console and ignored, and the next source applies.

Warning: debug and strict are not parsed from strings in code: pass true or false. API_TRAFFIC_DEBUG turns debug logging on only when it is exactly true (any case); 1 or yes do not.

Credentials and connection

Option Environment variable Type Default Effect
token API_TRAFFIC_TOKEN string - Required. Your ingest token. Without it the SDK logs an error and disables telemetry for the process; your app still starts.
bucket API_TRAFFIC_BUCKET string - Required. The ID of the bucket captured traffic is sent to: seven lowercase letters and digits, such as k3m9p2x. The setup page and Bucket Settings show it.
accountSid API_TRAFFIC_ACCOUNT_SID string Learned from your account settings Only needed by a process that mints embed tokens without running the ApiTraffic middleware.
- API_TRAFFIC_EMBED_TOKEN string - An Administrator API token that embedToken() mints embed tokens with. The ingest token in API_TRAFFIC_TOKEN can’t mint them. A token passed to embedToken() takes precedence. It is a read credential to your captured traffic: set it only on servers that mint embed tokens, and keep it secret.
apiHost API_TRAFFIC_API_HOST string api.apitraffic.io Host the SDK loads its settings from. A bare host name means https://.
ingestHost API_TRAFFIC_INGEST_HOST string ingest.apitraffic.io Host captured traffic is sent to. A bare host name means https://.
debug API_TRAFFIC_DEBUG boolean false Log SDK activity to the console. Useful while installing; leave it off in production.
strict - boolean false Throw at startup on misconfiguration (missing token or bucket) instead of logging and disabling telemetry. For apps that would rather not start than run unmonitored.

The SDK warns once if apiHost or ingestHost is plain http:// and not this machine, because the token and captured requests would cross the network unencrypted.

Proxies. Delivery to ApiTraffic honors the standard HTTPS_PROXY, HTTP_PROXY, ALL_PROXY and NO_PROXY environment variables (in upper or lower case).

Capture

Option Environment variable Type Default Effect
interceptOutbound API_TRAFFIC_INTERCEPT_OUTBOUND switch true Capture outbound calls made with http, https and fetch. Off leaves those modules untouched. See Outbound requests.
captureFetch API_TRAFFIC_CAPTURE_FETCH switch true Capture outbound global fetch calls (requires interceptOutbound). Off affects telemetry only: an egress firewall policy still applies to fetch.
redactSensitiveKeys API_TRAFFIC_REDACT_SENSITIVE_KEYS switch true Mask credential-shaped body keys and query parameters (password, token, secret, api_key and similar) in addition to your redaction rules. Credential headers are always masked.
maxBodyBytes API_TRAFFIC_MAX_BODY_BYTES bytes 524288 (512 KB) Largest request or response body sent to ApiTraffic. A larger body is replaced by a placeholder. Applied after redaction.
maxRedactBodyBytes API_TRAFFIC_MAX_REDACT_BODY_BYTES bytes 1048576 (1 MB) Largest body the SDK redacts. A larger body is replaced by a placeholder before any redaction work, so redaction cost stays bounded.
maxFetchBodyLength API_TRAFFIC_MAX_FETCH_BODY_LENGTH bytes 524288 (512 KB) Largest outbound request or response body captured, for http, https and fetch calls.
requestSampleRate API_TRAFFIC_REQUEST_SAMPLE_RATE rate 1 Fraction of captured requests sent. Requests with a 5xx response status are always sent, so 0 (only when given as 0 or "0") sends server errors only.

Bodies that cannot be captured safely - nested more than 256 levels deep, unreadable, or not processable by your redaction rules - are replaced with a [body not captured: …] placeholder and the rest of the request is still sent. A request whose redaction cannot be completed at all is dropped, never sent unredacted.

Delivery

Option Environment variable Type Default Effect
ingestBatch API_TRAFFIC_INGEST_BATCH switch true Send several payloads per request to ApiTraffic when your account and the ingest host both support it. false sends one request per payload.
ingestGzip API_TRAFFIC_INGEST_GZIP switch true Compress those batches when your account asks for it.

Delivery limits (timeouts, queue size, circuit breaker) are fixed; they are described in If ApiTraffic is unreachable.

Spans and APM

These options control the spans recorded inside each request: database, cache, queue and outbound work from the APM bridge, and your own spans from span() and startSpan(). Set them on the framework call or with their environment variables.

Option Environment variable Type Default Effect
captureSpans API_TRAFFIC_CAPTURE_SPANS switch true Master switch for spans and per-request span rollups.
captureStatements API_TRAFFIC_CAPTURE_STATEMENTS switch true Include the normalized SQL or command text (where id = ?) in spans.
captureStatementParams API_TRAFFIC_CAPTURE_STATEMENT_PARAMS switch false Also keep statements as issued, with their bind values. These carry your users’ data. Combines with the bucket’s Query Parameters setting: either one turns it on.
captureRedisKeys API_TRAFFIC_CAPTURE_REDIS_KEYS switch false Include the concrete Redis key, unmasked and not run through redaction rules. Combines with the bucket’s Redis Keys setting: either one turns it on.
captureCallSite API_TRAFFIC_CAPTURE_CALL_SITE switch true (bucket setting) Record the application code location (file:line) that started each span. Unset follows the bucket’s Code Location setting; set, it wins.
captureStackDepth API_TRAFFIC_CAPTURE_STACK_DEPTH whole number, 0 or more 10 (bucket setting) Application frames kept per span; 1 keeps the call site alone. Unset follows the bucket.
projectRoot API_TRAFFIC_PROJECT_ROOT string Detected Directory code locations are reported relative to. Detected from your workspace file, .git or package.json; set it when a bundled or serverless build has removed those.
redisKeyPatterns - array of strings or RegExps [] Patterns for Redis keys whose variable parts the automatic masking cannot infer.
maxSpansPerRequest API_TRAFFIC_MAX_SPANS_PER_REQUEST count 500 Spans kept per request. Work past the cap is still counted in the request’s rollups.
spanSampleRate API_TRAFFIC_SPAN_SAMPLE_RATE rate 1 Fraction of requests that keep full span detail. Rollups are computed for every request.
maxSpanMetaBytes API_TRAFFIC_MAX_SPAN_META_BYTES bytes 2048 Size cap on each span’s metadata, after redaction.
sendStatementTextOnce API_TRAFFIC_SEND_STATEMENT_TEXT_ONCE switch false Send each query’s statement text and call stack once per process per resend window, instead of on every span, to reduce payload size.
statementTextResendSeconds API_TRAFFIC_STATEMENT_TEXT_RESEND_SECONDS count 3600 How long text already sent is left off before it is sent again.
statementTextCacheSize API_TRAFFIC_STATEMENT_TEXT_CACHE_SIZE count 5000 Queries remembered per process for sendStatementTextOnce.

Options for the APM preload

register() (and node -r @apitraffic/node/register, which calls it) takes its own options, from the call or from these environment variables. The switches above that it shares (captureSpans, captureStatements, captureStatementParams, captureRedisKeys, captureCallSite, captureStackDepth, maxSpanMetaBytes, debug) read the same variables.

Option Environment variable Type Default Effect
enabledInstrumentations API_TRAFFIC_ENABLED_INSTRUMENTATIONS list [] Instrumentations to turn on beyond the default set, by full name (@opentelemetry/instrumentation-graphql) or short name (graphql). Comma-separated in the variable.
disabledInstrumentations API_TRAFFIC_DISABLED_INSTRUMENTATIONS list [] Instrumentations to turn off. Wins over everything else.
instrumentHttp API_TRAFFIC_INSTRUMENT_HTTP switch false Enable OpenTelemetry’s http/https client instrumentation. Off because the SDK already records those calls with bodies.
synthesizeOutboundRecords API_TRAFFIC_SYNTHESIZE_OUTBOUND_RECORDS switch true Record outbound calls the SDK cannot see itself, such as undici.request used directly, from their spans (metadata only).
flushTimeoutMs API_TRAFFIC_APM_FLUSH_TIMEOUT_MS milliseconds 5000 Longest the span processor’s flush or shutdown waits for queued payloads to be delivered.
serviceName API_TRAFFIC_SERVICE_NAME string - Service name reported to OpenTelemetry.
force API_TRAFFIC_APM_FORCE switch false Start even though Datadog or New Relic appears to be active. Never overrides OTEL_SDK_DISABLED or an OpenTelemetry provider already registered.

What the default instrumentation set covers, and how to use APM with an OpenTelemetry setup of your own, is in Set up APM.

Firewall options

With @apitraffic/node the firewall is always mounted and runs once your account has a live policy. These local controls exist mainly as overrides and kill switches.

Option Environment variable Type Default Effect
waf (@apitraffic/node only) API_TRAFFIC_WAF_ENABLED false or an object Unset false, or the variable set to false, 0 or off, keeps the firewall off whatever your account says. An object passes the options below to the firewall without changing whether it runs. true means the same as unset.
waf.enabled API_TRAFFIC_WAF_ENABLED boolean true With @apitraffic/waf used directly: the master kill switch.
waf.offlineWafMode API_TRAFFIC_OFFLINE_WAF_MODE 'inherit', 'open' or 'closed' 'inherit' What a server that has never loaded a policy does. inherit and open allow traffic; closed answers every request with 503 until a policy loads. The variable wins over the option.
waf.onEvent - function - Called for every inbound block or detection.
waf.onEgressEvent - function - Called for every outbound block or detection.
waf.debug API_TRAFFIC_DEBUG boolean false Log firewall decisions to the console.
javascript
app.use(apitraffic.express({
  waf: {
    onEvent: (event) => logger.warn({ waf: event }, 'firewall event')
  }
}));

Warning: offlineWafMode: 'closed' is the only setting with which an ApiTraffic outage can stop your application serving traffic: a server that starts while ApiTraffic is unreachable, with no cached or pinned copy of your policy, refuses every request. If you use it, commit offline definitions. See If ApiTraffic is unreachable.

Offline definitions

Environment variable Default Effect
API_TRAFFIC_DEFINITIONS_PATH Unset Path of the pinned definitions file. When set, it is the only place the SDK and the CLI look.
API_TRAFFIC_CACHE_DIR node_modules/.cache/apitraffic Where the SDK keeps its last-known-good copy of your settings.
API_TRAFFIC_FALLBACK_MAX_AGE_DAYS Unset (no limit) Skip a pinned file older than this many days.

See Offline definitions.

Server labels

These variables label each server on the Servers page and on the requests it serves. The SDK checks each list in order and uses the first variable that is set, so common platform variables work without extra setup.

Label Variables, in order
Service API_TRAFFIC_SERVICE_NAME, SERVICE_NAME, K_SERVICE, FLY_APP_NAME
Service version API_TRAFFIC_SERVICE_VERSION, SERVICE_VERSION, APP_VERSION
Region API_TRAFFIC_REGION, AWS_REGION, AWS_DEFAULT_REGION, FLY_REGION, GOOGLE_CLOUD_REGION
Commit API_TRAFFIC_GIT_SHA, GIT_SHA, GIT_COMMIT, SOURCE_VERSION, VERCEL_GIT_COMMIT_SHA, HEROKU_SLUG_COMMIT

A service version must be at most 64 characters of letters, digits, ., _, + and -; a commit must be 7 to 40 hexadecimal characters. Other values are ignored.

Settings from your ApiTraffic account

These are configured in ApiTraffic and reach every connected server within seconds of a change. None of them needs a restart or a deploy.

Setting Where you change it How it combines with local settings
Redaction rules Account → Redactions Applied in your process before anything is sent, in addition to the built-in masking. Requests are held until the rules have loaded.
Exclusions Account → Exclusions Matching requests are not sent.
Firewall policy Account → Firewall (WAF), on plans that include it waf: false or API_TRAFFIC_WAF_ENABLED=false keeps it off locally.
APM capture Bucket Settings → APM Capture Query Parameters and Redis Keys add to local settings and can switch off automatically under Auto-Disable. Code Location applies unless set locally.
Host telemetry Bucket Settings → Host Telemetry Server-side only. Your plan sets the fastest reporting interval.

Per-request APIs

Call these from code that runs while a request is being handled: route handlers, middleware after ApiTraffic, and anything they call, including across await. Each one attaches to the request in progress. Outside a request they do nothing, and none of them ever throws into your code.

They are exported by @apitraffic/node and by each framework package. Import them from the package you installed:

javascript
const apitraffic = require('@apitraffic/node');   // or '@apitraffic/express', and so on

Tag a request

tag(key, value) attaches a searchable key-value pair, for example a customer or tenant ID, so you can find every request for that customer in the request log.

javascript
apitraffic.tag('customerId', String(req.user.id));
apitraffic.tag('plan', req.user.plan);
  • key is 1 to 64 characters: a letter first, then letters, digits, _, . or -. Keys starting with waf., redaction., apitraffic. or at. are reserved.
  • value is a string, number or boolean; numbers and booleans are stored as text. Values longer than 255 characters are cut to 255. null or undefined adds no tag.
  • A request holds at most 32 tag keys. Setting an existing key again replaces its value and does not count twice.
  • A tag that breaks a rule is dropped and counted in Settings → Dimensions, never thrown into your handler. See the tag rules.

Trace a code path

trace(message) records a timestamped note on the request, a console log you can read in production:

javascript
apitraffic.trace('cart total exceeded the free-shipping threshold');

Each message is a string of at most 255 characters, and a request keeps at most 250 of them.

Time your own work

span(type, name, fn, meta?) runs fn, times it and records it as a span on the request’s waterfall. It returns exactly what fn returns, works with synchronous functions and promises, and re-throws fn’s error unchanged after marking the span failed. time() is the same function under another name.

javascript
const rates = await apitraffic.span('http.out', 'tax lookup', () => taxClient.rates(cart), {
  host: 'api.acme-tax.example'
});

startSpan(type, name, meta?) is for work that does not fit one function. It returns a handle; call end() once when the work finishes:

javascript
const span = apitraffic.startSpan('queue', 'publish order.created');
try {
  await queue.publish('order.created', order);
  span.end();
} catch (error) {
  span.end({ ok: false, meta: { error: error.code } });
  throw error;
}
  • type is one of db.query, redis, cache, http.out, queue, rpc, graphql or custom.
  • meta is an object of extra detail, redacted and capped at maxSpanMetaBytes. setMeta(meta) on a handle adds to it before end().
  • end({ ok: false }) marks the span failed. Calling end() again does nothing.
  • With captureSpans off, spans are not recorded and the function still runs.

Read the request context

getRequestManager() returns the object holding the current request’s tags, traces and spans, or undefined outside a request. getContext() returns the SDK’s context store for the current request, or undefined outside one. Most applications never need either; prefer tag, trace and span.

Process-level functions

Function Returns Use it to
stats() Delivery counters Check that telemetry is leaving the process: in flight, queued, delivered, recovered, dropped by cause, and whether the circuit breaker is open. @apitraffic/node only; @apitraffic/hapi also exports deliveryStats().
flush({ timeoutMs }) Promise<{ flushed, remaining }> Deliver what has been captured without stopping, for example before a serverless function is frozen. Default timeout 2 seconds.
shutdown({ flushTimeoutMs }) Promise<{ flushed, remaining }> Stop capturing, deliver what is queued, and release the realtime connection, timers and hooks so the process can exit. See Shutting down.
embedToken(options) Promise<{ token, expiresAt, tabs, features }> Mint a token for the embeddable request log. Rejects on failure.
escapeCriteriaValue(value) string Escape a value you put in double quotes inside an embed criteria string. Prefer filters.tags, which escapes for you.
register(options) { registered, reason } Start the APM bridge from code (@apitraffic/node only). Must run before your app loads the libraries it instruments.