ccnames.dev

cnames.dev / blog

Engineering16 min read

How we run SSL for 5,000+ customer domains without Cloudflare for SaaS

The architecture behind 5,000+ customer domains: on-demand TLS, Let's Encrypt rate-limit math, a stateless edge, and the failure modes that actually bite at scale.

S
Saeed
July 2, 2026

We serve HTTPS for more than 5,000 customer-owned domains at Lindo.ai, a white-label website builder. Every customer can bring www.their-business.com and it just works — valid cert, fast, isolated. We do it without Cloudflare for SaaS. Here is the actual architecture, the numbers, and the things that broke.

This is the system we productized into cnames.dev. Nothing below is theoretical.

The shape of the system

Three moving parts, deliberately boring:

Browser
  │  TLS ClientHello (SNI: www.acme.com)
  ▼
Edge node (anycast)
  │  1. SNI -> "is this host allowed?" (control-plane lookup, cached)
  │  2. cert in store? serve it : issue via ACME (HTTP-01), then serve
  │  3. host -> tenant -> origin (+ per-tenant headers, real client IP)
  ▼
Origin (multi-tenant app)

On-demand TLS, and the allow-list that guards it

We pre-issue nothing. When a TLS handshake arrives for a hostname we have never seen, the edge asks the control plane a single question: is this hostname registered and verified by a tenant? If yes, we issue via HTTP-01 inline and cache the result. If no, we drop the handshake.

That allow-list check is the entire security boundary of on-demand TLS. Without it, anyone who points a domain at your edge can trigger unbounded certificate issuance and burn your CA rate limits in minutes. The lookup has to be fast and it has to fail closed. We keep it in an in-memory cache at the edge with a short TTL, backed by the control plane.

Let's Encrypt rate limits: what the docs do not emphasize

The limit everyone worries about — ~50 certificates per registered domain per week — barely matters here, because each customer domain (acme.com, globex.io) is a different registered domain. You would need 50 certs for one customer's single domain in a week to hit it.

What actually bit us was the account-level pressure: new-order limits and the duplicate-certificate limit, both triggered by retries. A customer sets the CNAME, DNS has not propagated, our issuance fails, something retries aggressively, and now one broken domain is generating dozens of failed orders. Multiply by a few hundred customers configuring domains on the same afternoon and you have a self-inflicted outage.

The fixes were unglamorous:

Always re-read the current Let's Encrypt rate-limit page before tuning any of this; the numbers change. We also keep a second ACME provider configured as a fallback so a single CA incident is not a single point of failure.

Keeping the edge stateless

Edge nodes hold no durable truth. The certificate store and the hostname→tenant map are shared; a node can be recycled at any time and warm itself from the shared store. This is what lets us add capacity or replace a node without a certificate re-issuance storm. The first request to a cold node for a given host is a store lookup, not a fresh ACME order.

The real client IP problem

The moment you proxy, your origin sees the edge's IP, not the visitor's. For a multi-tenant app that does rate limiting, fraud checks, or geo logic, that is a correctness bug. We forward the client address explicitly and make the origin trust it only from our edge ranges. It sounds trivial; it is the kind of thing that silently corrupts analytics for months if you skip it. We wrote up the details in the broader custom domains guide.

What we would tell our past selves

Build it or buy it

If you want to run this yourself, the honest trade-offs are in cnames.dev vs self-hosting Caddy on-demand TLS. If you would rather make one API call per domain and never think about ACME rate limits again, that is what cnames.dev is — the same infrastructure described here, offered as a service. It is a particularly good fit for website builders running the exact playbook we did.

Building a SaaS that needs custom domains? cnames.dev gives every customer their own domain — SSL, edge routing, and per-tenant isolation in one API call. Free for 25 domains, no demo call. Start free · Read the docs

Frequently asked questions

Why not just use Cloudflare for SaaS?

It is a good product if you are already all-in on Cloudflare. We wanted provider independence — the ability to sit in front of any origin, run our own edge, keep per-tenant header and redirect policies, and not tie our unit economics to one vendor's per-hostname pricing. That trade-off is the whole reason cnames.dev exists.

What Let's Encrypt rate limits actually bite at scale?

Not the per-registered-domain cap, because every customer domain is its own registered domain. The account-level new-orders limit and the duplicate-certificate limit are what you hit — almost always because of a retry loop against domains whose DNS is not ready yet. The fix is backoff plus not attempting issuance until DNS resolves to you.

How long does a cert take to issue?

A few seconds once DNS resolves to the edge. The variable is DNS propagation on the customer side, not the CA.

Keep reading

S

SaeedFounder, cnames.dev — runs custom-domain infra for 5,000+ production sites at Lindo.ai.