Limits and validation

Every ceiling and every silent drop: batch sizes, rate limits, event name and property rules, timestamp clamping, and what a 204 with nothing in a report means.

Validation here is forgiving on purpose: an invalid event is dropped from a batch, never a reason to fail it. That is the right trade for analytics, where losing one event matters far less than losing the request that produced it, but it means a misconfigured client gets 204 and no data. This page is the list of everything that can be dropped, so you can find out which one you hit.

Numbers verified 2026-09-28 against the running service.

Batch and request ceilings

Beyond the event ceiling, the surplus is counted, not queued. On /v1/ingest the extra events are dropped; on /v1/import they come back in rejected. The service slices your list into batches of 50 internally, so you do not have to chunk for /v1/import, only for /v1/ingest.

Rate limits and quota

Over the per-key limit: 429 {"error":"rate_limited"}. The bucket is per key, so a whole fleet sharing one Server key shares one bucket. If you need more headroom, create more keys rather than asking for a higher number: keys are free and a separate key per service also tells you which service is noisy.

Over the Project's monthly quota: 429 {"error":"quota_exceeded"}. See Usage and billing.

Event names

The rule, exactly: 1 to 96 characters from letters, digits, _, $, ., : and -, with interior spaces allowed and no leading or trailing space.

A name the validator rejects means the whole event is dropped. The Mixpanel shim is gentler: it replaces rejected characters with _ and cuts the name at 96, so an SDK's event is never lost to a stray character.

Names are case-sensitive and never normalised.

Ids

At least one of did, uid, aid must survive, or the event is dropped. This is the most common cause of a 204 with nothing to show for it.

Properties

Values must be scalars: string, finite number, boolean or null. An array or a nested object is dropped on /v1/ingest. The keys __proto__, constructor and prototype are refused.

NaN and Infinity are not finite, so they are dropped. A number arriving as a string stays a string, and a report that sums it will not.

The Mixpanel shim is again gentler: it keeps arrays and nested objects as compact JSON strings rather than dropping them, cut at 512 characters.

Timestamps

Warning

/v1/import keeps every event's ts exactly as sent; the service marks imported ids internally so they are never clamped. Use your own stable id per row (an order id, a row key) so a re-run after a failure is idempotent. Only /v1/ingest clamps timestamps to the last 24 hours.

Clamping is not an error and is not reported. Verify a backfill by looking at the earliest event in a report, not at the import's answer.

Element metadata

Autocaptured events carry el. Every field has a cap, and a value over its cap drops the whole el object while keeping the event: tag 32, selector 512, text 64, href 512, data-track 96, id 128, at most 8 classes of 64 characters each, field name 96. el never contains an input's value.

Sessions and profiles

  • Session properties (sp): known keys (utm_source, utm_medium, utm_campaign, utm_term, utm_content, referrer, landing path) become columns; the rest are kept as properties. First-touch columns are written once and not overwritten.
  • profile on a $profile event is honoured only from a Server key. From anyone else it is ignored, and the event still stores.
  • Group keys per Project: 10. Allowed origins per Project: 50. Blocked IP hashes per Project: 500.

Retention

Default retention is the service default; a Project can set retentionDays between 1 and 3 650. See Data and privacy.

Concurrency

GET /v1/live allows 50 concurrent subscribers per Project. Over that: 503 {"error":"live_subscribers_exhausted","limit":50}. The stream buffers nothing, so a subscriber sees only what arrives after it connects.

Debugging a silent drop

A 204 and nothing in the Live view, in the order worth checking:

  1. No identifier. No did, uid or aid survived. A Project token's did is always stripped, so a browser client that sends only did sends nothing usable.
  2. Duplicate id. The same id twice in one batch, or an id already stored. Common when a client reuses one id for a whole batch.
  3. Rejected name. A character outside the allowed set, a leading space, or over 96 characters.
  4. Empty batch. events missing, not an array, or v not 1. A 204 is also the answer when a batch validates down to zero events.
  5. Wrong Project. The credential decides the Project, and a x-analytics-project header cannot override it. Check which Project the key belongs to.
  6. Origin pinned. If the Project lists allowed origins, a browser request from another Origin is refused outright.

If the event does reach the Live view but is missing from a report, the ingest side is fine: look at the report's date range, its filters, and whether it depends on a defined event whose rules do not match.

Next