Backfilling Historical Data

Load historical events and correct past usage data without corrupting current aggregates.

When to Use Backfill

Backfilling is the process of loading usage events with timestamps in the past. You should use the backfill endpoint in two main scenarios:

Initial migration: You’re switching to ABAXUS from an existing billing system and have historical usage data in your own database or another metering service. You want to load that history so ABAXUS has accurate aggregate totals for invoicing from your migration date forward.

Data correction: An event pipeline failure, a bug in your event-sending code, or a missed integration caused a gap in your usage data. You’ve identified the missing events from your own logs and want to backfill them to correct the record before the billing period closes.


How Backfill Differs from Regular Ingestion

The backfill endpoint (POST /v1/events/backfill) differs from the standard ingestion endpoints in two important ways:

Queue bypass: Regular events enter an async queue and are processed by a background worker. Backfill events write directly to the event store synchronously. This means the response to a backfill request is not 202 Accepted but 200 OK with confirmation that the events are written.

Aggregate invalidation: ABAXUS maintains pre-computed usage aggregates for efficiency. When backfill events are written for a time range that already has computed aggregates, those aggregates are automatically invalidated and will be recomputed on the next usage query. This ensures your usage totals reflect the corrected data without any manual cache-clearing.


Making a Backfill Request

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
curl -X POST "$ABAXUS_URL/v1/events/backfill" \
  -H "Authorization: Bearer $ABAXUS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [
      {
        "customer_id": "cust_acme",
        "metric_key": "api_calls",
        "value": 1500,
        "timestamp": "2026-03-15T14:22:00Z",
        "idempotency_key": "backfill_migration_acme_20260315_batch_001"
      },
      {
        "customer_id": "cust_acme",
        "metric_key": "api_calls",
        "value": 2200,
        "timestamp": "2026-03-16T09:00:00Z",
        "idempotency_key": "backfill_migration_acme_20260316_batch_001"
      }
    ]
  }'

Response: 200 OK

1
2
3
4
5
6
7
{
  "written": 2,
  "duplicates": 0,
  "affected_periods": [
    { "customer_id": "cust_acme", "period_start": "2026-03-01", "period_end": "2026-03-31" }
  ]
}

The affected_periods field tells you which billing periods had their aggregates invalidated. Any usage queries for those periods will now trigger a recompute.


Idempotency in Backfill

The same idempotency rules apply to backfill events. Every event in a backfill request must include an idempotency_key. If you’re running a backfill from a structured data source (database rows, log files, CSV exports), derive the key from a stable identifier in that source:

backfill_{source}_{record_id}_{metric_key}

This ensures that restarting an interrupted backfill doesn’t create duplicate events. ABAXUS will silently skip any events with keys it has already seen, and the duplicates count in the response tells you how many were skipped.


Backfill and Closed Invoices

If a billing period has already been invoiced and the invoice is in paid or archived status, backfilling events into that period does not automatically update or re-issue the invoice. ABAXUS protects closed invoices from modification. If corrected usage data should result in an adjusted charge, you’ll need to handle that through a credit note or an adjustment invoice for the difference — a workflow you manage in your billing operations process.