Skip to main content

Supported origins

All origin access goes through a single OriginStore trait implementation per backend type.
OriginAuthNotes
AWS S3IAM credentials or pre-signed URLsMost common
Cloudflare R2S3-compatible APINo egress fees between R2 and Workers
Backblaze B2S3-compatible APICheapest egress (~$0.01/GB)
MinIO (self-hosted)S3-compatible APIFull operator control
NFSFilesystem accessNo egress fees; local or network mount
Local diskFilesystem accessSingle-machine only
Your node binary already includes adapters for these. You configure which backend and how to authenticate, not how to talk to it.

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:
catalog: hash → { bucket, key, size_bytes, content_type }
A PostgreSQL table or a SQLite file both work. It is not on-chain — it’s an operational concern.

Minimal schema

CREATE TABLE catalog (
    hash          BYTEA PRIMARY KEY,   -- 32-byte BLAKE3 root
    bucket        TEXT NOT NULL,
    object_key    TEXT NOT NULL,
    size_bytes    BIGINT NOT NULL,
    content_type  TEXT,
    ingested_at   TIMESTAMPTZ DEFAULT now()
);
Origin-backed nodes query this on cache miss to locate the pull URL.

Ingest pipeline

Your ingest job should:
  1. Compute the BLAKE3 hash of the object as it’s uploaded to your backend. iroh-blobs exposes a streaming hasher — feed it during upload.
  2. Insert (hash, bucket, object_key, size_bytes, content_type) into the catalog.
  3. Broadcast the hash to whoever needs to play the content (clients, app server for key delivery).
The hash is the only content identifier the CDN exposes. Clients ask for blobs by hash; your app (if you have an app server) provides the hash to clients as part of a playback manifest.

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:
ModeSettingBehavior
Pull-through (default)pull_through: truePeer asks origin node on miss; origin streams while pulling; caches locally
Redirectpull_through: falsePeer returns a redirect to the origin node’s NodeId; client opens a direct channel
Pull-through is preferred — it caches bytes at the intermediate node for subsequent clients. Redirect is useful if you explicitly want all delivery to come from your node (no peer caching) — e.g., for legal or operational control.

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 origin
  • decdn_origin_fetch_bytes_total — bytes pulled from origin
  • decdn_origin_fetch_errors_total{type="not_found"|"auth"|"timeout"} — origin failures
These are on top of the standard node metrics in observability.