Custom domains for SaaS
How a SaaS lets each customer serve your product on their own domain, the five steps behind it, and which of them Apexly runs for you.
Short answer: your customer adds one DNS record that points their hostname (say careers.acme.com) at you. You verify that record, issue a TLS certificate for that exact hostname, and route each request to the right tenant by its Host header. After go-live you keep checking DNS and renewing the certificate. With Apexly, you make one API call and your customer adds the record. Apexly does the rest and forwards signed requests to your app.
For the long version, with code, apex domains, rate limits and failure states, read How to add custom domains to your SaaS: the complete guide.
The five steps
- The customer adds a DNS record. A subdomain gets a CNAME to its own target,
d-xxxxxx.cname.apexly.dev(dns.cname.valueon the domain). An apex likeacme.comcan't have a CNAME, so it gets the A records indns.apex.aplus a TXT record at_apexly.<hostname>. The connect page finds their DNS provider and shows them where to click. - You verify it. Apexly checks every 15 seconds for the first hour, then every 5 minutes, for up to 72 hours. Once it sees the record, it confirms it from 1.1.1.1, 8.8.8.8 and the zone's own nameservers. All three must agree.
- A certificate is issued for that hostname. Only verified hostnames get one. Apexly requests it from Let's Encrypt, checks CAA records first, and renews it 30 days before expiry.
- Requests are routed by
Host. The edge terminates TLS and forwards to your origin with the originalHost,X-Apexly-Domain-Id,X-Apexly-TimestampandX-Apexly-Signature. Your app finds the tenant from the host and accepts only signed requests. See the Next.js guide or the guide for your framework. - Keep watching. An active domain's DNS is re-checked every 6 hours. If the customer moves their DNS, the domain goes
dns_broken, the certificate keeps serving, and you get adomain.dns_brokenwebhook with the reason.
What you build, and what Apexly runs
| Step | Building it yourself | With Apexly |
|---|---|---|
| DNS instructions | Per-provider help pages and support tickets | The connect page, plus dns on the domain object |
| Verification | Polling, resolver caches, apex TXT tokens | Three resolvers, fixed cadence, a status_reason for every failure |
| Certificates | ACME client, storage, locks, rate limits, CAA | Issued and renewed for you |
| Routing | TLS proxy keyed by hostname | Signed requests to your origin with the original Host |
| Lifecycle | Monitoring and alerts | Domain states and webhooks |
Start with the quickstart: a test key walks a domain through every state on a ten-second timer, with no DNS and no certificate authority.
FAQ
How do custom domains for SaaS work?
The customer adds one DNS record that points their hostname at your infrastructure: a CNAME for a subdomain, or A records plus a TXT record for an apex domain. You verify the record, issue a TLS certificate for that exact hostname, and route each request to the right tenant by its Host header. Then you keep checking DNS and renewing the certificate for as long as the domain exists.
Should my customers use a CNAME or an A record?
A CNAME for subdomains like app.acme.com, so you can change IP addresses without asking customers to edit DNS. An apex domain like acme.com cannot have a CNAME, so it needs A records to fixed IPs. With Apexly, an apex also needs a TXT record at _apexly.<hostname> that proves control.
How do I get SSL certificates for my customers' domains?
Use an ACME certificate authority such as Let's Encrypt, and only after the customer's DNS is verified. Apexly checks the record from 1.1.1.1, 8.8.8.8 and the zone's own nameservers, issues a Let's Encrypt certificate once all three agree, and renews it 30 days before it expires.
How does my app know which customer a request is for?
From the Host header. Apexly forwards every request with the visitor's original Host plus X-Apexly-Timestamp and X-Apexly-Signature, an HMAC-SHA256 of timestamp.host with your app's signing secret, so your origin can trust the host it reads.
How much does Apexly cost?
Free for 20 domains, no card. Pay as you go is $0.15 per live domain a month with a $15 minimum, lower at volume. Domains that never connect are not billed. See Limits and pricing.