Skip to main content

Proxy Fetch

Make external API calls from Durable Objects without paying for wall-clock time. @lumenize/proxy-fetch offloads HTTP fetches to Workers (CPU billing) via Cloudflare Queues or a shared DO, stopping the accrual of wall clock time charges while waiting for responses.

The Problem

Durable Objects are billed on wall clock time, not CPU time. When a DO makes an external fetch() call:

  • DO wall clock billing continues during the fetch (awaiting external response)
  • For slow external APIs (100ms-5s response times), costs add up quickly

Example Cost Scenario:

100,000 fetches/day × 200ms avg = 20,000 seconds/day per instance
Over 30 days => 600,000 seconds => 167 hours/month wall clock time per instance
1,000 instances => 167,000 hours/month
@ ~$0.006 per hour
======================================================================
~$1000/month waiting on external APIs

Note: The above cost calculations do not take into account the additional requests charges incurred when using @lumenize/proxy-fetch. Those are smaller in comparison, but not zero.

The Solution

Key Insight: Cloudflare Workers are billed on CPU time, not wall clock time (Proxy Fetch Queue variant)! Similarly, the wall clock charges of running one DO 24/7 to serve the fetch needs of 1,000 DOs is only ~$4/month (other Proxy Fetch variants)!

By satisfying external fetches somewhere else (Worker or shared DO):

  • ✅ DO wall clock billing stops as soon as fetch is queued
  • ✅ Worker makes fetch with CPU billing or shared DO that is running 24/7
  • ✅ Response delivered back to DO via Workers RPC

How It Works

Variants

The @lumenize/proxy-fetch package provides four different approaches to making external API calls from Durable Objects:

Queue

Route fetch requests through Cloudflare Queues to Workers with CPU billing. Best for high-volume use cases where you can live with high latency penalty. Currently available.

Durable Object

Use a dedicated proxy DO to handle fetches. Simpler. Low latency penalty. Max throughput is 1,000 DOs doing 100,000 fetches per day each steady state. Divide by 10 if burst throughput is 10x mean throughput. Currently available.

Streaming

Stream large responses back to your DO. Coming soon.

Agents

Proxy SSE MCP and LLM stutter-speak responses back to DO. Coming soon.

Variant Comparison

FeatureDO VariantQueue Variant
Latency~50-100ms200ms-3s (p90)
Throughput~100k req/day per DOCloud-scale
ConfigurationProxyFetchDO bindingQueue binding
Billing~$4/month (1 DO 24/7) + 3x req count2x req count
Function to callproxyFetch() or proxyFetchDO()proxyFetch() or proxyFetchQueue()

All variants share the same API for error handling, fire-and-forget mode, and request patterns. See the Queue variant docs for complete guidance and examples.