The short answer
To let a customer serve your app on their own domain, say portal.customer.com, you register that domain as a custom hostname on your Cloudflare zone. The customer adds one CNAME record pointing at you, Cloudflare checks that they control the hostname, a certificate authority issues the certificates, and requests start reaching your app.
As of October 2026, the Cloudflare for SaaS plans page includes 100 custom hostnames on the Free, Pro and Business plans, lists $0.10 per additional hostname, and caps those plans at 50,000 hostnames.
Two limits shape every design. Customers can't point a bare apex domain (customer.com) at you without a paid Enterprise add-on. And wildcard custom hostnames, custom certificates and a choice of certificate authority are Enterprise-only. The Cloudflare setup is a handful of steps. The product work around it takes longer, and most of this guide is about that.
What a custom hostname is
A custom hostname is a domain your customer owns that Cloudflare routes into your zone. The setup guide has four pieces:
- SaaS zone. Your own domain on Cloudflare, with Cloudflare for SaaS enabled. A zone on the Free plan is enough to start.
- Fallback origin. A proxied DNS record, such as
proxy-fallback.yourapp.com, where custom-hostname traffic goes. - CNAME target. An optional, friendlier name for customers to point at, such as
customers.yourapp.com. - Custom hostname. The customer's domain, created by API or dashboard, with its own validation state. Cloudflare issues two certificates for each: an ECDSA P-256 primary and an RSA 2048-bit fallback for older clients.
If your app runs on Cloudflare Workers, the platform Dardo builds on, the Worker can be the fallback origin. A */* route catches requests for every custom hostname, and your code reads the Host header to find the tenant. Cloudflare also offers per-hostname custom metadata, but it's a paid Enterprise add-on, so on other plans that lookup lives in your own database, such as D1.
How the flow works
- The customer enters a domain in your app's settings. Your backend normalizes it and calls the Create Custom Hostname endpoint with a certificate validation method.
- The customer adds the DNS record you show them, for example
portal.customer.com CNAME customers.yourapp.com. - Cloudflare validates ownership of the hostname. Real-time validation runs when the CNAME appears, which can mean a short downtime. Pre-validation uses a TXT record or an HTTP token before DNS changes, for domains that are already live. Pre-validation isn't supported when the customer's own zone is also on Cloudflare (an "Orange-to-Orange" setup).
- The certificate authority validates domain control and issues the certificates.
- The hostname is ready when its
statusandssl.statusare bothactiveand DNS points at your target. Cloudflare warns that a TLS handshake can succeed beforessl.statusturns active, so treat the custom hostname details endpoint as the source of truth.
Certificate validation methods
Cloudflare's validation guide offers these options:
| Method | What the customer does | Works before DNS cutover | Notes |
|---|---|---|---|
| HTTP, automatic | Only adds the CNAME | No | Simplest. Cloudflare suggests it when customers "can handle a few minutes of downtime." |
| HTTP, manual | Nothing if their domain already points to you; otherwise they serve your token on their current server | Yes | Useful when the domain is live with another provider. |
| TXT | Adds a TXT record you give them | Yes | Required for wildcard hostnames. |
| Delegated DCV | Adds one _acme-challenge CNAME, once | Yes | Lets Cloudflare renew every future certificate. An existing _acme-challenge TXT record blocks it. |
Validation doesn't wait forever. Cloudflare retries hostname validation 75 times over seven days, and per its backoff schedule, "if the validation is unsuccessful, the custom hostname will be deleted." Certificate tokens expire too: after 7 days with Let's Encrypt and 14 days with Google Trust Services or SSL.com.
What it costs, as of October 2026
| Free | Pro | Business | Enterprise | |
|---|---|---|---|---|
| Hostnames included | 100 | 100 | 100 | Custom |
| Price per additional hostname | $0.10 | $0.10 | $0.10 | Custom |
| Maximum hostnames | 50,000 | 50,000 | 50,000 | Unlimited (contact sales above 50,000) |
| Wildcard custom hostnames | No | No | No | Yes |
| Custom certificates and selectable CA | No | No | No | Yes |
| Apex proxying / BYOIP | No | No | No | Paid add-on |
| Custom metadata | No | No | No | Paid add-on |
The plans page lists the $0.10 without a period. Cloudflare's 2022 announcement described it as cutting the price "from $2 to $0.10 a month." At that monthly rate, 1,000 customer domains means 900 beyond the included 100, or $90 a month.
Two billing rules matter for product design. Per Cloudflare's quotas and billing page, every hostname counts toward usage until you delete it, including "hostnames that are pending validation or activation." And non-Enterprise plans have an API enforcement threshold beyond which new hostnames are rejected.
Where it breaks
Apex domains
Cloudflare's setup guide is explicit: "By default, using an A record to point to the target is not a supported setup." Most DNS providers don't allow a CNAME at the root of a domain, so customers need a subdomain such as www.customer.com or app.customer.com. Apex proxying assigns your account static IP prefixes so customers can use an A record, but it is an Enterprise add-on with its own cost. Without it, ask customers for a subdomain and explain how to forward the bare domain to it at their DNS provider.
Certificate authorities and CAA records
Cloudflare's certificate authorities reference lists Let's Encrypt (90-day certificates), Google Trust Services and SSL.com (14, 30 or 90 days) for custom hostnames. Picking the CA is Enterprise-only; otherwise Cloudflare uses its default and checks CAA records first. If a customer's CAA records don't allow that CA, issuance fails with "CAA records block issuance," and only the customer can fix it. CAA lookups follow CNAME chains, so your own target domain's CAA records count too. The troubleshooting guide lists the other customer-side failures: broken DNSSEC and DNS servers answering SERVFAIL.
Renewals
Custom hostname certificates last 90 days and can renew 30 days before expiry. Active, non-wildcard hostnames renew automatically over HTTP. If a hostname is no longer active, for instance because the customer changed their DNS, the customer has to place a new token, and you are responsible for sending it to them. Wildcards can only renew through TXT, which is what Delegated DCV automates.
Customers on another CDN or on Cloudflare
Cloudflare says custom hostnames using another CDN are not compatible when that CDN hides the DNS records. Customers whose domains are on Cloudflare bring the opposite problem: if they leave and you don't delete their hostname, it can keep routing to your service even after they change DNS.
Workers in front of validation paths
If a Worker is your fallback origin, it has to pass /.well-known/pki-validation/* and /.well-known/acme-challenge/* through unchanged. A catch-all route that answers with your app's 404 page breaks HTTP validation.
The product work around it
- Plan enforcement. Decide which of your plans include custom domains and how many, and check that before calling Cloudflare. Its quota and threshold are ceilings, not your pricing.
- Onboarding screen. One input field. Lowercase it, strip the protocol and path, reject bare apex domains unless you bought apex proxying, and reject your own zone name, which Cloudflare says never to create as a custom hostname. Then show the exact record to add, with a copy button.
- Two statuses in plain language. Hostname and certificate validate separately, so show both. Translate
ssl.validation_errorsinto instructions: "Your domain's CAA records don't allow our certificate authority; add this record" beats "pending_validation." The create response may not include validation records yet, so fetch the hostname again after a short delay. Cloudflare's webhook notifications report validation and issuance events, which beats polling. - Renewal monitoring. A daily job that flags hostnames whose certificate isn't active or whose DNS no longer points at you, so your team hears about it before the customer does.
- Cleanup. Delete hostnames that never validate and those of customers who leave. Both are billed until deleted.
- Tenant isolation. Resolve the tenant only from active hostnames in your database. If tenants also get subdomains of your domain, Vercel's domain docs point out that a cookie one tenant sets for the parent domain reaches the others, so keep your dashboard and login on a separate domain.
- Support playbook. A short page for your team mapping each error to who fixes it: missing CNAME, CAA, DNSSEC and SERVFAIL are on the customer; tokens, CA rate limits and Worker routes are on you.
This is the kind of work Dardo does in web app development, and white-label client portals are where custom domains get asked for most.
Alternatives: Vercel and Netlify
If your app already runs elsewhere, both hosts handle customer domains with their own documented limits as of October 2026.
| Cloudflare for SaaS | Vercel | Netlify | |
|---|---|---|---|
| Domain limits | 100 included, up to 50,000 on Free, Pro and Business | 50 per project on Hobby; "Unlimited" on Pro and Enterprise, with soft limits of 100,000 and 1,000,000 | "We recommend assigning no more than 50 domain aliases to a site" |
| Apex domains | Enterprise add-on | A record to the value on the project's domain card | ALIAS, ANAME or flattened CNAME, or an A record as fallback |
| Certificates | Automatic, two per hostname; custom certificates on Enterprise | Automatic after domain verification; custom certificates on Enterprise | Automatic Let's Encrypt; custom certificates renewed by hand |
| Wildcards | Enterprise | Need Vercel nameservers or a delegated _acme-challenge | Automatic for domains on Netlify DNS |
| Built for | Many customer domains on one zone | Multi-tenant platforms with a REST API and SDK | A few dozen domains per site at most |
Vercel's apex support is the clearest difference: customers can point a bare domain at it with an A record. Note that the Hobby plan is restricted to "non-commercial, personal use only" under Vercel's fair use guidelines, so a paying SaaS starts on Pro. Netlify's 50-alias recommendation makes it a poor fit for one deployment serving hundreds of customer domains.
When to build it
If two or three customers ask, add their hostnames in the Cloudflare dashboard and keep a checklist. Build the self-serve flow when custom domains become part of a plan you sell or of a white-label offer. If customers need bare apex domains or wildcards at scale, talk to Cloudflare about Enterprise before you design around the limits.
If you want that flow built into your product, with the statuses, alerts and support notes above, tell us about your app.
