Documentation menu

Telemetry budgets

Open Settings → Data → Manage telemetry for an application's selected environment. Usage distinguishes received, retained, sampled-out, budget, cardinality and disabled-module observations. The chart covers 30 UTC days; counters and alerts remain available for 90 days. Metering starts with this feature, without backfilling historic traffic.

Policy

Defaults are 100% sampling, no daily limits, no series limit and no removed labels. Changes require apps.write, an expected revision, and an atomic audit event. Each organization, application and environment has a separate policy. An environment advisory lock serializes policy changes and admission, so multiple web processes cannot overshoot the same daily cap.

Signal Sampling Daily budget
Analytics Session ID, then anonymous ID, then distinct ID, then event ID; deterministic for each key Retained page, track, session and web-vital observations
Identity Always retained when Analytics or People is enabled Identify and alias are exempt to preserve account linking
Errors Deterministic event-ID sampling Retained error occurrences
Metrics Deterministic event-ID sampling Retained metric points

Sampling runs before daily limits. Warn only retains data beyond the budget; Stop retaining drops new observations after the limit until midnight UTC. Reducing a limit below today's usage takes effect immediately. Changing the sample percentage or reaching a daily cap can split an in-progress session's retained history. Reports show retained observations, with no extrapolation or inverse-probability weighting. Metric counters, sums and percentiles describe the sample, not estimated original traffic. An application notice identifies active sampling, limits or budget thresholds reached today.

Module-disabled signals are explicitly dropped. Web vitals require either Analytics or Metrics; identity requires Analytics or People. Controls affect new ingest only. Historic events are unchanged and discarded payloads cannot be recovered.

Accounting and retries

Admission follows authentication, origin checks, the existing per-key rate limiter, validation, bot filtering and retention-window checks. Usage excludes these earlier refusals. received counts unique valid observations presented to admission, not requests or retries. Byte counters measure validated JSON before and after label removal, not disk usage or billable network traffic.

HTTP 202 retains {accepted, rejected} and optionally adds discarded: [{index, reason}], with reason sampled, budget, cardinality or disabled. accepted + rejected.length + discarded.length equals batch size. Intentional drops are acknowledged and must not be retried. The Node SDK understands this response; browser and native transports already finish on 2xx. Older Node releases also finish, but can report an invalid-acknowledgement diagnostic when drops occur; update the SDK to remove that diagnostic.

Scoped receipts retain each event ID's decision for 48 hours. Repeated IDs within one batch or subsequent requests do not inflate usage or consume another slot, including errors and metrics. A retry receives the original outcome even after policy changes. Pre-rollout events are detected in all three stores within the same deduplication window and do not enter new counters. Outside the window, a retry may be metered again. Receipts, counters, series admission and sink writes commit together; failed ingestion rolls all of them back. Destinations receive only retained analytics IDs.

Metric cardinality

A series is the normalized metric name, kind, unit and complete label map. Selected exact label keys are removed before storage and hashing. A daily environment cap admits new combinations until full; already-admitted combinations continue. The registry tracks at most 100,000 combinations per environment and UTC day. With no configured cap, saturation does not stop ingestion and the UI displays 100,000+; enabling a cap then rejects unregistered combinations.

The daily count includes combinations admitted before a label-removal change; removing labels does not reclaim today's slots or alter historical labels. Hashes store no raw label values. The worker keeps today and yesterday's registries.

Noisy-field diagnostics examine at most the newest 10,000 retained metric points and 2,000 retained page/track events from the last 24 hours. They show the twenty highest distinct-value counts, never actual values. These are samples, not full cardinality estimates. Metric names/label keys require metrics.read and Metrics; event property keys require events.read and Analytics. Queries use a consistent read snapshot and a five-second timeout.

Alerts and operations

In-app alerts fire at the warning percentage and 100%, at most once per threshold, signal, policy revision and UTC day. Ingest after a revised policy can alert on usage already above its threshold. Selected channels additionally receive a telemetry.notify job. Changing targets requires metrics.write; channel IDs must belong to the same organization/application. Vault-backed adapters send outside the ingest transaction.

The worker rechecks current channel selection, enabled channels, application deletion and the Metrics module. Alerts show pending, sent, failed, unconfigured or in-app status. Provider failures are recorded without failing ingestion or retrying successful channels. Delivery is not an exactly-once guarantee: a crash after sending but before recording completion can repeat a notification on job retry. Responses and alert messages contain no credentials.

telemetry.retention.purge runs hourly: 48-hour receipts, two UTC days of series hashes, 90 UTC days of usage and 90 days of alerts. Deleting the application/environment cascades operational records; the append-only audit ledger is unchanged.

Management API

  • GET /apps/{app}/telemetry?env=production: policy revision, 30-day usage and latest 50 alerts; apps.read.
  • GET /apps/{app}/telemetry/cardinality?env=production: bounded diagnostics with signal permissions above; apps.read.
  • POST /apps/{app}/telemetry?env=production: {expectedRevision, policy}; apps.write, plus metrics.write to change channels.

OpenAPI describes the complete version-one policy. First save uses revision 0; conflicts return 409. Console writes retain the standard passkey session, origin and CSRF checks.

What the assistant can do here

Ask reads the whole budget picture — policy, thirty days of admission counters, the budget alerts and the high-cardinality labels and properties driving them — which makes "why did ingest stop?" and "why is this bill rising?" answerable in one turn.

Changing the policy is a proposal. Sampling rates, daily limits and series controls are written against the revision the assistant read, so a policy that moved underneath it is refused rather than overwritten, and the preview names exactly which limit changes and by how much before you approve.