Presets & Caching
Two concerns that sit behind the resize and format parameters: giving a recurring combination a name, and making sure the second request for it costs nothing.
Named Presets
A preset bundles width, height, fit, quality and format under one name. It is operator configuration — a JSON object in an environment variable, not app schema — because the right thumbnail size is a property of the deployment, not of the business domain.
STORAGE_TRANSFORM_PRESETS='{
"thumbnail": { "width": 150, "height": 150, "fit": "inside" },
"preview": { "width": 600, "quality": 80 },
"avatar": { "width": 64, "height": 64, "fit": "inside" }
}'GET /api/buckets/photos/files/{key}?preset=avatar
GET /api/buckets/photos/files/{key}?preset=thumbnail&quality=95| Situation | Result |
|---|---|
| Known preset | Its fields become the transform. |
| Explicit parameter alongside a preset | The explicit value wins, field by field. |
| Unknown preset name | 400 |
?preset= with none configured |
400, with a message saying so. |
Overrides are per-field, not all-or-nothing: ?preset=thumbnail&quality=95 keeps the preset's 150×150 inside and changes only the quality.
Preset names must be alphanumeric with single hyphens (thumbnail, hero-banner), which keeps them safe to put in a URL. Malformed JSON, a non-object value, an illegal name, or a preset declaring the withdrawn crop key fails the server at startup rather than at the first request — a typo in this variable is found on deploy, not by a user.
The crop key is refused rather than ignored on purpose. Unknown keys used to be dropped without comment, so a preset carrying crop would have kept booting while quietly no longer cropping — see Resize & Fit for why the capability was withdrawn.
Caching
A transform runs once per distinct combination. The result is held in a process-local LRU cache keyed by the storage key, the transform parameters, and the negotiated format together.
| Mechanism | Behaviour |
|---|---|
Cache-Control |
public, max-age=31536000, immutable — one year, never revalidated. |
ETag |
Derived from the source file plus the transform parameters. |
If-None-Match |
A match returns 304 Not Modified. |
| Server cache | In-memory LRU, evicting least-recently-used entries when it is full. |
| Invalidation | Deleting a file evicts every transform derived from its key. |
| Variable | Default | Meaning |
|---|---|---|
STORAGE_TRANSFORM_CACHE_MAX_SIZE |
256 |
Cache ceiling, in megabytes. |
An entry larger than the whole cap is served but never retained — it would evict everything else to fit.
The cache lives in the process, not on disk. It is empty after every restart and it is not shared between instances, so a multi-process deployment holds one copy per process and warms each independently. That is fine because the CDN-facing Cache-Control is a year: the browser and any edge cache absorb the repeat traffic, and this cache only has to absorb the first request per process.
The one-year immutable header is safe precisely because keys are content-addressed — a stored key is <uuid>-<filename>, so a replaced file is a new key and a new URL. Nothing is ever served stale under a URL whose content changed, because that situation cannot arise.
Originals Are Never Touched
| Guarantee | Behaviour |
|---|---|
| Source bytes | Byte-identical after any number of transform requests. |
| A request with no parameters | The original, subject only to Accept negotiation. |
?format=origin |
The original bytes verbatim, negotiation bypassed. |
| Clearing the cache | Discards derived variants only; originals stay fully available. |
| Non-image files | Transform parameters answer 400 — nothing is attempted. |
Transforms are derived, disposable, and reproducible: the cache can be dropped at any moment and the next request rebuilds it. Admins can do exactly that with DELETE /api/admin/storage/transform-cache.
Recognised image types are those Sovrium can infer from the key's extension: PNG, JPEG, GIF, WebP, AVIF, SVG and ICO. SVG passes through rather than being rasterised, and is always served as an attachment — see Upload Security.
Related Pages
- Resize & Fit — the parameters a preset bundles.
- Format & Quality — format negotiation and compression.
- File Operations — the endpoint serving cached results.
- Lifecycle & Quotas — the originals a transform reads from.
- Environment Variables: Services — preset and cache configuration.
Last updated September 1, 2026
This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta. Contributions and corrections are welcome.