Client options
JavaScript options are camelCase constructor fields; Python options are snake_case keyword arguments. Defaults are identical everywhere.
Platform-specific options —
autoFlush on the browser SDK, flushOnExit on the Node SDK — are documented on their SDK pages.
Batching
Messages queue in memory and are sent as JSON toPOST /api/v1/ingest with the write key as a bearer token. A single queued message is sent as a bare object; multiple messages are wrapped in { "batch": [...] }. Batches are capped at 100 messages — a larger queue drains in successive requests.
Each message includes an SDK-generated UUID in messageId. The value stays the same across retries, allowing the server to deduplicate a repeated delivery.
Timestamps
Without atimestamp, the SDK uses the call time in UTC with millisecond precision (2026-06-05T00:00:00.000Z). A JavaScript Date or Python datetime is serialized in the same format. Strings and numbers (epoch milliseconds) pass through unchanged for historical imports.
Validation
SDK methods validate input before queueing and throwTypeError for:
userId,event, andgroupIdmust be non-empty strings of at most 256 characters.profiletraits must include a non-emptyemail.pagenames, when provided, follow the same rules.
null, arrays, and nested objects. Do not send functions, undefined, BigInt, class instances, or circular references. The complete method shapes are listed in Message model.
Retries
A delivery attempt that fails with a retryable status —408, 429, 500, 502, 503, 504 — or a network error is retried up to maxRetries times with exponential backoff: 500 ms base, doubling per attempt, capped at 30 s, with jitter. A Retry-After header on a retryable response is honored.
Non-retryable statuses (for example 401 from a revoked write key, or 422 from an invalid payload) fail immediately without retrying.
The server responds after the transaction commits. If a request times out after committing, a retry sends the same messageId and the server deduplicates it.
Rate limits
Each write key has an ingest budget of 600 messages per 60-second sliding window by default; some plans have a higher limit. The budget counts messages, not requests. A429 response includes Retry-After and is retryable. If maxRetries is exhausted, the SDK returns the batch to the queue for the next flush. Pace sustained sends such as backfills below the limit.
Error handling
When a batch exhausts its retries or encounters a non-retryable failure, the error callback receives the error, affected messages, and delivery context:- Retryable (server errors, timeouts, network failures) — the batch goes back on the queue and is attempted again on the next flush. Nothing is lost while the process lives.
- Non-retryable (auth or validation failures) — the batch is dropped after
onErroris called. The callback is your only chance to log or persist it.
track/profile/group/page. Input validation and serialization errors are programming errors and may still throw at the call site or during an explicit flush.