---
title: Hostname routing · Cloudflare for Platforms docs
description: Learn how to route requests to the dispatch worker.
lastUpdated: 2025-07-01T18:55:53.000Z
chatbotDeprioritize: false
source_url:
  html: https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/hostname-routing/
  md: https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/hostname-routing/index.md
---

You can use [dynamic dispatch](https://developers.cloudflare.com/cloudflare-for-platforms/workers-for-platforms/get-started/dynamic-dispatch/) Workers to route millions of vanity domains or subdomains to Workers without hitting traditional [route limits](https://developers.cloudflare.com/workers/platform/limits/#number-of-routes-per-zone). These hostnames can be subdomains under your managed domain (e.g. `customer1.saas.com`) or vanity domains controlled by your end customers (e.g. `mystore.com`), which can be managed through [custom hostnames](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/).

## (Recommended) Wildcard route with a dispatch Worker

Configure a wildcard [Route](https://developers.cloudflare.com/workers/configuration/routing/routes/) (`*/*`) on your SaaS domain (the domain where you configure custom hostnames) to point to your dynamic dispatch Worker. This allows you to:

* **Support both subdomains and vanity domains**: Handle `customer1.myplatform.com` (subdomain) and `shop.customer.com` (custom hostname) with the same routing logic.
* **Avoid route limits**: Instead of creating individual routes for every domain, which can cause you to hit [Routes limits](https://developers.cloudflare.com/workers/platform/limits/#number-of-routes-per-zone), you can handle the routing logic in code and proxy millions of domains to individual Workers.
* **Programmatically control routing logic**: Write custom code to route requests based on hostname, [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/), path, or any other properties.

Note

This will route all traffic inbound to the domain to the dispatch Worker.

If you'd like to exclude certain hostnames from routing to the dispatch Worker, you can either:

* Add routes without a Worker specification to opt certain hostnames or paths from being executed by the dispatcher Worker (for example, for `saas.com`, `api.saas.com`, etc)
* Use a [dedicated domain](https://developers.cloudflare.com/dns/zone-setups/subdomain-setup/) (for example, `customers.saas.com`) for custom hostname and dispatch worker management to keep the rest of the traffic for that domain separate.

### Setup

To set up hostname routing with a wildcard route:

1. **Configure custom hostnames**: Set up your domain and custom hostnames using [Cloudflare for SaaS](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/)
2. **Set the fallback origin**: Set up a [fallback origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#1-create-fallback-origin), this is where all custom hostnames will be routed to. If you’d like to route them to separate origins, you can use a [custom origin server](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/custom-origin/). Requests will route through the Worker before reaching the origin. If the Worker is the origin then place a dummy DNS record for the fallback origin (e.g., `A 192.0.2.0`).
3. **Configure DNS**: Point DNS records (subdomains or custom hostname) via [CNAME record to the saas domain](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/getting-started/#3-have-customer-create-cname-record). If your customers need to proxy their apex hostname (e.g. `example.com`) and cannot use CNAME records, check out [Apex Proxying](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/start/advanced-settings/apex-proxying/).
4. **Create wildcard route**: Add a `*/*` route on your platform domain (e.g. saas.com) and associate it with your dispatch Worker.
5. **Implement dispatch logic**: Add logic to your dispatch Worker to route based on hostname, lookup mappings stored in \[Workers KV]\([Workers KV](https://developers.cloudflare.com/kv/)), or use [custom metadata](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/domain-support/custom-metadata/) attached to custom hostnames.

Note

If you plan to route requests based on custom metadata, you'll need to create subdomains (e.g. `customer1.saas.com`) as custom hostnames. This is because DNS records do not support custom metadata.

#### Example dispatch Worker

```js
export default {
  async fetch(request, env) {
    const hostname = new URL(request.url).hostname;


    // Get custom hostname metadata for routing decisions
    const hostnameData = await env.KV.get(`hostname:${hostname}`, { type: 'json' });


    if (!hostnameData?.workerName) {
      return new Response('Hostname not configured', { status: 404 });
    }


    // Route to the appropriate user Worker
    const userWorker = env.DISPATCHER.get(hostnameData.workerName);
    return await userWorker.fetch(request);
  }
};
```

## Subdomain routing

If you're only looking to route subdomain records (e.g. `customer1.saas.com`), you can use a more specific route (`*.saas.com/*`) to route requests to your dispatch Worker.

### Setup

To set up subdomain routing:

1. Create an orange-clouded wildcard DNS record: `*.saas.com` that points to the origin. If the Worker is the origin then you can use a dummy DNS value (for example, `A 192.0.2.0`).
2. Set wildcard route: `*.saas.com/*` pointing to your dispatch Worker
3. Add logic to the dispatch Worker to route subdomain requests to the right Worker.

#### Example subdomain dispatch Worker

```js
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const subdomain = url.hostname.split('.')[0];


    // Route based on subdomain
    if (subdomain && subdomain !== 'saas') {
      const userWorker = env.DISPATCHER.get(subdomain);
      return await userWorker.fetch(request);
    }


    return new Response('Invalid subdomain', { status: 400 });
  }
};
```

### Orange-to-Orange (o2o) Behavior

When your customers are also using Cloudflare and point their custom domain to your SaaS domain via CNAME (for example, `mystore.com` → `saas.com`), Worker routing behavior depends on whether the customer's DNS record is proxied (orange cloud) or DNS-only (grey cloud). Learn more about [Orange-to-Orange setups](https://developers.cloudflare.com/cloudflare-for-platforms/cloudflare-for-saas/saas-customers/how-it-works/#with-o2o)

This can cause inconsistent behavior when using specific hostname routes:

* If you're routing based on the CNAME target (`saas.com`), the custom hostname's DNS record must be orange-clouded for the Worker to be invoked.
* If you're routing based on the custom hostname (`mystore.com`), the customer's record must be grey-clouded for the Worker to be invoked.

Since you may not have control over your customer's DNS proxy settings, we recommend using `*/*` wildcard route to ensure routing logic always works as expected, regardless of how DNS is configured.

#### Worker invocation across route configurations and proxy modes

The table below shows when Workers are invoked based on your route pattern and the customer's DNS proxy settings:

| Route Pattern | Custom Hostname (Orange Cloud) | Custom Hostname (Grey Cloud) |
| - | - | - |
| `*/*` (Recommended) | ✅ | ✅ |
| Target hostname route | ✅ | ❌ |
| Custom hostname route | ❌ | ✅ |
