---
title: "14 — AI Gateway and Email Workers: Two Specialized Edge Layers"
uid: ai-gateway-email-workers
tags: ["observability", "llm-routing", "email-routing", "cloudflare", "roadmap:cloudflare", "email-workers", "ai-gateway"]
excerpt: "AI Gateway is a control plane in front of AI providers; Email Workers is compute for incoming email. Different problems, same shape: a Worker in front of traffic applying logic."
date: 2026-08-13T03:28:16+0000
source: https://www.aveshina.my.id/en/blog/ai-gateway-email-workers
---

Two products I kept filing under "miscellaneous edge features" — AI Gateway and Email Workers — have nothing to do with each other, which is exactly why conflating them hid both. Pulled apart, each is a focused layer for a specific kind of traffic: **AI Gateway is a control plane in front of AI providers, and Email Workers is a compute layer for incoming email.** [1][2] Different problems, same shape — a Worker sits in front of some traffic and applies logic to it.

The framing that landed is what each one is _not_. AI Gateway is not where models run (that's Workers AI); it's the layer between my code and wherever the models _do_ run, including external providers. Email Workers is not an email server I host; it's a hook into Cloudflare's email routing that lets a Worker intercept and act on mail addressed to my domain.

## AI Gateway: control over AI traffic

When an application calls an AI provider — OpenAI, Anthropic, Hugging Face, even Workers AI — the default experience is a direct HTTP call from my code to the provider's API. That works, but it leaves me with no control over the traffic. AI Gateway inserts itself as a layer between my code and the provider(s), and the value is entirely in what that layer can do [1][3]:

- **Caching.** Identical prompts return cached results instead of re-calling the provider. For non-deterministic workloads this is huge — repeat queries cost nothing and return instantly.
- **Rate limiting.** Cap requests per second to a provider, so a bug or a traffic spike doesn't blow through an API quota or budget.
- **Observability.** Logs and metrics on every request — which model, what latency, what cost, what status. The traffic that was previously opaque becomes queryable.
- **Routing and fallback.** Send requests to one provider, fall back to another on failure, or load-balance across providers. Reduces single-provider lock-in at the runtime layer.

The model that clicked: AI Gateway is to AI calls what an API gateway is to any API traffic. It's the place where cross-cutting concerns (cache, limit, observe, route) live, so my application code is just "produce a prompt, send it, get a result" and the policy is centralized.

```figure
<svg viewBox="0 0 740 280" xmlns="http://www.w3.org/2000/svg" class="my-6 w-full max-w-2xl" role="img" aria-label="AI Gateway between application code and AI providers. On the left, the app calls the gateway. In the middle, the gateway applies cache, rate limit, observability, and routing rules. On the right, requests fan out to multiple providers (Workers AI, OpenAI, Anthropic, etc.) with fallback.">
  <defs>
    <marker id="agarrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="7" markerHeight="7" orient="auto">
      <path d="M0,0 L10,5 L0,10 z" fill="#64748b"/>
    </marker>
  </defs>
  <g font-family="ui-sans-serif, system-ui, sans-serif" text-rendering="geometricPrecision">

    <!-- app -->
    <rect x="20" y="110" width="100" height="50" rx="8" fill="#e0e7ff" stroke="#6366f1" stroke-width="1.5"/>
    <text x="70" y="132" font-size="11" font-weight="700" fill="#1e1b4b" text-anchor="middle">app code</text>
    <text x="70" y="148" font-size="9" fill="#475569" text-anchor="middle">produce prompt</text>

    <!-- gateway -->
    <rect x="200" y="70" width="280" height="140" rx="10" fill="#dcfce7" stroke="#16a34a" stroke-width="2"/>
    <text x="340" y="92" font-size="12" font-weight="700" fill="#052e16" text-anchor="middle">AI Gateway</text>

    <rect x="215" y="105" width="115" height="28" rx="4" fill="#fef9c3" stroke="#ca8a04"/>
    <text x="272" y="123" font-size="9" font-weight="700" fill="#422006" text-anchor="middle">cache identical prompts</text>
    <rect x="350" y="105" width="115" height="28" rx="4" fill="#fef9c3" stroke="#ca8a04"/>
    <text x="407" y="123" font-size="9" font-weight="700" fill="#422006" text-anchor="middle">rate limit / budget</text>
    <rect x="215" y="140" width="115" height="28" rx="4" fill="#fef9c3" stroke="#ca8a04"/>
    <text x="272" y="158" font-size="9" font-weight="700" fill="#422006" text-anchor="middle">logs + metrics</text>
    <rect x="350" y="140" width="115" height="28" rx="4" fill="#fef9c3" stroke="#ca8a04"/>
    <text x="407" y="158" font-size="9" font-weight="700" fill="#422006" text-anchor="middle">route + fallback</text>
    <text x="340" y="190" font-size="9" font-style="italic" fill="#052e16" text-anchor="middle">policy lives here, not in app code</text>

    <!-- providers -->
    <rect x="560" y="60" width="140" height="32" rx="6" fill="#fce7f3" stroke="#db2777"/>
    <text x="630" y="80" font-size="10" font-weight="700" fill="#500724" text-anchor="middle">Workers AI</text>
    <rect x="560" y="105" width="140" height="32" rx="6" fill="#fce7f3" stroke="#db2777"/>
    <text x="630" y="125" font-size="10" font-weight="700" fill="#500724" text-anchor="middle">OpenAI</text>
    <rect x="560" y="150" width="140" height="32" rx="6" fill="#fce7f3" stroke="#db2777"/>
    <text x="630" y="170" font-size="10" font-weight="700" fill="#500724" text-anchor="middle">Anthropic</text>
    <rect x="560" y="195" width="140" height="32" rx="6" fill="#fce7f3" stroke="#db2777"/>
    <text x="630" y="215" font-size="10" font-weight="700" fill="#500724" text-anchor="middle">others…</text>

    <path d="M120,135 L198,135" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#agarrow)"/>
    <path d="M480,90 L558,76" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#agarrow)"/>
    <path d="M480,120 L558,121" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#agarrow)"/>
    <path d="M480,160 L558,166" fill="none" stroke="#64748b" stroke-width="1.5" marker-end="url(#agarrow)"/>
    <path d="M480,180 L558,205" fill="none" stroke="#64748b" stroke-width="1.5" stroke-dasharray="3,2" marker-end="url(#agarrow)"/>

    <text x="370" y="252" font-size="10" font-style="italic" fill="#64748b" text-anchor="middle">the gateway is where cross-cutting AI-traffic concerns live</text>
    <text x="370" y="270" font-size="10" font-style="italic" fill="#64748b" text-anchor="middle">cache + limit + observe + route — without changing app code</text>
  </g>
</svg>
```

The distinction from Workers AI is worth restating, because it's easy to conflate. Workers AI _runs_ models at the edge. AI Gateway _manages traffic to_ models, wherever they run — including Workers AI, including external providers. They compose: I can put an AI Gateway in front of Workers AI to get caching and observability on those calls too. Workers AI is the compute; AI Gateway is the policy layer.

## Email Workers: code on incoming mail

Email Workers is the email equivalent of an HTTP Worker — instead of intercepting an HTTP request, it intercepts an incoming email addressed to a domain I control [2][4]. The email arrives at Cloudflare's mail routing; instead of (or in addition to) forwarding it to a mailbox, Cloudflare runs my Worker against it.

The capabilities the Worker has, mapped to the three layers in the reference [5][6][7]:

### Routing

The Worker decides where the email goes [5]. Based on the sender, recipient, subject, or any other header, the Worker can:

- Forward to one or more mailboxes.
- Trigger custom logic — fire a webhook, write to a database, enqueue a task.
- Reject (bounce) the message outright.

This is routing as code, not as a static rules file. A rule like "if the sender is in this KV list of VIPs, forward to my phone; otherwise file in the inbox" becomes a few lines of Worker code rather than a fragile filter chain in a mail client.

### Processing

Once the email is routed to the Worker, the Worker can read and manipulate its contents [6]:

- Read headers, body (text and HTML), and attachments.
- Extract data — parse a confirmation number, pull a tracking link, scrape structured content.
- Modify the message — append a disclaimer, translate, redact.
- Trigger downstream work — store an attachment in R2, post the parsed data to an API, kick off a Workflow.

The pattern that clicked: an inbox becomes an API. Any service that sends email (Stripe receipts, GitHub notifications, monitoring alerts) becomes a structured input to my application, not just a message a human reads. The Worker turns the email into data and an action.

### Filtering

Filtering is the selective layer — which emails the Worker processes at all, and how [7]. The rules can be based on:

- Sender or recipient address, or domain.
- Subject-line keywords or patterns.
- Header values (a list-id, a spam score).
- Body content.

A common pattern: filter to detect spam or phishing (a known-bad sender list, suspicious link patterns), filter to classify (transactional vs. personal vs. alert), then route and process accordingly. The filtering happens before the heavy processing, so the Worker doesn't waste effort on messages it doesn't care about.

## How these two fit together

The unifying shape is "a Worker in front of a traffic stream it can intercept." For AI Gateway, the stream is calls to AI providers and the value is centralized policy. For Email Workers, the stream is incoming mail and the value is programmatic control over routing and processing. Neither is a compute product in the Workers-AI sense — both are control planes for a specific kind of traffic.

## How I use this

For AI Gateway: I reach for it the moment an application makes more than a handful of AI calls per day, because the observability alone pays for itself — knowing what's being called, at what latency, at what cost, is the difference between an AI feature I can operate and one I can't. Caching is the second win, and it's often larger than I expect.

For Email Workers: I use it when email is an input to my system, not just a human-readable notification. The trigger is usually "I'm getting an email I want to turn into data" — receipts, alerts, form submissions, third-party notifications. For purely human-to-human mail, a regular mailbox is simpler.

## References

[1] Cloudflare, "Cloudflare AI Gateway," Cloudflare Developer Platform, 2024. [Online]. Available: [https://www.cloudflare.com/developer-platform/products/ai-gateway/](https://www.cloudflare.com/developer-platform/products/ai-gateway/)

[2] Cloudflare, "Email Workers — Cloudflare Email Routing," Cloudflare Docs, 2024. [Online]. Available: [https://developers.cloudflare.com/email-routing/email-workers/](https://developers.cloudflare.com/email-routing/email-workers/)

[3] Cloudflare, "Cloudflare + AI," ai.cloudflare.com, 2024. [Online]. Available: [https://ai.cloudflare.com/](https://ai.cloudflare.com/)

[4] Cloudflare, "Announcing route to Workers — automate your email processing," Cloudflare Blog. [Online]. Available: [https://blog.cloudflare.com/announcing-route-to-workers/](https://blog.cloudflare.com/announcing-route-to-workers/)

[5] Cloudflare, "Email Workers — Cloudflare Email Routing," Cloudflare Docs. [Online]. Available: [https://developers.cloudflare.com/email-routing/email-workers/](https://developers.cloudflare.com/email-routing/email-workers/)

[6] Cloudflare, "Email Workers routing — Runtime API," Cloudflare Docs. [Online]. Available: [https://developers.cloudflare.com/email-routing/email-workers/runtime-api/](https://developers.cloudflare.com/email-routing/email-workers/runtime-api/)

[7] G. Chmr, "Implementing an email delivery service with Cloudflare Workers," Medium. [Online]. Available: [https://medium.com/@georgechmr/implementing-an-email-delivery-service-with-cloudflare-workers-c141422109d0](https://medium.com/@georgechmr/implementing-an-email-delivery-service-with-cloudflare-workers-c141422109d0)

```quiz
Q: What's the difference between Workers AI and AI Gateway?
- They're the same product under different names
- Workers AI runs models at the edge; AI Gateway manages traffic TO models (including external providers), with caching, rate limiting, and observability
- AI Gateway runs models; Workers AI routes requests
correct: 1
explain: Workers AI is compute — it runs inference. AI Gateway is policy — it sits in front of model calls (to Workers AI or external providers) and applies cache, rate limit, logging, and routing. They compose.

Q: Which problem does AI Gateway specifically solve?
- It trains new models faster
- It centralizes cross-cutting concerns for AI traffic — caching identical prompts, rate limiting, logging, and fallback across providers
- It replaces the need to call AI providers at all
correct: 1
explain: Direct calls to AI providers leave you no control over the traffic. AI Gateway inserts a layer where cache, limits, observability, and routing live, so the app code stays simple.

Q: An Email Worker intercepts an incoming email. What can it NOT do?
- Read headers, body, and attachments
- Forward to a mailbox or reject the message
- Run its own SMTP server to send arbitrary outbound mail to arbitrary recipients
correct: 2
explain: Email Workers operate on incoming mail addressed to a domain you control — reading, forwarding, rejecting, triggering logic. They're not a general-purpose outbound SMTP server; outbound mail delivery is a separate concern.

Q: The reference lists Routing, Processing, and Filtering for Email Workers. In what order do they conceptually apply?
- Filter (decide which to act on) → Route (decide where it goes) → Process (act on contents)
- Process first, then route, then filter
- Route, process, and filter all happen simultaneously with no ordering
correct: 0
explain: Filtering selects which messages the Worker cares about. Routing decides where they go. Processing reads and acts on the contents. The order matters so the Worker doesn't waste processing on messages it would have filtered out.

Q: You want every Stripe receipt email to become a structured record in your database. Which product fits?
- AI Gateway
- Email Workers — intercept the receipt, parse the contents, write the record
- Workers AI
correct: 1
explain: Email Workers turns an inbox into an API. The incoming email is intercepted, its contents parsed by the Worker, and the extracted data written to (say) D1. The email becomes a structured input, not just a human-readable message.
```
