# Token or usage indicator is shown near the input

- **Pattern:** `ab-000145` (`ai-chat-visibility.loading-and-streaming.token-usage-indicator`)
- **Severity:** info
- **Lifecycle:** active
- **Last modified:** 2026-04-18
- **Canonical URL:** https://auditbuffet.com/patterns/ab-000145
- **License:** CC-BY-4.0 — attribute to AuditBuffet Pattern Catalog (https://auditbuffet.com/patterns/ab-000145)

## Why it matters

When an application enforces per-user message quotas or subscription-tier rate limits but shows no indicator, users experience silent, opaque walls — a request goes out, nothing comes back, and there is no signal explaining why. This erodes trust and generates support tickets that cost real time. The iso-25010:2011 performance-efficiency dimension treats predictability as a quality attribute: users cannot manage their own consumption if the system conceals it. Cost-efficiency also degrades on the operator side when users retry aggressively against an invisible limit, amplifying API spend without delivering additional value.

## Severity rationale

Informational because the failure harms user experience and increases support load but does not expose data or create a security vulnerability.

## Remediation

Return remaining quota from your API route and render it near the input in `src/components/chat/ChatInput.tsx`. Only render the indicator when a limit is actually enforced — do not show it for unlimited tiers.

```tsx
{usageLimit && (
  <span className={cn(
    "text-xs",
    remaining < 5 ? "text-destructive" : "text-muted-foreground"
  )}>
    {remaining} / {usageLimit} messages remaining
  </span>
)}
```

Emit `X-RateLimit-Remaining` (or equivalent) as a response header in `app/api/chat/route.ts` so the client can read it without parsing the full response body.

## Detection

- **ID:** `token-usage-indicator`
- **Severity:** `info`
- **What to look for:** Count all usage-limiting mechanisms in the codebase: rate limiting middleware, per-user quotas, subscription tier checks on the chat route. Check whether any form of usage information is displayed near the chat input or in the interface header. This could be a message count ("5 / 20 messages remaining"), a token counter, or a context window indicator. Look for usage tracking in API response handling and UI rendering.
- **Pass criteria:** The interface shows some form of usage or limit indicator when the application has at least 1 usage limit. For unlimited applications, this check passes by default. Report even on pass: "Found N usage limit mechanisms; indicator displays [description]."
- **Fail criteria:** The application has usage limits (rate limiting, per-user message quotas, or subscription tier limits) but displays no indicator — users hit limits without warning.
- **Skip (N/A) when:** The application has no usage limits (no rate limiting, no per-user quotas, no subscription gating on chat usage). Signal: no rate limiting middleware, no usage tracking in the database, and no subscription-based access control on the chat route.
- **Detail on fail:** `"Chat has per-user message limits enforced in API route but no usage indicator in UI — users hit limits without warning"`
- **Remediation:** In your API route at `app/api/chat/route.ts`, return usage data as a header or in the response body. In `src/components/chat/ChatInput.tsx`, render the indicator:

  ```tsx
  {usageLimit && (
    <span className={cn("text-xs", remaining < 5 ? "text-destructive" : "text-muted-foreground")}>
      {remaining} / {usageLimit} messages remaining
    </span>
  )}
  ```

---

## External references

- iso-25010 performance-efficiency

Taxons: user-experience, cost-efficiency

HTML version: https://auditbuffet.com/patterns/ab-000145
