In-memory frame cache
At startup, Hagaki loads all frame overlay images from../asset/private/frame/ into a HashMap<String, DynamicImage> wrapped in an Arc. This map is shared across all request handlers via an Axum extension.
Properties:
- Loaded once at startup — no per-request disk I/O for frame assets.
- Shared across all concurrent requests without cloning the images.
- Never evicted — frame assets remain in memory for the lifetime of the process.
- If you add or replace frame image files on disk, you must restart the service for the changes to take effect.
Disk cache
The disk cache is opt-in. To enable it for a render, include asave_name field in the payload.
How it works
Check for a cached file
When a request arrives and If the file exists, its contents are read and returned immediately. The response header
save_name is set, Hagaki checks for an existing file at:X-Source is set to loaded from disk cache.Render and save
If no cached file is found, Hagaki renders the image normally. After a successful render, the PNG is written to:The response header
X-Source is set to rendered on request.Cache path
The disk cache directory is fixed at../asset/public/render/ relative to the Hagaki binary. The full path for a cached file is:
save_name format
Hagaki writes the file exactly as named — it does not append an extension. If you want a .png extension in the saved filename, include it in save_name:
Content-Type: image/png regardless.
No automatic invalidation
The disk cache has no TTL and no automatic eviction. Files persist until you delete them manually. To force a re-render for a givensave_name, delete the corresponding file from ../asset/public/render/.
Response headers
Every response includes two observability headers:| Header | Values | Description |
|---|---|---|
X-Source | rendered on request | loaded from disk cache | Indicates whether the response was freshly rendered or served from the disk cache. |
X-Processing-Time | e.g. 12.345ms | Wall-clock time taken to produce the response, in milliseconds. |
X-Source: loaded from disk cache and a very low X-Processing-Time (typically under 1 ms for small files).
Reproducibility and HTTP caching
Because the hash fully encodes all render parameters, the same hash always produces the same image. This makes Hagaki naturally compatible with HTTP-level caching upstream of the service. You can configure Nginxproxy_cache to cache responses keyed on the request URL. When a hash is seen again, Nginx serves the cached PNG directly without the request ever reaching Hagaki.
Combining disk cache and Nginx cache
The two caching layers serve different purposes and work well together:| Layer | Scope | Eviction | Best for |
|---|---|---|---|
Disk cache (save_name) | Selected renders only | Manual | Long-lived renders you want to persist across Hagaki restarts |
Nginx proxy_cache | All responses | TTL-based | Reducing request load without modifying render payloads |
save_name disk cache is useful when you want persistence across Hagaki process restarts or when you need the cached file to be accessible as a static asset from the public/render/ directory.