FreeLLMAPI KeyStatus Options: Understanding API Key Health States
FreeLLMAPI uses five distinct status values—healthy, rate_limited, invalid, error, and unknown—to track the operational state of every stored API key.
Each upstream provider key in FreeLLMAPI (the open-source LLM routing gateway by tashfeenahmed) carries a KeyStatus field that controls whether it receives traffic. The enum is defined centrally in shared/types.ts and drives routing decisions across the health-checking, rate-limiting, and request-dispatching subsystems.
The Five Key Status Values
healthy
A key marked healthy has passed validation and is actively used for routing requests. This is the desired steady-state for production workloads.
The health-check service in server/src/services/health.ts promotes keys to this status after successful credential verification against the upstream provider.
rate_limited
When an upstream returns HTTP 429, the affected key transitions to rate_limited. It is temporarily excluded from the routing pool until a cooldown period expires.
This protects the overall system from hammering providers that have already signaled capacity constraints. The rate-limiting logic at server/src/services/ratelimit.ts#L450 filters these keys before dispatch.
invalid
Keys that fail definitive credential checks (bad API key, revoked credentials, etc.) are marked invalid. These keys are permanently sidelined and will not be retried.
This state prevents wasted requests on known-bad credentials. The health probe captures the specific error and stores it in last_health_error for audit purposes.
error
Error indicates a non-recoverable transport or protocol failure—timeouts, TLS failures, malformed responses—that does not imply the key itself is bad.
The key leaves the active pool but remains in the database for diagnostics. Operators can inspect the stored error details to distinguish transient infrastructure issues from credential problems.
unknown
Freshly added or never-checked keys start as unknown. They are eligible for routing (tentatively) but will be probed immediately to resolve to healthy or invalid.
This default state allows quick onboarding: keys become usable instantly while background validation determines their true health.
How Status Drives System Behavior
The SQLite api_keys table stores status as a string column. Three core services consult it:
| Service | File | Role |
|---|---|---|
| Health checker | server/src/services/health.ts |
Periodically probes keys and updates status based on validation results |
| Rate limiter | server/src/services/ratelimit.ts |
Excludes rate_limited keys from the candidate pool |
| Router | server/src/services/router.ts |
Selects only healthy or unknown keys for request dispatch |
Working with KeyStatus in Code
Type Definition
// shared/types.ts (L252)
type KeyStatus = 'healthy' | 'rate_limited' | 'invalid' | 'error' | 'unknown';
The type is exported from the shared package and consumed by both server and client code.
Querying Usable Keys
import type { KeyStatus } from '@freellmapi/shared/types.js';
function getUsableKeys(platform: string): Promise<Array<{id: number; key: string; status: KeyStatus}>> {
const stmt = db.prepare(`
SELECT id, encrypted_key AS key, status
FROM api_keys
WHERE platform = ? AND enabled = 1
AND status IN ('healthy', 'unknown')
`);
return Promise.resolve(stmt.all(platform));
}
This pattern appears in server/src/services/media.ts and the router: only healthy and unknown keys are considered for live traffic.
Updating Status After Probes
async function setKeyStatus(
keyId: number,
newStatus: KeyStatus,
errorMsg: string | null = null
): Promise<void> {
db.prepare(`
UPDATE api_keys
SET status = ?,
last_health_error = ?,
last_checked_at = datetime('now')
WHERE id = ?
`).run(newStatus, errorMsg, keyId);
}
The health service calls this pattern at server/src/services/health.ts#L113 after each validation attempt.
Handling Rate-Limit Responses
async function handleRateLimit(keyId: number): Promise<void> {
await setKeyStatus(keyId, 'rate_limited', '429 Too Many Requests');
}
This triggers the temporary exclusion pathway enforced by server/src/services/ratelimit.ts.
Key Lifecycle Flow
- Creation → Key inserted with status
unknown - First request or background probe → Health checker validates credentials
- Validation succeeds → Status becomes
healthy; key enters rotation - Validation fails definitively → Status becomes
invalid; key ignored - Runtime 429 response → Status becomes
rate_limited; key suspended for cooldown - Cooldown expires → Health checker re-probes; may return to
healthy - Transport failure → Status becomes
error; key quarantined for review
Summary
- Five statuses:
healthy,rate_limited,invalid,error, andunknownform the complete state machine for API key health in FreeLLMAPI. - Defined in
shared/types.tsand stored in the SQLiteapi_keystable. - Routing eligibility: Only
healthyandunknownkeys receive traffic;rate_limitedkeys are temporarily blocked;invalidanderrorkeys are excluded. - Automatic recovery:
rate_limitedkeys return tohealthyafter cooldown;unknownkeys resolve on first probe. - Audit trail:
last_health_errorcaptures diagnostic details forinvalid,error, andrate_limitedtransitions.
Frequently Asked Questions
How does FreeLLMAPI handle keys that hit rate limits?
When an upstream provider returns HTTP 429, the key is immediately marked rate_limited in the database. The rate-limiting service at server/src/services/ratelimit.ts filters these keys from the routing pool until a configurable cooldown expires, at which point the health checker revalidates the key.
Can I manually set a key's status?
Yes. The status column is a standard string field in the api_keys table. You can issue direct SQL updates or call internal service methods like setKeyStatus() shown above. Changes take effect on the next routing decision—there is no caching layer that would delay status updates.
What happens to keys with error status?
error indicates a non-recoverable transport or protocol problem rather than a credential failure. These keys are excluded from routing but retained in the database. Operators should inspect last_health_error and last_checked_at to determine whether the issue was transient infrastructure failure or requires manual intervention.
Why does unknown status still allow routing?
unknown is the default for newly added keys. The system permits tentative routing to avoid startup delays, while simultaneously triggering a background health probe. This design balances availability (keys work immediately) with safety (bad keys are quickly demoted to invalid).
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →