Guides

How to let customers use their own domain in your SaaS

Short answer: a custom-domain feature is five jobs. Get a DNS record into the customer's zone, prove they own the domain, get a certificate for it, route its requests to the right tenant, and notice when any of that stops being true. Most of the difficulty is outside your code, in DNS the customer controls and in a certificate authority's rate limits. This guide covers each job and the rules that shape it, then points to the framework walkthroughs.

Published · external sources retrieved

1. The DNS record

The customer's domain has to resolve to your servers, and only the customer can make that happen, in a DNS editor they rarely open, sometimes at a company that is not their registrar. Which record you ask for depends on the name:

  • A subdomain, like app.customer.com: a CNAME record pointing at a hostname you control, such as domains.yourproduct.com. You can then move your infrastructure without asking a single customer to change anything.
  • The bare domain, like customer.com: DNS does not allow a CNAME at the apex, because the apex must also hold the zone's SOA and NS records. You need A and AAAA records to fixed IP addresses, or a provider-specific ALIAS or flattened CNAME. Stable IPs are a commitment: every customer has them in their zone.

Offering subdomains first is the common compromise. The subdomain vs custom domain entry covers the trade-off, and apex domains in the docs covers the patterns that work at the root.

2. Proof of ownership

Anyone can type any domain into your settings page. Without a check, the first person to claim shop.bigbrand.com holds it in your system, and the real owner cannot. The standard proof is a TXT record with a random token you generate, at a name like _yourproduct.shop.bigbrand.com. Only someone who controls the zone can publish it.

Check it at the domain's authoritative nameservers rather than through a public resolver. A resolver that looked the name up before the record existed caches the empty answer, and our measurements found zones where that lasts from a minute to two days. Your customer sees a failed check for a record they can see in their own DNS editor.

3. The certificate

Every custom domain needs its own TLS certificate, issued to you, for a name you do not control. Most products automate this with an ACME certificate authority such as Let's Encrypt, and its limits shape the design more than any library choice. Let's Encrypt publishes them:

LimitWhat Let's Encrypt saysWhat it means for custom domains
Per registered domainUp to 50 certificates can be issued per registered domain (or IPv4 address, or IPv6 /64 range) every 7 days.Each customer's own domain has its own budget. Tenant subdomains of YOUR domain all share one, so issue a wildcard for those.
Per accountUp to 300 new orders can be created by a single account every 3 hours.A burst of sign-ups or a bulk import has to be queued, not fired at once.
Failed validationsUp to 5 authorization failures per identifier can be incurred by one account every hour.Requesting a certificate before the customer's DNS points at you fails, and after five failures in an hour that hostname is refused until the window clears.
Duplicate certificatesUp to 5 certificates can be issued per exact same set of identifiers every 7 days.A retry loop that re-issues instead of reusing the stored certificate runs out after five tries, and then gets one more attempt every 34 hours.

The registered domain is worked out with the Public Suffix List, which is why each customer's domain gets a budget of its own while every tenant subdomain under your domain shares one. For volumes beyond these, the page adds:

If you are a large hosting provider or organization working on a Let's Encrypt integration, we have a rate limiting form that can be used to request higher rate limits.

Issue only after DNS points at you. An HTTP-01 or TLS-ALPN-01 challenge fails while the domain still resolves somewhere else, and failures are the limit you hit first. Gate issuance on the record being live at the authoritative nameservers, not on the customer clicking "done".

Or issue at the first request. Caddy's on-demand TLS "dynamically obtains a new certificate during the first TLS handshake that requires it, rather than at config load". It is the simplest way to serve many customer domains from one server, and it comes with a warning:

On-demand TLS must be both enabled and restricted to prevent abuse.

Without a restriction, anyone who points a domain at your IP address makes you request a certificate for it. Caddy's restriction is an ask endpoint: "Caddy will send an HTTP request to ask if it has permission to obtain and manage a certificate for the domain in the handshake." Answer yes only for domains that passed step 2.

Watch for CAA records. A customer can restrict which certificate authorities may issue for their domain. IETF is strict about it:

If such an RRset exists, a CA MUST NOT issue a certificate unless the CA determines that either (1) the certificate request is consistent with the applicable CAA RRset or (2) an exception specified in the relevant CP or CPS applies.

A customer whose security team allowed only their own CA will see your certificate fail with every DNS record correct. Read their CAA record at setup and tell them which issuer to add. The SSL notes in the docs cover Vercel, Cloudflare for SaaS, Caddy, nginx, Render and Fly.io.

4. Routing

Once the certificate is served, every request arrives with the customer's domain in its Host header. Your application maps that hostname to a tenant, usually with one lookup in a table of verified domains, cached, before any other routing runs. Two rules keep it safe:

  • Only verified domains go in the table. An unverified hostname should get a plain 404, never a default tenant.
  • Session cookies are scoped per host. A customer domain cannot read your main app's cookies, so sign-in on a custom domain needs its own flow or a token hand-off.

The walkthroughs for Next.js, Rails, Laravel and Django show the hostname-to-tenant middleware in each framework.

5. Watching it afterwards

A custom domain that worked on day one can break on any later day, and nothing in your stack will say so. The customer moves DNS hosts and does not copy your record. An agency tidies the zone. The domain lapses. The first symptom is often a certificate renewal failing weeks later, or a customer's visitors seeing an error before anyone at either company notices.

Re-check every connected domain on a schedule, at the authoritative nameservers, and treat a missing or changed record as an event your product acts on: email the customer, pause renewal attempts, flag the domain in their settings. A check that only runs at setup cannot see any of this.

Build it, or use a service for some of it

The five jobs split cleanly between DNS work and traffic work, and the services in this space divide along the same line.

  • Proxy services take the traffic side. Requests for customer domains flow through their edge, which issues the certificates and forwards to your origin, and they stay in the request path for as long as the feature exists. Cloudflare for SaaS and Approximated work this way.
  • DoDomain takes the DNS side: jobs 1, 2 and 5. A hosted connect flow gets the records into the customer's zone: guided manual steps on every plan, and on the Pro and Scale plans one click where the customer's DNS provider supports it (the Free plan has the guided steps only). DoDomain verifies at the authoritative nameservers, sends a signed connection.verified webhook when the domain is live, and keeps re-checking afterwards, sending connection.failed when a record drifts. It never sits in your request path and issues no certificates; jobs 3 and 4 stay on your own host, with connection.verified as the trigger to issue. The webhooks reference lists every event.

Whichever you choose, the order is the same: record, proof, certificate, routing, watching. Skipping the last one is the most common mistake, because it is the only one nobody notices on launch day.

Sources

All external pages retrieved 2026-09-23. Quotes are verbatim.

  1. Let's Encrypt, Rate Limits. The issuance limits that decide how a custom-domain feature requests certificates.
  2. Caddy, Automatic HTTPS. How on-demand TLS issues a certificate at the first handshake, and why it must be restricted.
  3. IETF, RFC 8659: DNS Certification Authority Authorization (CAA) Resource Record. Why a customer's CAA record can stop your certificate authority from issuing.