For the complete documentation index, see llms.txt. This page is also available as Markdown.

Node — @millimetric/track-node

@millimetric/track-node — server-side SDK. Node 18+ / Bun / Deno.

A thin wrapper over POST /v1/track and POST /v1/batch with batching, retries on 5xx, and exponential backoff. Zero dependencies.

Install

npm i @millimetric/track-node

Requires Node 18+ (global fetch). Works in Bun and Deno too.

Quick start

import { init, track, flush } from "@millimetric/track-node";

init({ key: process.env.AOA_SK!, host: "https://api.millimetric.ai" });

// somewhere in a request handler:
track({
  event: "purchase",
  anonymous_id: req.cookies.aid,
  user_id: user.id,
  properties: { amount_cents: 4900, currency: "usd" }
});

// before a serverless function returns:
await flush();

Public API

init(options) → MillimetricClient

You can also construct a client directly without the singleton:

track(event)

Same field shape as the POST /v1/track HTTP body.

flush()

Flushes the queue synchronously. Call this before a serverless function exits — otherwise queued events may be lost when the function is frozen.

Retry behavior

  • 5xx response → retried with exponential backoff (100, 200, 400, 800 ms).

  • Network error → same.

  • 4xx response → thrown immediately, no retry. (The payload is bad; retrying won't help.)

  • After maxRetries attempts, the in-flight batch is re-added to the head of the queue and the error bubbles up from flush().

Batching

flushAt controls how many events to accumulate before sending:

With flushAt > 1, the SDK uses POST /v1/batch. With flushAt = 1 (the default), it uses POST /v1/track directly — no extra latency.

The internal timer is unref()'d so it won't keep a Node process alive on its own. You still need flush() before exit.

Pattern: long-running server

Pattern: serverless (Vercel / Cloudflare / Lambda)

Pattern: background backfill

Last updated

Was this helpful?