Blog

Custom domains for SaaS: let customers use their own domain with Cloudflare for SaaS

Let customers point their own domain at your SaaS with Cloudflare for SaaS: how validation works, what it costs as of October 2026 and where it breaks.

By Nicolás Cerón · · Leer en español

A row of distinct shopfronts on a night street, with a cutaway beneath the pavement showing crimson cables that connect every shop to one shared engine room.

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

  1. 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.
  2. The customer adds the DNS record you show them, for example portal.customer.com CNAME customers.yourapp.com.
  3. 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).
  4. The certificate authority validates domain control and issues the certificates.
  5. The hostname is ready when its status and ssl.status are both active and DNS points at your target. Cloudflare warns that a TLS handshake can succeed before ssl.status turns active, so treat the custom hostname details endpoint as the source of truth.

Certificate validation methods

Cloudflare's validation guide offers these options:

MethodWhat the customer doesWorks before DNS cutoverNotes
HTTP, automaticOnly adds the CNAMENoSimplest. Cloudflare suggests it when customers "can handle a few minutes of downtime."
HTTP, manualNothing if their domain already points to you; otherwise they serve your token on their current serverYesUseful when the domain is live with another provider.
TXTAdds a TXT record you give themYesRequired for wildcard hostnames.
Delegated DCVAdds one _acme-challenge CNAME, onceYesLets 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

FreeProBusinessEnterprise
Hostnames included100100100Custom
Price per additional hostname$0.10$0.10$0.10Custom
Maximum hostnames50,00050,00050,000Unlimited (contact sales above 50,000)
Wildcard custom hostnamesNoNoNoYes
Custom certificates and selectable CANoNoNoYes
Apex proxying / BYOIPNoNoNoPaid add-on
Custom metadataNoNoNoPaid 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_errors into 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 SaaSVercelNetlify
Domain limits100 included, up to 50,000 on Free, Pro and Business50 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 domainsEnterprise add-onA record to the value on the project's domain cardALIAS, ANAME or flattened CNAME, or an A record as fallback
CertificatesAutomatic, two per hostname; custom certificates on EnterpriseAutomatic after domain verification; custom certificates on EnterpriseAutomatic Let's Encrypt; custom certificates renewed by hand
WildcardsEnterpriseNeed Vercel nameservers or a delegated _acme-challengeAutomatic for domains on Netlify DNS
Built forMany customer domains on one zoneMulti-tenant platforms with a REST API and SDKA 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.