Ask
118
@brinekeeper ·

my stripe meter reports 6% fewer events than my own counter, which number do i trust Usage-Based

I bill $0.02 per completed task. My app writes a row to tasks for each one and also posts a meter event to Stripe.

For last month my table says 1,204,880 tasks. The meter summary says 1,133,090. That is 71,790 tasks, roughly $1,436 I did not invoice.

I have been through it twice and I cannot make the two agree. Chart of where it goes is attached. I do not know whether the correct move is to fix the pipeline or fix my expectations about how close these should be.

9 answers Share
Report

Answering anonymously — a moderator will review it first.

  • @p99_hana · 4d ago · 3 replies

    Two causes, both boring, both in your chart.

    The rejections are almost certainly fire-and-forget posts whose response nobody reads. Meter events have an accepted timestamp window; anything you replay from a backlog, a dead-letter drain or a late worker lands outside it and comes back a 400 that goes straight into the void. Log the status code and you will find them in an afternoon.

    The dedupe is your retry wrapper. Stripe keeps one event per identifier and it is right to. Your table kept two because you inserted before you sent. Make the identifier deterministic - a hash of the task id, not a uuid generated at send time - and retries become free instead of lossy.

    The structural fix is an outbox. Add metered_at and meter_event_id columns to the task row, a worker that fills them, and a query that finds rows older than an hour with metered_at is null. Then the gap is an alert on a Tuesday instead of a discovery at month end.

    141
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @token_rot_priya · 6d ago

      The outbox is the whole answer. Once every billable row has a nullable metered_at, reconciliation is one query you can put on a dashboard, and "are we billing correctly" stops being a feeling.

      44
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
    • @rueben_alsop · 6d ago

      Deterministic identifier is the bit I would do first because it is ten minutes and it makes the rest of the debugging honest. As long as the id changes per attempt you cannot tell a duplicate from a genuine second task.

      15
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @runway_math · 5d ago

    Trust the invoice, because that is the number your customer will argue with and the number your accountant will reconcile against the bank. Keep your own counter as the check, not the source.

    Then set a threshold and treat crossing it as an incident. Anything over about half a percent means a bug, not variance. 6% is not a rounding difference, it is a broken pipe you have been paying for.

    62
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @hemline_hana · 3d ago · 2 replies

    Meter aggregation is eventually consistent. Give it 24 hours and check again, the numbers usually converge and everyone stops panicking.

    21
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
    • @p99_hana · 5d ago

      Ingestion lag is real and it is minutes, not a 6% hole at month end. If the period is closed and the invoice is finalised, the number on the invoice is the number. Waiting a day here just delays finding the actual bug.

      18
      Share
      Reply

      Answering anonymously — a moderator will review it first.

      Report
  • @burr_and_edge · 4d ago

    6% is not drift. Drift is 0.1%. I lost most of a week to something that looked exactly like this and it was a retry helper deduping on a key that included the attempt number, so every retry was a new event on our side and the same event on theirs. Look at your retry code before you look at anything else.

    38
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @bench_dogged · 6d ago

    Worth knowing for the other direction too: if you ever bill an event you should not have, there is a meter event adjustment for cancelling it. You cannot just send a negative one and you cannot re-send a rejected one after the window closes, so build the retry to be fast rather than eventual.

    17
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report
  • @late_stage_phd · 5d ago

    For whatever it is worth, undercounting is the good direction to have this bug in. The other direction is refunds, a support thread and a customer who now reads every invoice line by line forever.

    9
    Share
    Reply

    Answering anonymously — a moderator will review it first.

    Report