Three ways to serve a public avatar

  1. Private only

    Railway Storage Buckets

    S3-compatible and cheap, but buckets are private. Public delivery means presigned URLs or proxying every image through the backend.

  2. Needs DNS on Cloudflare

    Cloudflare R2

    Production caching needs a custom domain in a Cloudflare zone. Partial CNAME setup is Business or Enterprise only, and r2.dev is for development.

  3. Public CDN, no DNS change

    Sanity image assets

    Upload once through an authenticated backend. Sanity stores the asset, transforms it on request, and serves it from cdn.sanity.io.

The final flow

Writeauthenticated, once per image
  1. Browser
  2. App backend
  3. Sanity Content Lake
Readevery render, every size
  1. Browser
  2. cdn.sanity.io
The backend is on the write path only. After upload, no image byte passes through it.
  • The backend authenticates, checks type, size, and magic bytes, enforces quotas, then calls Sanity with a server-only token.
  • The app stores an AssetLake image id, not a URL. Presets in Sanity turn that id into transform URLs at render time.
  • Browsers request those URLs from cdn.sanity.io. The app origin serves zero image bytes.

Known limitations

Public images only. A Sanity image asset is readable by anyone who has its URL, so AssetLake is for avatars, covers, and other images meant to be seen.

  1. Public images only. Standard Content Lake assets are not private.
  2. Not S3-compatible. AssetLake is an image service abstraction, not an S3 protocol endpoint.
  3. No custom asset domain by default. Images use cdn.sanity.io; custom asset domains are an Enterprise add-on.
  4. Deletion is not instant revocation. CDN caches may keep serving a previously cached image for a while.
  5. Different cost profile. Sanity is chosen for storage, transforms, and delivery together, not for the lowest raw storage price.
  6. Workflows is early access. The review workflow is optional and not part of this demo's core path.
  7. Review is not confidentiality. Putting an image in review does not hide an asset URL that already exists.
  8. Images only. There is no generic file or video pipeline.
  9. No anonymous uploads. The demo needs a passcode session, and quotas cap uploads per session and per day.
  10. No invented analytics. Pages show only data that Sanity documents or APIs actually return.