Event delivery & batching
How PlayGenus SDKs batch, retry, and deliver events in the background — flush intervals, offline queueing, and what happens when the app closes or your server shuts down.
You never manage networking or batching yourself. Every SDK runs a background
loop that collects your track() calls into batches and ships them to the
ingestion API. This page is for when you want to know exactly what that loop
does — because "trust me" is not documentation.
How it works
- You call a typed event method (say,
purchaseCompleted(...)) or the generictrack(). - The event goes into an in-memory queue with an ISO 8601 timestamp.
- A background timer wakes at a fixed interval and sends everything queued
as a single JSON batch to
POST /v1/events. - If the queue hits the max batch size before the timer fires, a flush triggers immediately.
- On a 5xx or network error, the SDK retries up to 3 times with exponential backoff (1s → 2s → 4s).
- On a 4xx error — bad request, invalid API key — the batch is dropped and logged. Retrying a request that's wrong won't make it right.
Timing by SDK type
| SDK | Flush interval | Max batch size | Why |
|---|---|---|---|
| Client SDK | 30 seconds | 50 events | Player devices are battery-constrained — fewer network calls save battery and mobile data |
| Server SDK | 5 seconds | 50 events | Servers are always-on with stable connectivity — faster delivery means fresher dashboards |
Client SDK — the extra triggers
The client has delivery triggers beyond the timer, because mobile apps don't get to choose when they die:
| Trigger | What happens |
|---|---|
| App goes to background | Flushes all queued events, then tracks session_end |
| App is closing | Best-effort flush before the OS kills the process |
| App returns to foreground | Tracks session_foreground and starts a new session |
Manual Flush() call | Force a flush any time — worth doing right after a critical event like a purchase |
The client queue is also persisted to disk (up to 10,000 events), so events survive an app crash and go out on the next launch. If the player is offline, everything queues and sends when connectivity returns.
Server SDK — shutdown
Server SDKs provide a shutdown() method to call during server stop. It
stops accepting new events, flushes the queue, waits up to 10 seconds for
in-flight requests, and stops the timer.
// Java — in a shutdown hook or Spring @PreDestroy
PlayGenusServer.getInstance().shutdown();// TypeScript — in a SIGTERM handler or server close callback
await PlayGenus.shutdown();Skip this and you'll lose whatever was queued in the last few seconds before the process exited — which, given deploys restart servers all the time, adds up to a slow leak of data. Wire it up once and forget about it.
Overriding the defaults
All timing settings are configurable via the optional Config object passed
to init() — examples on the Quick start.
| Setting | Client default | Server default | Config property |
|---|---|---|---|
| Flush interval | 30s | 5s | FlushIntervalSeconds (C#) / flushIntervalMs (Java, TS) |
| Max batch size | 50 | 50 | MaxBatchSize / maxBatchSize |
| Debug logging | Off | Off | Debug / debug |
The defaults are sensible for nearly everyone. The one override we see legitimately used: shortening the client flush interval during development so you can watch events arrive while testing.
Custom events
Beyond the 47 standard events, PlayGenus recommends custom events shaped to your game's specific mechanics during onboarding — here's how that works, with examples per genre.
Tracking best practices
Naming conventions, event-volume hygiene, receipt validation, and the other habits that keep your PlayGenus data trustworthy.