What Database Does FreeLLMAPI Use for Its Ledger? SQLite Implementation Explained
FreeLLMAPI stores its rate-limit and usage ledger in a SQLite database, using the better-sqlite3 driver (with a fallback to node:sqlite on Android) to persist request counts, token usage, and cooldowns to disk.
FreeLLMAPI is an open-source API gateway that requires robust rate limiting to manage LLM provider quotas. According to the source code in tashfeenahmed/freellmapi, the project answers the question "what database does FreeLLMAPI use for its ledger" by implementing a lightweight, file-based SQLite solution that tracks per-key request counts and provider-wide caps without requiring external database servers.
SQLite as the Ledger Backend
The FreeLLMAPI ledger relies on SQLite as its persistent store. The system uses better-sqlite3 as its primary driver, falling back to the built-in node:sqlite module only when running on Android environments. This synchronous, embedded database approach eliminates network overhead while maintaining ACID compliance for rate-limit accounting.
Default Database Location
By default, FreeLLMAPI creates or opens the SQLite file at server/data/freeapi.db. This path is resolved at runtime and passed to the database factory function. Developers can configure alternative paths, but the standard deployment persists all ledger tables—including rate_limit_usage and rate_limit_cooldowns—within this single file.
Database Driver Selection
The connection logic in server/src/db/index.ts dynamically selects the appropriate SQLite implementation:
- Primary driver:
better-sqlite3for high-performance synchronous operations - Fallback driver:
node:sqlite(Node.js built-in) for Android compatibility
Ledger Schema and Tables
The rate-limit ledger consists of multiple tables defined through migration scripts. The primary table rate_limit_usage records every request and token consumption event, while rate_limit_cooldowns tracks provider-specific backoff periods. These tables are created via migration files located in server/src/db/migrations/.
Core Implementation Files
Recording Usage in ratelimit.ts
The ledger logic resides in server/src/services/ratelimit.ts, where the recordRequest() function persists usage data. This function attempts to write to SQLite first, then falls back to in-memory tracking if the database write fails.
// Record a request in the ledger (ratelimit.ts)
export function recordRequest(platform: string, modelId: string, keyId: number) {
const now = Date.now();
// Try to persist the request; fall back to in‑memory if DB write fails
if (!recordUsage(platform, modelId, keyId, 'request', 0, now)) {
pushMemoryRequest(`${platform}:${modelId}:${keyId}:rpm`, MINUTE, now);
pushMemoryRequest(`${platform}:${modelId}:${keyId}:rpd`, DAY, now);
}
}
Connection Management in db/index.ts
Database connection handling is centralized in server/src/db/index.ts. The betterSqliteFactory() function instantiates the SQLite connection using the resolved file path.
// Open the SQLite database (db/index.ts)
function betterSqliteFactory(resolvedPath: string): Db {
const BetterSqlite = runtimeRequire('better-sqlite3') as new (path: string) => unknown;
return new BetterSqlite(resolvedPath) as Db; // ← SQLite connection
}
Migration System
Schema definitions and table creation are handled through the migration CLI in server/src/db/migrate/cli.ts. Migration files such as 20260729_000001_custom_model_endpoint_identity.ts define the ledger structure, ensuring the rate_limit_usage table exists before the server begins recording data.
How the Ledger Queries Request Counts
When enforcing rate limits, FreeLLMAPI queries the SQLite ledger to determine current usage. The providerDailyRequestCount() function demonstrates this pattern by first checking persisted records, then falling back to in-memory counters if necessary.
// Retrieve the provider‑wide daily request count (ratelimit.ts)
export function providerDailyRequestCount(platform: string, keyId: number, now = Date.now()): number {
const windowMs = msSinceUtcMidnight(now);
const persisted = countPersistedProviderRequests(platform, keyId, windowMs, now);
if (persisted !== undefined) return persisted;
// Fallback to in‑memory windows if the DB is unavailable
// ...
}
Summary
- FreeLLMAPI uses SQLite as the persistent backend for its rate-limit ledger, stored by default in
server/data/freeapi.db. - The system prefers better-sqlite3 for synchronous performance, with
node:sqliteas an Android fallback. - Ledger tables (
rate_limit_usage,rate_limit_cooldowns) are defined via migrations inserver/src/db/migrations/. - Usage recording happens in
server/src/services/ratelimit.ts, with SQLINSERTstatements tracking per-key requests and token consumption. - If SQLite writes fail, the system gracefully degrades to in-memory rate limiting to prevent service interruption.
Frequently Asked Questions
Does FreeLLMAPI support databases other than SQLite for the ledger?
No. According to the source code in tashfeenahmed/freellmapi, the ledger implementation is tightly coupled to SQLite through the better-sqlite3 and node:sqlite drivers. There are no abstraction layers for PostgreSQL, MySQL, or other database engines in the current codebase.
Where is the FreeLLMAPI ledger database file located?
By default, FreeLLMAPI creates the SQLite database at server/data/freeapi.db relative to the project root. This path is resolved and passed to betterSqliteFactory() in server/src/db/index.ts, though developers can modify the configuration to use alternative locations or in-memory storage (:memory:) for testing.
What happens if the SQLite database becomes unavailable?
FreeLLMAPI implements a graceful degradation strategy. If the SQLite write fails in recordRequest(), the system falls back to in-memory tracking via pushMemoryRequest(). Similarly, providerDailyRequestCount() returns in-memory counts when countPersistedProviderRequests() returns undefined, ensuring rate limiting continues even during database outages.
Which tables store the rate limit data in FreeLLMAPI?
The primary ledger data resides in the rate_limit_usage table, which records every request and token consumption event with timestamps. The rate_limit_cooldowns table tracks provider-specific backoff periods. These tables are created and managed through migration scripts in the server/src/db/migrations/ directory.
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 →