How the FreeLLMAPI Model Catalog Sync Works: Signed Catalog Synchronization Explained
FreeLLMAPI synchronizes its local model catalog with an upstream signed catalog service through a cryptographically verified process that runs on a scheduled interval and supports offline re-application of cached catalogs.
The FreeLLMAPI model catalog sync is a security-critical background service that keeps your local deployment aligned with the latest available AI models. Located in server/src/services/catalog-sync.ts, this system fetches, verifies, and applies model definitions while preserving user customizations and ensuring zero-trust integrity through Ed25519 signatures.
Scheduler Initialization and Boot Sequence
When the FreeLLMAPI server starts, startCatalogSync() establishes the synchronization lifecycle.
The function performs three critical setup tasks:
- Registers a one-off timer (
BOOT_DELAY_MS) for the initial sync after startup - Schedules a recurring interval (
SYNC_INTERVAL_MS, approximately twice daily) - Immediately calls
reapplyCachedCatalog()to restore the last verified catalog from the local SQLitesettingstable
This dual-timer approach ensures rapid availability of models after boot while maintaining freshness through periodic updates.
// Start the background sync (usually called from server initialization)
import { startCatalogSync } from './services/catalog-sync.js';
import { scheduler } from '../lib/scheduler.js';
startCatalogSync(scheduler);
Source: server/src/services/catalog-sync.ts lines 33-45
Fetching the Catalog with Incremental Updates
The syncCatalog() function constructs authenticated requests to <base-url>/v1/latest with intelligent delta handling.
Request construction follows these rules:
- Premium authentication: When a license key exists, adds
Authorization: Bearer <key>header - Incremental fetch: Appends
?since=<applied_version>when a version is already applied (unlessforce=true) - Fresh fetch: Bypasses the
sinceparameter when forcing a full refresh
// Manually trigger a sync, e.g. after a user upgrades their license
import { syncCatalog } from './services/catalog-sync.js';
const result = await syncCatalog(true); // `force=true` ignores the `since` shortcut
console.log(result);
// {ok: true, action: 'applied', version: '2026.09.01', ...}
The since parameter enables bandwidth-efficient synchronization by allowing the server to return only changed portions of the catalog when the version hasn't advanced.
Source: lines 71-84
Cryptographic Signature Verification
Before any catalog data is processed, FreeLLMAPI enforces strict signature validation to prevent supply-chain attacks.
The verification flow in syncCatalog():
- Extracts the
x-catalog-signatureheader from the HTTP response - Reads the response body as raw bytes
- Verifies the signature against the pinned Ed25519 public key (
PINNED_CATALOG_PUBKEY) embedded in the binary
If verification fails, the entire response is discarded and the sync aborts. This signature-first security model ensures that even a compromised CDN cannot inject malicious model definitions, as the client only trusts content signed by the matching private key held by the upstream service.
Source: lines 94-99
Payload Validation and Schema Checking
After signature verification, the JSON payload undergoes strict validation through isCatalog().
The validator checks required structural fields:
version— catalog version stringtier— deployment tier identifiermodels— array of chat model definitionsquirks— model behavior overrides- Optional arrays:
embeddings,videoModels,mediaModels,transcriptionModels
Type checking ensures each field conforms to expected shapes before the sync proceeds. This prevents partially corrupted or malformed catalogs from affecting the database state.
Source: lines 100-150
Version Safety and Migration Protection
The FreeLLMAPI model catalog sync includes a safeguard against destructive rollbacks.
Before applying any catalog, the system compares catalog.version against MIN_CATALOG_VERSION — a hard-coded constant representing the bundled migration baseline. If the fetched catalog version is older than this minimum, the sync is skipped entirely.
This protection ensures that:
- Downgrade attacks via stale catalog delivery are blocked
- Database migrations always move forward
- Offline re-application of cached catalogs never regresses schema state
Source: lines 104-109
Atomic Catalog Application
When version or tier changes are detected, applyCatalog() executes within a single SQLite transaction to maintain consistency.
The application process handles multiple model categories:
| Model Type | Target Table | Special Handling |
|---|---|---|
| Chat models | models |
Respects user-owned rows, applies overrides |
| Image/audio | media_models |
Gated by MEDIA_PLATFORMS allow-list |
| Video | videoModels |
Gated by VIDEO_PLATFORMS allow-list |
| Transcription | transcriptionModels |
Gated by TRANSCRIPTION_PLATFORMS allow-list |
| Embeddings | embeddings |
Optional snapshot section |
Key application behaviors:
- User row protection: Rows with
source='user'are preserved and never overwritten or deleted - Tombstone awareness: Checks
catalog_model_tombstonesfor permanently retired models - Override handling: Applies
model_config_overridesandfallback_configrows - Profile consistency: Maintains relationships between user profiles and available models
- Stale row cleanup: Deletes catalog-managed rows (
source='catalog') that no longer appear in the new snapshot - Quirk replacement: Clears existing quirks and inserts the complete new set wholesale
Source: lines 57-66, 75-129, 140-250, 260-470
State Persistence and Caching
After successful application, the sync state is persisted to the settings table:
catalog_applied_version— the applied catalog versioncatalog_applied_tier— the deployment tiercatalog_applied_json— complete raw catalog JSON for offline use
Additional metadata is recorded:
lastSyncMs— timestamp of the sync attemptlastError— error message if the sync failed
This caching enables the offline re-application capability that makes FreeLLMAPI resilient to network outages.
Source: lines 114-130
License Status Refresh
Independently of catalog synchronization, refreshLicenseStatus() maintains premium entitlement state.
This function:
- Contacts
/v1/license/checkwhen a license key is configured - Updates cached license status in the database
- Logs failures without aborting the catalog sync
The separation of concerns allows model availability to proceed even when license verification is temporarily unavailable.
Source: lines 44-63
Offline Re-Application via Cached Catalogs
The reapplyCachedCatalog() function provides deterministic recovery for server restarts.
Execution flow:
- Reads
catalog_applied_jsonfrom thesettingstable - Re-validates the cached payload with
isCatalog() - Executes
applyCatalog()without any network traffic
This guarantees that the local database reflects the last known-good catalog state even when the server boots without internet connectivity. The re-validation step ensures data integrity against disk corruption or manual tampering.
Source: lines 95-108
Querying Sync State
The getSyncState() function exposes current synchronization status for monitoring and UI purposes.
// Query the current sync state (useful for UI)
import { getSyncState } from './services/catalog-sync.js';
const state = getSyncState();
console.log(state);
/*
{
baseUrl: 'https://api.freellmapi.co',
appliedVersion: '2026.09.01',
appliedTier: 'live',
lastSyncMs: 1725112000000,
lastError: ''
}
*/
This enables dashboards to display synchronization health, applied catalog versions, and error conditions to administrators.
Key Architectural Files
| File | Role |
|---|---|
server/src/services/catalog-sync.ts |
Core implementation: fetching, verifying, applying, and caching |
server/src/services/model-state.ts |
Tombstone handling, overrides, and retired model reinstatement |
server/src/services/media.ts |
Platform allow-lists (MEDIA_PLATFORMS, VIDEO_PLATFORMS, TRANSCRIPTION_PLATFORMS) |
server/src/db/index.js |
SQLite helpers (getDb, getSetting, setSetting) |
shared/types.ts |
Shared type definitions including Platform |
Summary
- FreeLLMAPI model catalog sync is driven by
catalog-sync.tswith scheduled and on-demand execution modes - Ed25519 signature verification provides zero-trust integrity before any data is processed
- Incremental updates via the
sinceparameter reduce bandwidth;force=trueenables full refresh - Migration protection via
MIN_CATALOG_VERSIONprevents destructive catalog rollbacks - Atomic SQLite transactions ensure consistent application across chat, media, video, transcription, and embedding models
- Source-of-truth handling preserves user-owned rows and respects tombstones
- Offline resilience through cached catalog re-application on every boot
Frequently Asked Questions
How often does FreeLLMAPI sync the model catalog?
The sync runs approximately twice daily via SYNC_INTERVAL_MS, plus an immediate attempt after BOOT_DELAY_MS on server startup. Administrators can trigger manual syncs with syncCatalog(true) at any time.
What happens if the catalog signature verification fails?
The entire response is discarded immediately. No database changes occur, and the error is recorded in lastError. The system continues operating with the previously applied (or re-applied cached) catalog until a valid signed response is received.
Can FreeLLMAPI work without internet connectivity?
Yes. On every boot, reapplyCachedCatalog() validates and re-applies the last known-good catalog from local SQLite storage without network access. Models that were available before disconnection remain functional.
How does FreeLLMAPI handle user-customized model configurations?
User-owned rows (source='user') are preserved across all syncs. They take precedence over catalog definitions on collision and are never deleted by the synchronization process. The catalog_model_tombstones table separately tracks permanently retired upstream models.
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 →