Caching Strategy
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The FOSSBilling API utilizes a multi-layered caching strategy designed to maximize performance, respect upstream rate limits (specifically GitHub API), and ensure high availability through stale-data delivery during upstream failures. The system is built on Hono and employs platform-agnostic interfaces to allow deployment across different runtimes, such as Cloudflare Workers or Node.js environments.
The primary goals of the caching system are to store expensive GitHub API responses, provide rapid access to release statistics, and secure sensitive authentication tokens used for administrative cache refreshes. By separating the platform layer from application logic, the project maintains consistent caching behavior regardless of the underlying storage implementation.
Sources: README.md:12-14, AGENTS.md:6-10, src/services/versions/v1/index.ts:31-35
Core Components and Adapters
The caching architecture is divided into a high-level interface (ICache) and specific adapter implementations. This allows the application logic to interact with cache storage without needing to know the technical details of the environment.
Cache Interface and Adapters
The platform layer defines how data is stored and retrieved. In production (Cloudflare), the system uses KV (Key-Value) namespaces. For local development or alternative environments, a Node.js adapter using SQLite is provided.
| Component | Implementation | Purpose |
|---|---|---|
CloudflareKVAdapter | Cloudflare KV | Production-grade persistent storage for releases and auth tokens. |
SQLiteCacheAdapter | Node.js / SQLite | In-memory or file-based caching for testing and non-Cloudflare environments. |
publicCacheKey | URL Normalization | Helper to normalize keys by removing query strings and fragments. |
Sources: src/lib/adapters/cloudflare/cache.ts, src/lib/adapters/node/cache.ts, src/lib/cache.ts:3-10, AGENTS.md:8-10
Cache Data Flow
The following diagram illustrates how the application decides between serving cached data or fetching fresh data from an upstream source.
Service-Specific Caching
Versions Service
The Versions Service (/versions/v1) caches GitHub release data to prevent hitting API rate limits. It uses a 24-hour TTL for the primary release list and employs a "stale-while-error" pattern. If GitHub is unreachable, the system attempts to parse and serve the last known good version from the cache.
- Cache Key:
gh-fossbilling-releases - TTL: 86,400 seconds (24 hours)
- Update Mechanism: An authenticated
/updateendpoint allows manual cache invalidation and fresh fetching.
Sources: src/services/versions/v1/index.ts:26-30, src/services/versions/v1/index.ts:107-150
Stats Service
The Stats Service caches aggregated statistics derived from the Versions Service. This prevents the need to re-aggregate complex data (like release sizes or PHP version trends) on every request.
- Cache Key:
fossbilling-stats-data - TTL: 86,400 seconds (24 hours)
- Source Data: Reuses the cached release data from the Versions Service to perform its calculations.
Sources: src/services/stats/v1/index.ts:18-21, src/services/stats/v1/index.ts:153-160, AGENTS.md:54-55
Authentication Token Caching
The API uses a specialized internal cache for the UPDATE_TOKEN to minimize KV lookups for administrative requests.
Cache Configuration and Constants
The following table summarizes the constants used to control caching behavior across the system.
| Constant | Value | Description |
|---|---|---|
RELEASE_CACHE_TTL | 86400 | TTL for GitHub release data in seconds. |
RELEASES_CACHE_CONTROL | "max-age: 86400" | HTTP Header sent to clients for browser/CDN caching. |
STATS_CACHE_TTL | 86400 | TTL for aggregated stats data. |
UPDATE_TOKEN_CACHE_TTL_MS | 60000 | Internal memory TTL for the update bearer token in milliseconds. |
Sources: src/services/versions/v1/index.ts:26-39, src/services/stats/v1/index.ts:18-21
Key Implementation Details
GitHub API Error Handling and Stale Data
When getReleases is called, it first checks the cache. If an update is required but the GitHub API request fails (e.g., RateLimitError or AuthError), the function catches the error, logs a warning, and attempts to serve the "stale" version from the cache if it exists. Responses served this way include a stale: true flag in the JSON metadata.
Sources: src/services/versions/v1/index.ts:340-370, README.md:32-34
Memory Cache Synchronization
To handle high-traffic scenarios, the UPDATE_TOKEN is cached in a local variable updateTokenCache with a 60-second expiration. This prevents repeated network calls to the AUTH_KV namespace for every request to the /update endpoint.
Sources: src/services/versions/v1/index.ts:41-58
Conclusion
The FOSSBilling API caching strategy provides a robust balance between data freshness and system resilience. By utilizing Cloudflare KV for persistent storage and short-term memory caching for configuration, the API minimizes latency and provides a reliable fallback mechanism during upstream disruptions. The implementation remains portable across runtimes thanks to a strict adapter-based architecture.