Rate limits
Pionne enforces two independent rate limit layers: SDK-side (anti-runaway loop in your app) and server-side (anti-abuse for a leaked token). Both protect your monthly quota.
Server limit — per token
Section titled “Server limit — per token”All public endpoints authenticated by X-Pionne-Token (/ingest, /sessions, /feedback, /profiles) are rate-limited per token, not per IP.
Why per token and not per IP?
Section titled “Why per token and not per IP?”On mobile, the source IP is a carrier NAT shared by thousands of users. Throttling per IP either breaks legitimate apps at peak hours or protects nothing (an attacker swaps IPs on 4G).
Throttling per token means:
- The actual blast-radius unit: a leaked token = one project impacted, not the whole ecosystem.
- Stable: a user moving from Wi-Fi to 4G keeps their token, no glitch.
- Aligned with the monthly quota: you read the throttle in the same unit as your billing.
Response on overflow
Section titled “Response on overflow”Beyond the limit, the API returns:
HTTP/1.1 429 Too Many RequestsRetry-After: 42The SDK silently fails the send (internal try/catch). No error surfaced to the host app.
Per-project override (coming soon)
Section titled “Per-project override (coming soon)”For enterprise projects that need more, a custom per-project quota will soon be configurable via Settings → Project → Rate limit. If you need it right now, get in touch.
Client limit — token bucket
Section titled “Client limit — token bucket”The SDK itself enforces a process-level rate limit via the maxEventsPerSecond option:
Pionne.init({ token: '...', maxEventsPerSecond: 10, // sane default});It’s a token bucket: capacity = burst, refill = maxEventsPerSecond/sec, silent drop above.
Anti-runaway loop
Section titled “Anti-runaway loop”The typical case: a badly written useEffect that throws in a loop:
useEffect(() => { throw new Error('oops');}, [stateThatChangesEveryRender]);Without a rate limiter, your app sends dozens of events per second to Pionne, draining your monthly quota in minutes. The token bucket caps that, then drops.
In dev (__DEV__), the SDK warns periodically in the console so you catch the leak:
[Pionne] rate-limit reached (250 events dropped). Bump maxEventsPerSecond if intentional.Disable
Section titled “Disable”For apps doing batch processing or with a legitimate burst:
Pionne.init({ token: '...', maxEventsPerSecond: 0, // disabled});What it protects
Section titled “What it protects”| Scenario | Client limit | Server limit |
|---|---|---|
| Error loop in your code | ✅ token bucket | ✅ server backup |
| Stolen token spammed from another app | ❌ (the attacker can disable it) | ✅ 429 |
| Accidental load test | ✅ + ✅ | |
| Volumetric DDoS attack | (not very useful) | Cloudflare in front + 429 |
See also
Section titled “See also”- Tokens & rotation — regenerate your token if you suspect a leak.
- Bundle ID binding — orthogonal layer that rejects events from another bundle.
- API Ingest — endpoint details.