Guide 02. By Nicolas Dao

The LLM streaming proxy

How do I add an AI chat feature without leaking my API key or paying for the model's thinking time?

Never call an LLM from the browser. A Worker holds the key, checks the user's budget and streams tokens back. Waiting costs nothing on Workers.

The problem

If the browser calls OpenRouter directly, your API key has to be in the app. Anyone can open DevTools, copy it and run up your bill, and you can't limit what each user does.

The fix

Browser ──(user's login token)──▶ Worker ──(your OpenRouter key)──▶ OpenRouter
        ◀──── tokens streamed back word by word ◀────────────────

The Worker:

  1. checks the user is logged in (a Cognito JWT works);
  2. checks that user's quota or budget ("50 messages a day", "$2 a month");
  3. adds your key on the server side, so it never reaches the browser;
  4. streams the answer back as it's generated;
  5. records token usage for billing or analytics.

Why a Worker

The proxy does about 2 ms of work, then waits 10–60 seconds while the model writes.

1M chats a month × 20 s Monthly
Classic Lambda $33.50 (128 MB) to $167 (512 MB)
Lambda Web Functions ~$3.40 (not in Sydney yet)
Cloudflare Workers ~$0 extra, inside the $5 plan

On Lambda you pay memory × wall-clock time for the waiting, and response streaming through a function URL doesn't work inside a VPC. Workers bill CPU time only.

Add Cloudflare AI Gateway in front of OpenRouter for caching, per-client spend caps and fallback when a provider is down.

Want this stack in your AWS account?

Cloudless Labs is a Sydney consultancy. We migrate on-premises systems to AWS, build serverless apps on this stack, and coach teams to ship with Claude Code and Codex.

Contact Us

For general inquiries, please contact us at:

For e-learning capabilities, please contact: