Collector limits
Every limit here is enforced by the collector and shared with both SDKs from one definition, so the documented number and the enforced number cannot drift apart.
| Limit | Value | What happens at the edge |
|---|---|---|
| Event name | ^[a-z0-9_]{1,64}$ | Rejected and reported; the rest of the batch is still accepted |
| Properties per event | 2048 bytes of JSON | The event is rejected and reported |
| Events per batch | 100 | The SDK splits larger queues automatically |
| Events a month | By plan: 100,000 to 5,000,000 | Warnings at 80% and 100%; collection pauses past 120% until the next month. See Plans and usage |
| Events per second, per project | 50 a second, bursts of 500 | Answered 429 with Retry-After; the SDKs retry |
| Distinct event names per project | 200 | New names beyond the cap are rejected and reported |
| Write key length | 64 characters | Longer is rejected |
| Anonymous identifier length | 64 characters | Longer is rejected |
| Clock skew | 7 days either side | Beyond it the event is rejected rather than filed under the wrong day |
| Queue depth | 500 events | The oldest are dropped first |
| Captured value length | 64 characters | Truncated by the SDK before sending |
| Captured path length | 128 characters | Truncated by the SDK before sending |
| Raw event retention | 90 days | Then deleted. Daily rollups are kept indefinitely |
| Data of an account with no plan | Removed 60 days after its trial or subscription ends | Projects and write keys stay. See When a trial ends |
Why captured values are bounded
The properties the SDK captures for you are spent from the same 2048-byte budget your own properties come from. Left unbounded, a link somebody tagged with five kilobytes of UTM would push your event over that limit and get it rejected — your data lost to our convenience. At the lengths above the whole captured set fits inside half the budget, leaving the rest yours.
Paths get the longer bound because truncating a path is worse than shortening it: two different pages that share a long prefix would collapse into one row in every report, where a truncated campaign label is still recognisably itself.
Rejections are per event, not per batch
One malformed event does not lose the ninety-nine that travelled with it. The collector filters them out, accepts the rest, and reports what it dropped and why.
Only a malformed envelope — a bad write key, a missing client field — rejects the whole request, because in that case nothing in it can be attributed to anybody.
Why the distinct-name cap exists
Two hundred is generous for named events and immediately restrictive for generated ones. It exists to catch saved_session_${id} early, before a project has a hundred thousand event names nobody can group by. See naming.
Why the clock-skew window is seven days
Because a durable queue means events arrive late by design: an offline laptop, a suspended service worker, a device with a wrong clock. Seven days covers all three. The rollups recompute far enough back to include everything the window admits, so a late event still lands in the right day rather than being accepted and never counted.