Custom Domains for SaaS: Let Customers Bring Their Own (Vercel & Bunny)
How to let users point their own domains at your SaaS — the Vercel and Bunny approaches, SSL, and the DNS gotchas to avoid.
Table of contents9 sections
- 01The Client Who Wanted Their Own Domain
- 02Two Problems That Look Like One
- 03Your Own Domain Is the Easy Part
- 04Letting Customers Bring Their Own (The Vercel Way)
- 05The Bunny Way: Pull Zones and a Dollar
- 06Cloudflare for SaaS: The Big Gun (And an Honest Correction)
- 07The Comparison, Since You’ll Ask
- 08SSL and the DNS Gotchas That’ll Eat Your Weekend
- 09The Bottom Line
The Client Who Wanted Their Own Domain
In 2023, when I was building Clickly — my Bitly-style URL shortener that I’ve written about before — I got the kind of question that sounds tiny and turns out to be a rabbit hole.
Someone I was showing it to said: “Cool, but can my short links be on my domain? Like go.mybrand.com instead of clickly.io/abc?”
Reasonable. Obvious, even. Every serious link shortener does it. Bitly charges a fat monthly fee for exactly that feature. So I said “sure, give me a day” — because I’m an engineer and I’m delusional about how long things take.
That day turned into a week. Because “let a customer use their own domain” is not one problem. It’s three problems in a trench coat: DNS, SSL, and routing. And in 2023 the tooling for it was genuinely bad. I remember staring at Vercel’s custom-domain API at 1 AM, watching a certificate refuse to provision, wondering why nobody warned me.
This is the guide I wish I’d had that night.
Two Problems That Look Like One
Before any tools, get this distinction straight, because mixing them up is where most people waste time.
Problem 1: your own domain. You built myapp.com and you want the app to live there. This is trivial. You do it once. It’s a solved problem and you should spend about ten minutes on it.
Problem 2: your customers’ domains. You’re building something white-labelable — a link shortener, a link-in-bio tool, a portfolio builder, hosted status pages, a docs platform — and your customers want their brand on it. links.acme.com pointing at your servers, with their logo, and an SSL padlock that says acme.com, not yourapp.com.
Problem 2 is the one that makes your product worth real money. It’s also the one that will eat your weekend. Let’s do the easy one first and get it out of the way.
Your Own Domain Is the Easy Part
You bought a domain from a registrar — Namecheap, Cloudflare Registrar, whoever. Now you point it at wherever your app is deployed.
If you’re on Vercel (and if your app is Next.js, you probably are — I go into why in the deployment tier list), you literally add the domain in the dashboard, drop in the A and CNAME records they show you, and Vercel provisions the certificate for you. Free on any paid plan. Done before your coffee’s cold.
If your app is somewhere else and you just want a CDN in front of it, Bunny does the same thing for a $1/month minimum — still the floor in 2026 — with bandwidth from about $0.01/GB on top. You create a Pull Zone, attach your hostname, click “add free Let’s Encrypt certificate,” and it’s live. (The whole reason I fell for Bunny is a separate love letter.)
That’s the entire section. Your own domain is plumbing you touch once. The interesting money is in the next part.
Letting Customers Bring Their Own (The Vercel Way)
Here’s the shape of the problem. A customer of yours owns acme.com. They want app.acme.com (or even the bare acme.com) to serve your SaaS, styled as their brand. You need to:
- Let them add that domain from inside your dashboard.
- Verify they actually own it (so a stranger can’t hijack someone else’s domain).
- Route their traffic to the right tenant in your app.
- Get a valid SSL certificate issued for their hostname, automatically.
In 2023 this was painful on Vercel. The API existed but it was fiddly, under-documented, and certificates would hang in a “pending” state with no clear reason. I distinctly remember cursing at it. Then — and this is a real thing that happened — the folks behind dub.co (an open-source link shortener with the exact same needs I had) pushed hard on Vercel, and Vercel cleaned the whole thing up. Shoutout to that homie; he saved a lot of us a lot of nights.
Today it’s genuinely good. It’s now packaged as Vercel for Platforms (their multi-tenant story), and the flow is:
- Your customer types
app.acme.cominto your dashboard. - You call the Vercel SDK —
projectsAddProjectDomain— to attach it to your project. - Vercel hands back the DNS records the customer needs to set, and a verification step to prove ownership.
- Once the DNS resolves, Vercel issues and auto-renews the SSL certificate for that hostname. You never touch a
.pemfile.
Vercel advertises unlimited custom domains and *.yourdomain.com wildcard subdomains on this setup, with automatic SSL for every tenant. There are sane rate limits — roughly 100 domain-adds per hour per team, last I checked — which matter only if you’re onboarding customers in a giant batch. For a bootstrapper adding domains one signup at a time, you’ll never feel them.
My take: if you’re already on Vercel, don’t shop around. This is the least-friction path to a real bring-your-own-domain feature, and it’s the one I’d use for a dashboard-heavy Next.js SaaS.
The Bunny Way: Pull Zones and a Dollar
But what if you’re not on Vercel? Maybe your backend runs on Railway or Koyeb, maybe you just refuse to pay for a Pro plan yet. This is where Bunny quietly wins.
The trick Bunny nailed years before anyone else: unlimited custom hostnames at no extra cost. You attach a customer’s domain to a Pull Zone, Bunny pulls a free Let’s Encrypt cert for it, and you’re done. A thousand customers, a thousand branded domains — the bill is still driven by bandwidth, not by a per-domain tax. For an optimization-obsessed broke engineer, that’s the whole game.
The mechanics, from your customer’s side:
- They add a
CNAMErecord pointing their subdomain (saylinks.acme.com) at your Bunny Pull Zone hostname. - Once it resolves, you (via Bunny’s API, which is genuinely well-documented — I’ve hammered it) add that hostname to the zone and request the free certificate.
- Bunny validates, issues, installs, and auto-renews. No renewal cron, no 3 AM cert panic.
Bunny has since launched Bunny for Platforms, an API-first product built specifically for the “manage thousands of customer domains” use case — DNS, SSL, and CDN in one, with per-domain pricing instead of bandwidth-based so your costs stay predictable, plus it lifts the old 500-zone limit. If custom domains are your product’s core feature and you’re onboarding them at scale, that’s worth a serious look. For a smaller shop, plain Pull Zones on the $1/month plan are plenty.
Cloudflare for SaaS: The Big Gun (And an Honest Correction)
I owe you a correction here. In the Bunny story I said Cloudflare for SaaS offered custom domains “only for enterprise plans.” That was true once. It isn’t anymore, and I don’t want a stale claim floating around with my name on it.
As of 2026, Cloudflare for SaaS is generally available on every plan — Free, Pro, and Business. You get 100 custom hostnames free to provision and test, and beyond that it’s $0.10 per custom hostname per month, with the cap raised into the tens of thousands on pay-as-you-go. It’s powerful: custom hostname verification, automatic certs, and all the WAF/DDoS muscle Cloudflare is famous for, bolted onto every tenant domain.
So why isn’t it my default? Two reasons. First, if you’re not already living in the Cloudflare ecosystem, it’s more moving parts than a solopreneur needs. Second, $0.10 per domain per month sounds like nothing until you’re at 5,000 customer domains and it’s $500/month — versus Bunny, where that same fleet rides on bandwidth you were paying for anyway. Cloudflare is a giant and I respect them; I just reach for the cheaper, simpler tool until scale forces my hand. (Same reasoning as the rest of my survival-guide stack.)
The Comparison, Since You’ll Ask
Here’s the honest side-by-side for the three I’d actually consider:
| Option | Best when | Custom domain cost | SSL | Setup pain |
|---|---|---|---|---|
| Vercel for Platforms | You’re already on Vercel / Next.js | Unlimited, included on paid plan | Auto (Vercel-managed) | Low |
| Bunny Pull Zones | You want cheapest at scale | Unlimited, no per-domain fee | Auto (Let’s Encrypt) | Medium |
| Cloudflare for SaaS | You’re deep in Cloudflare / need WAF | 100 free, then $0.10/domain/mo | Auto (Cloudflare-managed) | Medium |
There’s no wrong answer here — there’s a right answer for your situation. On Vercel already? Vercel. Cost-obsessed and hosting elsewhere? Bunny. Already have Cloudflare in front of everything and need enterprise security? Cloudflare for SaaS.
SSL and the DNS Gotchas That’ll Eat Your Weekend
The tools above hide most of the horror. But custom domains still fail in the same handful of ways every time, and knowing them up front is the difference between a five-minute onboarding and a support ticket that ruins your Sunday. Here’s what actually bites:
-
The apex domain problem. Customers love pointing the bare
acme.com(nowww, no subdomain) at you. But classic DNS won’t let you put aCNAMEon a root domain — only on subdomains. The fix isANAME/ALIAS/“CNAME flattening” records, which not every registrar supports. My advice: strongly nudge customers toward a subdomain (app.acme.com,links.acme.com). It’s one sentence in your docs and it kills 80% of the pain. -
DNS propagation isn’t instant. After a customer adds the record, it can take minutes to (rarely) hours to resolve worldwide. Your UI should say “verifying, this can take a few minutes” — not silently fail and make them think your product is broken. I’ve lost users to a missing loading state. Not code. A sentence.
-
Certificate issuance waits on DNS. Let’s Encrypt (and every provider above) has to see the domain pointing at them before it can validate and issue. So the cert can’t provision until the customer’s DNS is live. Order matters: DNS first, cert second. If you try to issue too early, it hangs, and you’ll blame the tool. It’s not the tool.
-
CAA records can silently block you. If a customer has a
CAArecord locking certificate issuance to some other authority, Let’s Encrypt is forbidden from issuing and the whole thing fails with a cryptic error. Rare, but when it happens it’s baffling. Add it to your troubleshooting doc so future-you doesn’t rediscover it at midnight. -
Verification is not optional. Always verify ownership (a
TXTrecord or a Vercel/Bunny-supplied token) before routing traffic. Otherwise someone can point their DNS at a domain they don’t own and hijack another brand’s setup. The platforms handle this for you — just don’t switch it off to “save a step.”
None of this is hard. It’s just unfamiliar, and unfamiliar at 1 AM feels like hard. Build the four states into your UI — pending DNS, verifying, issuing cert, live — and your customers will think your product is magic. It’s not. It’s a CNAME and some patience.
The Bottom Line
Custom domains feel like a chore until you realize they’re a moat. A link shortener without them is a toy; a link shortener with them is something a company will pay $49/month for. Same code. The feature that unlocks the price is the boring DNS plumbing everyone skips.
I never turned Clickly into a business — I over-engineered it into the ground, as usual. But I walked away knowing exactly how to let a customer bring their own domain, and that single feature has shown up in three projects since. Learn it once. Charge for it forever.
If you’re already on Vercel, use Vercel for Platforms and don’t think about it. If you’re chasing the lowest possible bill, Bunny’s Pull Zones are the cheapest real answer I know. And if the four DNS states above are in your UI, you’ve already done more than most.
This is the Broken Engineer Guide. I over-engineer everything, fail at business, and hand you the shortcuts so you don’t bleed the same weekends I did. Now go let someone bring their own domain.
