LLM Cost Tracking: How to Actually Monitor API Spend
LLM cost tracking means recording, attributing, and monitoring how much you spend on model API calls — broken down by user, feature, environment, or team — so you can catch overspend before the invoice arrives. It's different from cost estimation (predicting spend in advance) because it deals with actual, historical usage data pulled from real requests.
If you're searching for this, you probably already have an LLM feature in production and you've either been surprised by a bill or you're trying to avoid being surprised next month. This article covers what to track, how to instrument it, and how to build a system that gives you answers instead of guesses.
Why Cost Tracking Gets Skipped
Most teams add LLM calls to a feature, ship it, and only look at cost when finance asks a question. This happens for a few reasons:
- Usage data is buried. Provider dashboards show aggregate totals, not per-user or per-feature breakdowns.
- Streaming responses make token counting harder. You don't know the final token count until the stream closes.
- Multiple environments blend together. Staging, dev, and production traffic often hit the same API key.
- Nobody owns it. Cost tracking falls between engineering and finance, so it defaults to nobody.
None of these are hard problems individually, but they compound. By the time you notice a cost spike, you've usually lost the context needed to explain it.
What to Actually Track
A useful LLM cost tracking setup captures more than a running total. At minimum, log these fields per request:
- Timestamp — for time-series analysis and spotting spikes
- Model — different models have different per-token pricing
- Input tokens and output tokens — separately, since output is usually priced higher
- Endpoint or feature — which part of your product triggered the call
- User or account ID — who or what caused the cost
- Environment — dev, staging, production
- Request ID — for tracing back to logs when something looks wrong
With these fields, you can answer the questions that actually matter: which feature is expensive, which users are driving cost, and whether a recent deploy changed your spend trajectory.
Instrumenting Cost Tracking Yourself
If you're calling a model API directly, the token counts usually come back in the response metadata. A basic logging wrapper looks like this:
async function trackedCall(payload, meta) {
const start = Date.now();
const response = await callModel(payload);
await logUsage({
timestamp: new Date().toISOString(),
model: payload.model,
inputTokens: response.usage.input_tokens,
outputTokens: response.usage.output_tokens,
feature: meta.feature,
userId: meta.userId,
environment: process.env.NODE_ENV,
latencyMs: Date.now() - start,
});
return response;
}
This gets you raw data, but you still have to build the pricing math, the dashboard, and the alerting on top of it. For a side project that's fine. For anything with multiple developers or multiple features hitting the model, it turns into ongoing maintenance — pricing tables change, new models get added, and someone has to keep the aggregation queries correct.
Attribution: The Part People Underbuild
Raw totals tell you what you spent. Attribution tells you why. The most common attribution gaps:
- Per-feature breakdown. If your chatbot, your summarizer, and your search assistant all call the same model, you need a
featuretag on every request, not just a shared API key. - Per-team or per-customer breakdown. If you're building a B2B product, you may need to bill or budget by customer, which means every call needs a customer ID attached.
- Per-environment separation. A load test in staging shouldn't show up in your production cost dashboard, but it will if everything shares one key.
Tagging every call correctly is tedious to enforce manually — someone always forgets to pass the metadata, and now you have a chunk of untracked spend.
Where a Managed Layer Helps
This is where a managed API layer can remove a category of work rather than just adding another dashboard. SubToAPI sits between your app and Claude, issuing application-level API keys (sub_live_...) per team or per project, and every request that goes through those keys carries usage metadata — tokens in, tokens out, model used — that you can pull for reporting.
Instead of building your own logging wrapper, pricing table, and aggregation job, you generate a separate key per feature or per environment from the SubToAPI dashboard, and the usage naturally splits along those lines. If you want per-customer attribution, a key per customer works the same way. The quickstart covers key creation and the messages docs cover the request format, which mirrors the standard Claude API shape:
curl https://api.subtoapi.app/v1/messages \
-H "Authorization: Bearer $SUBTOAPI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "Summarize this ticket."}]
}'
Because seats and keys are managed per team (Solo €9, Team €19/seat, Scale €49/seat), cost tracking maps directly to your org structure instead of requiring a separate attribution system bolted on afterward. That's a meaningful shortcut if you're a small team and don't want to own a billing pipeline as a side project.
Setting Up Alerts, Not Just Dashboards
A dashboard you check once a week won't catch a runaway loop that burns through your budget in six hours. At minimum, set up:
- A daily spend threshold that pages someone if crossed
- A per-user rate limit to stop a single account from generating unbounded cost
- A weekly digest broken down by feature, so trends are visible before they become emergencies
If you're building this yourself, a simple cron job that queries yesterday's usage and compares it against a rolling average catches most anomalies without much engineering effort.
Keeping It Simple
You don't need a full observability platform on day one. Start with per-request logging of tokens, model, and feature. Add per-user attribution once you have more than one meaningful user segment. Add alerting once you've been burned once by a spike you didn't see coming. Every added layer should answer a specific question you've actually needed to answer — not one you might need to answer someday.
Questions
Does LLM cost tracking replace rate limiting? No. Cost tracking tells you what happened after the fact; rate limiting prevents runaway spend in real time. You generally want both — tracking for reporting and attribution, limits for protection.
Can I track cost without provider-level token metadata? You can estimate it by counting tokens client-side with a tokenizer library, but actual provider-reported usage is more accurate, especially for output tokens in streaming responses.
How often should I review LLM cost data? Daily for anomaly detection (a spike usually means a bug, not organic growth) and weekly for trend review across features and teams.