Bulk Event Ingestion
This guide covers how to reliably send large volumes of usage events to Monk from a database, warehouse, or scheduled export.For real-time event streaming, see Send your first
Event. This guide is for batch/scheduled workflows —
e.g., syncing 100K+ events daily from a centralized database.
Architecture Overview
| Daily Volume | Requests Needed | Approach |
|---|---|---|
| < 10,000 | 1 | Single batch call |
| 10K – 100K | 2–10 | Sequential or parallel batches |
| 100K – 1M | 10–100 | Parallel batches with concurrency control |
| > 1M | 100+ | Parallel batches + contact us for dedicated ingestion |
Step-by-Step
1. Query your events
Pull new events from your database since the last sync. Track your cursor (e.g., last processed ID or timestamp) to avoid re-processing.2. Chunk into batches
Split your result set into chunks of up to 10,000 events.3. Schedule it
Run your sync on a schedule — hourly or daily depending on how fresh you need usage data.| Frequency | Use Case |
|---|---|
| Every hour | Near-real-time usage visibility on invoices |
| Daily | Sufficient for monthly billing cycles |
| On-demand | Backfills, migrations |
4. Handle failures
Use idempotency keys for safe retries
Use idempotency keys for safe retries
Derive keys from your source data (e.g.,
sync_{row_id}) so retrying the same batch doesn’t create duplicates.Retry transient errors with backoff
Retry transient errors with backoff
On
5xx or 429 responses, retry with exponential backoff. Don’t retry 4xx validation errors — those need fixing in your source data.Log and alert on persistent failures
Log and alert on persistent failures
If a batch fails after retries, log the failed events and alert your team. Don’t silently drop events — they’ll show up as missing usage on invoices.
Customer Mapping
Events require eithercustomerId (Monk UUID) or externalCustomerId (your identifier). For bulk sync, externalCustomerId is usually easier since it matches your internal customer IDs.
Monitoring Your Sync
After syncing, verify events landed correctly:- List events:
GET /v1/events?customerId=...&start=2026-03-15&end=2026-03-16 - Check usage cost:
POST /v1/usage/costto verify aggregated amounts - Dashboard: Navigate to Usage-based → Events to browse visually
FAQ
Can I send more than 10,000 events at once?
Can I send more than 10,000 events at once?
Not in a single request. Split into multiple batch calls. At 5,000 events
per batch, you can sync 100K events in 20 sequential API calls — typically
under a minute.
What if I send duplicate events?
What if I send duplicate events?
Use consistent
idempotencyKey values derived from your source data. Monk
deduplicates on this key — only one copy is counted for billing.How quickly do events appear on invoices?
How quickly do events appear on invoices?
Events are processed asynchronously. Usage-based invoice line items are
refreshed within minutes of ingestion.
Can I backfill historical events?
Can I backfill historical events?
Yes. Set the
timestamp field to the original event time. Events are
attributed to the billing period matching their timestamp, not their
ingestion time.What happens if a batch has one invalid event?
What happens if a batch has one invalid event?
The entire batch is rejected with a validation error. We recommend
validating your data before sending — check that all customer IDs exist and
timestamps are valid ISO 8601.
Next Steps
Events Concepts
Idempotency, schema, and best practices
Batch Events API
Full API specification
Usage Cost API
Verify aggregated usage amounts
Meters
How events are aggregated into billable usage