Your tenant's custom domain goes dark at 3 a.m. Not because your app is down — your status page is green — but because a certificate renewal failed silently three weeks ago and nobody noticed until the browser padlock turned into a warning. Now multiply that failure mode by every tenant who ever pointed a domain at your platform, and then halve every certificate lifetime on the internet. That is the renewal treadmill a self-hosted PaaS is stepping onto: Let's Encrypt is cutting default lifetimes from 90 days toward 45, and the CA/Browser Forum has already scheduled the industry-wide maximum at 47 days by 2029. Whoever renews your tenants' certificates is about to do twice the work, forever.
Three self-hostable answers compete for that job — cert-manager, the Kubernetes-native default; Gardener cert-management, the multi-cluster contender; and certctl, the new lifecycle platform. Verdict first, evidence below.
| cert-manager | Gardener cert-management | certctl | |
|---|---|---|---|
| Challenge types | HTTP-01 + DNS-01 | DNS-01 only (ACME) | Any CA via 12 connectors; embedded ACME server |
| Issuer secret placement | Same cluster as tenants | Secured cluster, separate from source clusters | Control plane holds CA creds; keys stay on hosts in agent mode |
| Certificate reuse | No — duplicate requests re-issue | Yes — reuses on common-name + DNS-name match | Yes — lifecycle-tracked, idempotent deploy |
| Multi-cluster story | One install per cluster | One controller, many source clusters | One control plane, agents everywhere |
| Renewal failure blast radius | Per-cluster, per-Issuer | Centralized controller to watch | Central scheduler + per-target status |
| Maturity / license | CNCF graduated, Apache-2.0 | Production in Gardener, Apache-2.0 | Early-access, BSL 1.1 |
The default: run cert-manager unless you have a concrete reason not to. It is the graduated, boring, hireable choice. Switch to Gardener cert-management when you run multiple clusters and refuse to put issuer credentials in tenant-reachable ones. Evaluate certctl when your problem is bigger than Kubernetes — mixed VMs, appliances, and private PKI — or when you need a second CA behind Let's Encrypt. Whichever you pick, the renewal-monitoring checklist at the end is non-negotiable: every one of these tools can fail quietly.
What "cost" actually means when tenants bring domains
"Operational overhead" is vague until you price it in the four currencies that actually hurt.
1. Challenge mechanics per tenant domain. Every issuance must prove control of the domain, and the two ACME challenge types have opposite scaling properties. HTTP-01 serves a token over port 80 from the domain itself: simple, but it cannot issue wildcards and it assumes your solver is what answers on that tenant's port 80 — awkward when the tenant's DNS points through their own CDN first. DNS-01 creates a TXT record in the tenant's zone: it handles wildcards and firewalled origins, but it needs DNS API credentials for every zone you validate, or a CNAME delegation from the tenant pointing _acme-challenge at a zone you control. At ten tenants this is a spreadsheet; at a thousand it is a credential-management problem of its own.
2. Secret distribution. A certificate that exists but isn't mounted where TLS terminates is just a log entry. Someone must move each cert and key from the issuer to the ingress, gateway, or VM that serves it — across namespaces, across clusters, across renewals — without leaking private keys into places tenants can read.
3. Renewal failure blast radius. Issuance gets the demo; renewal gets the 3 a.m. page. The questions that matter are: what breaks when renewal fails, how loudly does it alert, and how many tenants share the fate of one broken component?
4. CA and rate-limit exposure. Let's Encrypt's production limits are public and hard: 50 new certificates per registered domain per week, 5 duplicate certificates per exact set of names per week, 300 new orders per ACME account every 3 hours, and at most 100 names per certificate. Renewals of the exact same name set are exempt from the first and third limits, and staging limits are far higher — which is why every serious setup validates against staging first.
One subtlety that reshapes the whole comparison: when every tenant brings their own domain, each tenant owns a separate 50-per-week bucket, so that limit rarely bites tenant custom domains directly. It bites your platform's shared onboarding domain — the tenant-1234.yourpaas.com names you mint before the custom domain arrives. For custom domains, the binding constraints are the 5-duplicates-per-week limit during retry storms and the 300-orders-per-3-hours account ceiling during mass re-issuance. Keep that split in mind; it is where the tools diverge.
And the treadmill is speeding up. Let's Encrypt's 6-day short-lived profile went generally available in January 2026, the tlsserver profile switched to 45-day certificates as an opt-in in May 2026, and the default classic profile follows to 64 days in February 2027 and 45 days in February 2028. The CA/Browser Forum's SC-081 ballot caps public certificates at 200 days by March 2026, 100 days by March 2027, and 47 days by March 2029. At 90-day lifetimes a thousand-tenant fleet already processes over a hundred renewals a week; at 45 days that doubles. Manual workflows don't survive that math. Automation with monitoring barely notices it.
cert-manager: the default, and where it bites
cert-manager is the CNCF-graduated industry standard for a reason: install it, define a ClusterIssuer pointing at Let's Encrypt, annotate an Ingress, and certificates appear and renew as Secrets. HTTP-01 works out of the box; DNS-01 covers wildcards through built-in providers plus a webhook mechanism for the rest. Every Kubernetes hire has operated it, every managed Kubernetes offering tolerates it, and its failure modes are Googleable — an underrated feature at 3 a.m.
Three costs bite specifically at tenant scale, and all three are documented rather than secret.
First, issuer credentials live in the same cluster as the tenants. The ACME account key and DNS provider tokens are Secrets in the cluster cert-manager runs in. For a single-cluster PaaS where tenants get namespaces, that means your most powerful TLS credentials share a control plane with tenant workloads. Namespace isolation plus RBAC makes this acceptable for many teams, but the boundary is policy rather than architecture — and the upstream issue tracking cross-cluster issuers has been open for years.
Second, there is no certificate reuse. Request the same names twice and cert-manager issues twice, burning two slots of the 5-duplicates-per-week budget per exact name set. Normally harmless; during a retry storm — a deploy loop re-creating Certificate resources, a controller restart racing itself — it converts a transient error into a week-long rate-limit lockout for the tenant already having a bad day. Mitigate with staging validation, retry backoff, and alerts on duplicate issuance, but know the guardrail is yours to build.
Third, DNS-01 at scale means provider sprawl. Each tenant zone needs either API credentials your solver can use or a CNAME delegation to a zone you control. cert-manager supports delegation per-Issuer, but every new DNS provider a tenant brings is a new solver configuration, a new credential to rotate, and a new way for renewal to fail in a provider-specific way. HTTP-01 dodges all of this until the first tenant who needs a wildcard or sits behind their own CDN — which, at scale, is a "when," not an "if."
None of this disqualifies cert-manager. It means the honest price of the default is: one install per cluster, issuer secrets in the tenant control plane, and operator-built guardrails around duplicates and DNS credentials.
Gardener cert-management: the multi-cluster answer
Gardener's cert-management starts from the complaint above and inverts the architecture. Instead of running issuance inside every cluster, a single cert-controller-manager runs in a secured cluster — holding all issuer secrets — and watches one or more untrusted source clusters for Certificate, Ingress, Service, and Gateway resources. It solves ACME DNS-01 challenges by creating DNSEntry records handled by a companion DNS controller, possibly in yet another cluster. Tenant clusters never see the CA account keys or DNS credentials. If cert-manager's trust boundary is drawn in RBAC policy, Gardener's is drawn in network topology.
The project maintains an explicit "why not cert-manager" list, and the entries that matter for tenant TLS are concrete: existing certificates are reused when common name plus DNS names match, so duplicate requests don't burn rate limits; followCNAME is configurable per Certificate rather than per Issuer, which is exactly the granularity you want when each tenant delegates differently; and annotated sources include Istio Gateways and LoadBalancer Services alongside Ingress and Gateway API — the load-balancer case cert-manager simply doesn't cover.
The costs are the mirror image. First, DNS-01 is the only ACME game in town — there is no HTTP-01 escape hatch for the simple cases, so you operate the DNS companion and its credentials from day one. Second, the whole thing is Gardener-shaped: even used standalone, you adopt its extension concepts, DNS controller dependency, and operational model — a heavier lift than a Helm chart outside the Gardener ecosystem. Third, centralization concentrates the blast radius: one controller owns renewal everywhere it watches, so its availability and monitoring become platform-critical rather than per-cluster.
When does it win? The moment you run more than one cluster and the sentence "issuer secrets live next to tenant workloads" stops being acceptable. For a single-cluster PaaS, it is over-engineering. For a fleet, it is the architecture cert-manager's issue tracker wishes it had.
certctl: the lifecycle-platform bet
certctl attacks a different scope: not "certificates for this cluster" but "every certificate everywhere." It is a self-hosted control plane with twelve native CA connectors — Let's Encrypt and any ACME provider, a built-in local CA with sub-CA mode, step-ca, Vault PKI, EJBCA, AWS ACM PCA, Google CAS, DigiCert, Sectigo, GlobalSign, Entrust — plus an OpenSSL and shell-script adapter for anything custom. On the deployment side it claims fourteen production-ready target connectors, from NGINX, Caddy, Traefik, and Envoy through IIS, Java keystores, AWS ACM, Azure Key Vault, and F5. In agent mode — the default — private keys are generated on the host they serve and never touch the control plane, with server-side key generation available only behind an explicit demo-mode acknowledgment flag.
Two features are directly relevant to the tenant-TLS problem. First, multi-CA is native, so a Let's Encrypt outage or rate-limit event can fail over to another ACME CA instead of failing issuance — the only one of the three tools where the second CA is a configuration line rather than a migration project. Second, certctl runs an embedded ACME server (RFC 8555 plus RFC 9773 ARI for renewal-info) that existing clients can point at directly: cert-manager, certbot, and lego all work against it. That makes it adoptable incrementally — keep cert-manager in the clusters, move CA policy and failover into certctl — instead of demanding a flag day.
The honest caveats, all from the project's own docs: it is early-access software actively seeking design partners, the Kubernetes Secrets deployment connector is explicitly preview because the production client-go integration is incomplete, and it is source-available under BSL 1.1, not OSI open source — a licensing distinction your legal team gets a vote on. Evaluate it the way you'd evaluate any early-access control plane: against staging, with the rollback plan written first. But the direction is right — as lifetimes shrink toward 47 days and fleets mix clusters, VMs, and appliances, "one lifecycle for every cert" stops sounding ambitious and starts sounding necessary.
The default, stated plainly
Decision rules first, then the math that justifies them:
- Default to cert-manager on a single cluster or a small fleet where per-cluster installs are fine and RBAC-backed issuer secrets are acceptable. It is boring in the best way.
- Switch to Gardener cert-management when you run multiple clusters, when issuer credentials must not share a control plane with tenants, or when duplicate issuance has burned you once.
- Add certctl when your TLS footprint escapes Kubernetes, when you need a second CA behind Let's Encrypt, or when you want one renewal dashboard for clusters plus everything else. Its ACME-server mode means "add" need not mean "replace."
Now the scaling vignette the rules rest on. Assume each tenant brings one custom domain, one certificate each, renew-before at one-third of lifetime:
- N = 10 tenants. Any of the three works; HTTP-01 suffices unless someone needs a wildcard. Renewal load is about one certificate a week — a human could do it, though they shouldn't. Pick cert-manager and spend the saved effort on monitoring.
- N = 100 tenants. DNS-01 is now load-bearing: at this count you will have tenants behind their own CDNs and at least one wildcard request. Renewal load is roughly 12 renewals a week at 90-day lifetimes, doubling as profiles shorten. The limit that bites first is duplicates-per-exact-set during retry storms, not the per-domain 50 — cert-manager's weakest spot, mitigated by staging-first validation and duplicate alerting, and where Gardener's reuse starts looking attractive.
- N = 1,000 tenants. Renewal is continuous: ~115 renewals a week at 90 days, ~230 at 45 days — 16 to 33 a day, every day. The binding constraints become the 300-orders-per-3-hours account ceiling during correlated re-issuance (a bad config push, a mass migration) and DNS-credential sprawl across tenant zones. This is where centralized renewal state, cert reuse, and a second CA stop being nice-to-haves — the default flips from "cert-manager alone" to "cert-manager behind something that absorbs correlated failure," whether that's Gardener's reuse or certctl's multi-CA failover.
And regardless of tool or tenant count, the renewal checklist:
- Alert on certificate expiry below 21 days and on renewal attempts that fail twice — expiry alerts alone tell you after the automation already failed.
- Validate every config change against Let's Encrypt staging before production; staging limits exist so your retry storm happens where it's cheap.
- Track duplicate issuance per name set; a spike is the early warning for a 5-per-week lockout.
- Monitor the ACME account order rate; approaching 300 per 3 hours means a correlated event is underway.
- Keep one documented runbook for "tenant domain shows expired cert" that starts with "which issuer, which challenge, which credential" — because at 2 a.m. nobody should be discovering your TLS architecture for the first time.
The uncomfortable truth is that all three tools solve issuance well and renewal adequately — the gap between adequate and reliable is monitoring you build yourself. Certificate lifetimes are shrinking on a published schedule, tenant counts only grow, and the CA's rate limits don't care that your outage is urgent. Pick the tool whose failure modes you understand, instrument the renewal path like the production dependency it is, and your tenants will never learn what a padlock warning looks like on your platform.
Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own. Star the repo on GitHub or deploy your first app today.



