Skip to content

TSA-495: Include rate-limited and retry charges in document_cost - #538

Merged
anjoanka merged 9 commits into
mainfrom
fix/TSA-495-document-cost-rate-limited-charges
Sep 30, 2026
Merged

anjoanka merged 9 commits into
mainfrom
fix/TSA-495-document-cost-rate-limited-charges

Conversation

@anjoanka

Copy link
Copy Markdown
Collaborator

Closes #495

Summary

document_cost only summed the transcription table, but the worker charges
document.spent_usd in two places where no transcription row is written:

  • rate-limited repair call (deferRateLimitedPage): tokens from the first call
    are charged, the page is deferred, the charge lives only in
    page_event transcribe_rate_limited
  • retryable failure (handleFailedTranscription with retry): the charge lives
    only in page_event transcribe_failed with transcription_id = NULL

Budget enforcement was correct, but the cost view understated spending — or
returned no row at all for a document stopped by its budget on such calls.

Changes

  • New migration recreating document_cost: sums transcription rows plus
    page_event charges (transcribe_rate_limited / transcribe_failed) that have
    no transcription row and costUsd > 0. Events linked to a transcription row are
    skipped, so nothing is counted twice. Columns are unchanged; calls,
    avg_latency_ms and cache_hits still describe transcription rows only.
    down() restores the previous view.
  • transcribe.ts: the transcribe_rate_limited event now also stores
    inputTokens / outputTokens, same as transcribe_failed already does.
  • Docs: docs/schema/schema.sql and docs/04-database.md updated.

The retryable-failure path is not in the original issue, but it is the same
root cause in the same view, so it is fixed here too.

How to test

  1. npm run migrate:dev -w apps/backend
  2. Inside a transaction (rolled back at the end), insert a document with two
    rate-limited events ($0.000144 each) and a document with a retry charge
    ($0.003) + a final failure with a transcription row ($0.004) + a success ($0.01).
  3. Compare document.spent_usd with document_cost.total_cost_usd.

Before:

     title      | spent_usd | total_cost_usd | calls | input_tokens
----------------+-----------+----------------+-------+--------------
 TSA-495 ticket |  0.000288 |                |       |
 TSA-495 mixed  |  0.017000 |       0.014000 |     2 |         3200

After:

     title      | spent_usd | total_cost_usd | calls | input_tokens
----------------+-----------+----------------+-------+--------------
 TSA-495 ticket |  0.000288 |       0.000288 |     0 |          200
 TSA-495 mixed  |  0.017000 |       0.017000 |     2 |         4200

Notes

  • Rate-limited events written before this change have no token counts, so they
    add cost but 0 tokens.
  • A document with only such charges shows calls = 0 and avg_latency_ms = null.

@anjoanka anjoanka self-assigned this Sep 29, 2026
@anjoanka anjoanka added bug Something isn't working backend Backend application labels Sep 29, 2026
@RomanNabukhotniidev

Copy link
Copy Markdown
Collaborator

good work!

@MatiStb
MatiStb self-requested a review September 30, 2026 10:03
@Dekshad
Dekshad self-requested a review September 30, 2026 13:59

@Dekshad Dekshad left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!
Tested locally, works as expected.

@anjoanka
anjoanka merged commit 9b730f3 into main Sep 30, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Backend application bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] document_cost omits charges from rate-limited repair calls

5 participants