Skip to content

Release downloads stream through the smart-placed Worker (SJC) with no edge cache: slow and erratic far from it #580

Description

@xxchan

What happens

Hosted release downloads (GET /dl/:slug/releases/:releaseId/:file, and the channel latest route) are streamed through the Worker from R2 (serveHostedAsset → APK_BUCKET.get). The Worker runs with "placement": { "mode": "smart" } (worker/wrangler.hands.jsonc), which places it near D1, in San Jose, so every byte of a download flows R2 → SJC Worker → client. Nothing caches it at the edge: the response has cache-control: public, max-age=31536000, immutable but no cf-cache-status, since a Worker's response doesn't populate the CDN cache.

$ curl -sI https://hands.build/dl/ferry-cli/releases/633a9164-619f-43e8-8732-901a59f75efb/darwin-arm64.gz
cache-control: public, max-age=31536000, immutable
cf-placement: remote-SJC

Impact

From Asia (Beijing, 2026-09-30), the same 43 MB ferry-cli download ran at very different speeds depending on the route, all through the SJC Worker:

When Direct Via a local proxy
16:50 CST ~96 KB/s ~730 KB/s
17:40 CST ~3.2 MB/s ~170 KB/s

A remote Ferry update of a Mac spent ~6 minutes on this download, and the next one ~4 minutes. ferry-installer did nothing wrong: it saw only a slow stream.

Suggestions

Any of these would serve the bytes from near the client:

  • Put hosted-asset responses in the edge cache with the Cache API (caches.default), keyed on the immutable release URL. The bytes are immutable per release id, so there's nothing to invalidate.
  • Redirect (302) to a cacheable R2 public or custom-domain URL, or a presigned GET, after the D1 lookup. The redirect stays tiny, even from SJC.
  • Keep smart placement for API routes but not /dl/*, for example by splitting the download route into its own Worker without placement.

Reported from botiverse/ferry, whose installer and remote updates download through these routes.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions