The autoKeepAlive option controls whether the keep-alive timer starts automatically when a trace is created:
New traces (autoKeepAlive defaults to true): the timer starts automatically after the first flush.
Resumed traces (when traceId is set, autoKeepAlive defaults to false): the timer does not start automatically.
This prevents zombie keep-alive timers — for example, when a backend resumes a frontend trace just to append a few events and close it, there’s no need for the backend to keep pinging.
// New trace — keep-alive starts automaticallyconst trace = client.trace({ name: 'UserSession' });// Resumed trace — no keep-alive by defaultconst resumed = client.trace({ traceId: req.headers['x-mirador-trace-id'], name: 'BackendHandler'});// Override the default: force keep-alive on a resumed traceconst resumedWithKeepalive = client.trace({ traceId: req.headers['x-mirador-trace-id'], name: 'LongRunningBackend', autoKeepAlive: true});
You can manually start or stop the keep-alive timer at any time using the startKeepAlive() and stopKeepAlive() methods on the trace. Both methods are idempotent — calling them multiple times is safe.
const trace = client.trace({ name: 'ManualControl', autoKeepAlive: false });// Start keep-alive manually when neededtrace.startKeepAlive();// Stop it when the trace is idletrace.stopKeepAlive();
You can bound the maximum lifetime of a trace independently of keep-alive using the maxTraceLifetimeMs client option. When the lifetime is exceeded, the trace is automatically closed.
const client = new Client('your-api-key', { maxTraceLifetimeMs: 300000 // Auto-close traces after 5 minutes});
maxTraceLifetimeMs defaults to 0 (disabled). When set, it applies to all traces created by the client.
In v2, trace IDs are generated client-side at creation time as W3C Tracing Context compatible 32-character hex strings. The ID is available immediately via getTraceId() — no need to wait for the server response.
const trace = client.trace({ name: 'MyTrace' });const traceId = trace.getTraceId(); // Available immediately// Pass to backend before any network callfetch('/api/action', { headers: { 'X-Mirador-Trace-Id': traceId }});
This is especially important for cross-SDK trace sharing — the frontend can generate the ID and pass it to the backend via headers before any network call completes.
Both the Web SDK and Node.js SDK automatically batch and send trace data at the end of the current JavaScript tick (microtask). All flushes send idempotent FlushTrace requests.You can also call flush() manually at any time to send pending data immediately:
const trace = client.trace({ name: 'MyTrace' }) .addAttribute('key', 'value') .addEvent('started');trace.flush(); // Send immediately instead of waiting for microtask
flush() is fire-and-forget — it returns void and maintains strict ordering of requests internally.
You can share a trace between the frontend (Web SDK) and backend (Node.js SDK) so that both sides contribute data to the same trace. This is useful when a user action in the browser triggers a backend API call that you want to correlate.
You can also create a trace on the backend and resume it on the frontend:
// Backend creates the trace and returns the ID in the responseapp.get('/api/session', async (req, res) => { const trace = mirador.trace({ name: 'UserSession' }) .addAttribute('userId', req.user.id) .addEvent('session:started'); // ID is available immediately const traceId = trace.getTraceId(); res.json({ traceId });});