generation credit FIFO expiration: Reconcile eligible source credits before spending
The generation credit FIFO expiration behavior is defined by the source transactions available to the consumption function. It is more specific than simply spending the oldest purchase first. A reconciliation must inspect eligibility and ordering as well as the user’s displayed balance.
Read the eligible source set
The consumption query excludes USAGE and EXPIRE entries. It selects transactions with a positive remainingAmount and either no expiration date or an expiration date strictly later than the current time. An expired source is therefore not eligible for that consumption query even if an old report still shows a positive remainder.
The query orders by expirationDate ascending and then createdAt ascending. This gives earlier expiration priority among dated sources, with creation time breaking their ties. Do not replace that logic with a sort based solely on purchase date or transaction identifier in an accounting spreadsheet.
For sources with no expiration date, use the actual database ordering when reproducing the query. Do not invent an application rule that all permanent credits always precede expiring grants. The SQL expression, not a label such as purchase or gift, controls the selected order.
Walk a fictional allocation
Suppose a fixture contains a grant with six eligible credits expiring tomorrow and another source with ten credits expiring next month. A request needing eight consumes six from the first and two from the second, leaving zero and eight respectively. These figures are a made-up accounting example, not a report about a customer.
A source that expired yesterday should not participate in that allocation. If a saved balance and the source totals disagree, record the discrepancy and inspect the expiration and transaction history. Do not quietly add the expired source back to make the arithmetic look convenient.
Refund transactions can also have positive remainingAmount. The refund helper creates a usable source entry when it credits a job refund, so exclude neither refunds nor nonpurchase grants merely because your report originally focused on purchases.
Keep source allocation separate from activity logs
A USAGE entry records a negative amount for consumption. Source entries track what remains available from grants, purchases, or refunds. Summing negative usage amounts together with remaining source balances as though they were identical measures mixes two different views.
Use one report to reconcile the balance movement and another to inspect current source eligibility. Include a common timestamp because eligibility changes at expiration boundaries. A snapshot captured before expiration cannot be compared directly with a source query taken afterward without explaining the time difference.
Acceptance review
Build local fixtures covering two expiration dates, equal expiration dates, an expired source, a permanent source, and a refund source. Check the expected allocation against the query and retain the assumptions about database null ordering.
Approve a diagnostic report when it identifies the snapshot time, eligible sources, selected ordering, and remaining amounts without modifying production data. Read credit ledger reconciliation, refund receipts, and reservation lifecycle for the related accounting boundaries.
Continue with costs and billing
Where these facts come from
- codebase: src/ai/api/credits.ts
- codebase: src/credits/credits.ts
- codebase: src/ai/jobs/service.ts
- codebase: src/ai/jobs/db.ts
- Editorial keyword hypothesis; search volume not measured