Supported origins
All origin access goes through a singleOriginStore trait implementation per backend type.
| Origin | Auth | Notes |
|---|---|---|
| AWS S3 | IAM credentials or pre-signed URLs | Most common |
| Cloudflare R2 | S3-compatible API | No egress fees between R2 and Workers |
| Backblaze B2 | S3-compatible API | Cheapest egress (~$0.01/GB) |
| MinIO (self-hosted) | S3-compatible API | Full operator control |
| NFS | Filesystem access | No egress fees; local or network mount |
| Local disk | Filesystem access | Single-machine only |
The hash-to-object-key catalog
Your backend speaks object keys (media/2026/04/foo.mp4). The CDN speaks BLAKE3 hashes. You maintain a small database mapping one to the other:
Minimal schema
Ingest pipeline
Your ingest job should:- Compute the BLAKE3 hash of the object as it’s uploaded to your backend. iroh-blobs exposes a streaming hasher — feed it during upload.
- Insert
(hash, bucket, object_key, size_bytes, content_type)into the catalog. - Broadcast the hash to whoever needs to play the content (clients, app server for key delivery).
Storage and durability
deCDN does not replace your origin’s durability. The CDN caches bytes; your bucket is the source of truth. Recommended posture:- S3 Standard or equivalent (11 nines durability).
- Lifecycle rules to keep hot content in hot tiers; cold tiers are fine for long-tail.
- Region matching your origin-backed node’s region to avoid cross-region backend egress.
Pull-through vs redirect
Two modes on origin-backed nodes:| Mode | Setting | Behavior |
|---|---|---|
| Pull-through (default) | pull_through: true | Peer asks origin node on miss; origin streams while pulling; caches locally |
| Redirect | pull_through: false | Peer returns a redirect to the origin node’s NodeId; client opens a direct channel |
max_blob_size
Per-node policy. Recommended default is 10 GB. Nodes reject requests for blobs larger than this with StreamError::BlobTooLarge. Adjust based on your content — streaming video segments rarely exceed a few hundred MB; large downloads may need a higher limit.
Observability hooks
Origin-backed nodes should expose, at minimum:decdn_origin_fetch_total{backend="s3"}— cache misses that fell through to origindecdn_origin_fetch_bytes_total— bytes pulled from origindecdn_origin_fetch_errors_total{type="not_found"|"auth"|"timeout"}— origin failures