Custom Domains
Background
Custom Domains allow you to connect your Worker to a domain or subdomain, without having to make changes to your DNS settings or perform any certificate management. After you set up a Custom Domain for your Worker, Cloudflare will create DNS records and issue necessary certificates on your behalf. The created DNS records will point directly to your Worker. Unlike Routes, Custom Domains point all paths of a domain or subdomain to your Worker.
Custom Domains are routes to a domain or subdomain (such as example.com
or shop.example.com
) within a Cloudflare zone where the Worker is the origin.`
Custom Domains are recommended if you want to connect your Worker to the Internet and do not have an application server that you want to always communicate with. If you do have external dependencies, you can create a Request
object with the target URI, and use fetch()
to reach out.
Custom Domains can stack on top of each other. For example, if you have Worker A attached to app.example.com
and Worker B attached to api.example.com
, Worker A can call fetch()
on api.example.com
and invoke Worker B.
Custom Domains can also be invoked within the same zone via fetch()
, unlike Routes.
Add a Custom Domain
To add a Custom Domain, you must have:
- An active Cloudflare zone.
- A Worker to invoke.
Custom Domains can be attached to your Worker via the Cloudflare dashboard, Wrangler or the API.
Set up a Custom Domain in the dashboard
To set up a Custom Domain in the dashboard:
- Log in to the Cloudflare dashboard and select your account.
- Select Workers & Pages and in Overview, select your Worker.
- Go to Triggers > Custom Domains > Add Custom Domain.
- Enter the domain you want to configure for your Worker.
- Select Add Custom Domain.
After you have added the domain or subdomain, Cloudflare will create a new DNS record for you. You can add multiple Custom Domains.
Set up a Custom Domain in your wrangler.toml
To configure a Custom Domain in your wrangler.toml
, add the custom_domain=true
option on each pattern under routes
. For example, to configure a Custom Domain:
routes = [ { pattern = "shop.example.com", custom_domain = true }
]
To configure multiple Custom Domains:
routes = [ { pattern = "shop.example.com", custom_domain = true }, { pattern = "shop-two.example.com", custom_domain = true }
]
Worker to Worker communication
On the same zone, the only way for a Worker to communicate with another Worker running on a route, or on a workers.dev
subdomain, is via service bindings.
On the same zone, if a Worker is attempting to communicate with a target Worker running on a Custom Domain rather than a route, the limitation is removed. Fetch requests sent on the same zone from one Worker to another Worker running on a Custom Domain will succeed without a service binding.
For example, consider the following scenario, where both Workers are running on the example.com
Cloudflare zone:
If worker-a
sends a fetch request to worker-b
, the request will fail, because of the limitation on same-zone fetch requests. worker-a
must have a service binding to worker-b
for this request to resolve.
worker-aexport default { fetch(request) { // This will fail return fetch("https://shop.example.com") }
}
However, if worker-b
was instead set up to run on the Custom Domain shop.example.com
, the fetch request would succeed.
Request matching behaviour
Custom Domains do not support wildcard DNS records. An incoming request must exactly match the domain or subdomain your Custom Domain is registered to. Other parts (path, query parameters) of the URL are not considered when executing this matching logic. For example, if you create a Custom Domain on api.example.com
attached to your api-gateway
Worker, a request to either api.example.com/login
or api.example.com/user
would invoke the same api-gateway
Worker.
Interaction with Routes
A Worker running on a Custom Domain is treated as an origin. Any Workers running on routes before your Custom Domain can optionally call the Worker registered on your Custom Domain by issuing fetch(request)
with the incoming Request
object. That means that you are able to set up Workers to run before a request gets to your Custom Domain Worker. In other words, you can chain together two Workers in the same request.
For example, consider the following workflow:
- A Custom Domain for
api.example.com
points to yourapi-worker
Worker. - A route added to
api.example.com/auth
points to yourauth-worker
Worker. - A request to
api.example.com/auth
will trigger yourauth-worker
Worker. - Using
fetch(request)
within theauth-worker
Worker will invoke theapi-worker
Worker, as if it was a normal application server.
auth-workerexport default { fetch(request) { const url = new URL(request.url) if(url.searchParams.get("auth") !== "SECRET_TOKEN") { return new Response(null, { status: 401 }) } else { // This will invoke `api-worker` return fetch(request) } }
}
Certificates
Creating a Custom Domain will also generate an Advanced Certificate on your target zone for your target hostname.
These certificates are generated with default settings. To override these settings, delete the generated certificate and create your own certificate in the Cloudflare dashboard. Refer to Manage advanced certificates for instructions.
Migrate from Routes
If you are currently invoking a Worker using a route with /*
, and you have a CNAME record pointing to 100::
or similar, a Custom Domain is a recommended replacement.
Migrate from Routes via the dashboard
To migrate the route example.com/*
:
- Log in to the Cloudflare dashboard and select your account.
- Go to DNS and delete the CNAME record for
example.com
. - Go to Account Home > Workers & Pages.
- In Overview, select your Worker > Triggers.
- Select Add Custom Domain and add
example.com
. - Delete the route
example.com/*
located in your Worker > Triggers > Routes.
Migrate from Routes via Wrangler
To migrate the route example.com/*
in your wrangler.toml
:
- Log in to the Cloudflare dashboard and select your account.
- Go to DNS and delete the CNAME record for
example.com
. - Add the following to your
wrangler.toml
file:
routes = [ { pattern = "example.com", custom_domain = true }
]
- Run
npx wrangler deploy
to create the Custom Domain your Worker will run on.