Image optimization CDN
A read-only optimizing proxy in front of images you already host. This page describes exactly what it does, including where it deliberately does nothing.
The URL contract
GET https://cdn.picsoar.com/v1/:projectKey/:preset/*sourcePath?v=assetHash
HEAD https://cdn.picsoar.com/v1/:projectKey/:preset/*sourcePath?v=assetHashA concrete example:
https://cdn.picsoar.com/v1/prj_01H8XKQ2M7N4P5R6S7T8V9W0XY/card/products/shoe.jpg?v=8f2c1aWhy there is no width parameter
A URL that accepts ?width= accepts a million widths. Every distinct value is a transformation you pay for and a cache entry that displaces something useful. One visitor with a loop can run up your bill. Presets bound that: the set of derivatives per source image is a small constant that you control.
The only query parameter we accept is v, a cache-busting token you choose. Any other parameter is rejected, not ignored — ignoring it would recreate the same unbounded-cardinality problem one redirect later.
Built-in presets
| Preset | Width | Behaviour |
|---|---|---|
original-safe | unchanged | Format negotiation and recompression only. Never changes geometry, so it is safe to adopt without auditing your layout. |
thumbnail | 320px | Scale-down, light sharpening. |
card | 640px | Scale-down, light sharpening. |
content | 1280px | Scale-down. |
hero | 1920px | Scale-down. |
Presets never scale an image up. All built-ins use scale-down fit, so a 400px source requested through hero stays 400px.
Every failure path, and what a visitor sees
| Situation | Response | Why |
|---|---|---|
| Client does not accept WebP | Original file, 200 | Capability is a fact; our preference is not. |
| Transformation fails | Original file, 200 | A larger image beats a hole in the page. Configurable per project. |
| Source missing at your origin | 404 | Preserved verbatim, so you can debug a missing asset. |
| Your origin returns 5xx | 502 | Reported as an upstream failure, not as ours. It does not consume our availability SLO. |
| Origin serves a non-image content type | 502 | We refuse to put unvetted bytes on our CDN hostname. |
| Source is larger than 20 MB | Original file, 200 | Passed through rather than decoded. Decompression bombs are cheap to send and expensive to open. |
| Monthly allowance exhausted | Original file, 200 | Running out of quota degrades optimization. It does not break your site. |
| Origin redirects off-host | 502 | Redirects are only followed within your verified origin. Register the final host instead. |
Caching
A derivative is cached under a key built from the project, the cache epoch, the presetand its version, the negotiated output format, the version token, and the canonical source path. Two requests that mean the same image produce the same key; nothing a visitor can vary — header casing, tracking parameters, encoding tricks — reaches it.
Requests carrying ?v= are marked immutable and cached for a year. Without a token we cache for five minutes at the browser and an hour at the edge, because we cannot promise on your behalf that the bytes at that path will not change.
Frequently asked
- Do you modify or replace my original files?
- No. The delivery pipeline only issues GET and HEAD requests against your origin. There is no write path, no import step, and no credential that would allow one.
- What happens if a transformation fails?
- By default we serve your original file. The visitor gets a larger image rather than a broken one. You can opt into surfacing the failure instead, per project.
- What does a browser without WebP support receive?
- The original file, in its original format. We decide from the Accept header, so a client that did not declare WebP support never receives WebP — including proxies, link previewers, and old email clients.
- Can I request arbitrary widths or quality settings?
- No, and that is deliberate. Public URLs name a server-owned preset. Unbounded parameters would let any visitor mint unlimited derivatives, which is a cost attack against you and a cache-pollution problem for everyone.
- How do I invalidate a cached derivative?
- Add a version token to the URL when the bytes change, or purge the whole project from the dashboard. A purge is a single counter increment, so it is instant regardless of how many images you have.
More detail — including the cache-key specification and the threat model — is in thedocumentation.