TLS troubleshooting

Let's Encrypt Rate Limit: Too Many Certificates

cert-manager stops issuing, and the Order shows a rateLimited error from Let's Encrypt. The cause is almost always the same: the cluster keeps requesting a certificate for a name set that has already been issued several times this week. This guide shows how to read the error, which limit it is, how to stop the retry loop, and how to reduce issuance so it stays under the limit.

By , Founder at SeaGit

·

Key takeaways

  • Read the retry time in the error. It is the earliest moment the next order for that limit can succeed.
  • The exact set limit is 5 certificates per 7 days for one set of names, global across all accounts, with no override.
  • The registered domain limit is 50 per 7 days, and it can be raised by an override request.
  • Stop the loop first. Each new Certificate, Order or delete-and-recreate counts toward the limit.
  • One Certificate per name set, a wildcard where it fits, and copied Secrets keep issuance low.

Read the error

Let's Encrypt enforces its limits when an order is created, so the refusal appears in the cert-manager Order, not in the Ingress or the application. The text has three parts: the error type, the count that is full, and the retry time. The count and the phrase after it name the limit.

text
# Illustrative error text, shape only (not from a real account)
urn:ietf:params:acme:error:rateLimited: too many certificates (5) already issued
for this exact set of identifiers in the last 168h0m0s, retry after 2026-10-17 09:00:00 UTC
Shape of the refusal. The count in brackets is the number of issuances already in the window. Your numbers will differ.

The phrase "for this exact set of identifiers" points to the exact set limit. A message about a registered domain points to the domain limit. A message about too many failed authorizations points to a different limit, which comes from validation failures, not from issuance volume. Fix the validation error before you retry, or the failures will fill that limit too.

Do not treat the retry time as a schedule for your automation. Retrying earlier will be refused again. Retrying after the retry time works only if the loop that caused the first refusal has stopped.

Too many certificates already issued for exact set of domains

This is the most common rate limit error from cert-manager. The Let's Encrypt documentation names it New Certificates per Exact Set of Identifiers. It allows up to 5 certificates for the same exact set of identifiers every 7 days. The set is exact: the same names, and no extra or missing names. Two certificates for example.com and www.example.comare one set. A certificate for example.com alone is a different set.

The limit is global. All new orders for the set count, whichever ACME account submits them. Two clusters that each request the same names share one budget. The documentation says the ability to issue for the same set refills at one certificate every 34 hours, so five quick issuances take about a week to clear.

There is no override for this limit. The only real fixes are to issue the same name set less often, or to change the set so it is new. The next sections show how.

Which limit you hit

Let's Encrypt groups its limits into account, domain and identifier scopes. The three that cause most cert-manager failures are below. The figures are from the Let's Encrypt rate limit page, checked October 2026, and they can change, so confirm them on that page before you plan around them.

LimitDocumented valueOverride
New Certificates per Exact Set of Identifiers5 per 7 days, global. Refill 1 per 34 hours.None
New Certificates per Registered Domain50 per 7 days, global. Refill 1 per 202 minutes.Request form, for the domain or an account
New Orders per Account300 per 3 hours. Refill 1 per 36 seconds.See the rate limit page
A new order must pass three Let's Encrypt limits. The exact set limit has no overrideA cert-manager order enters on the left. It is checked against three limits in turn: orders per account, certificates per registered domain, and certificates per exact set of identifiers. If any limit is full, the order is refused with a retry time. The exact set limit is marked as having no override.cert-managernew orderOrders per account300 per 3 hours, refill 1 per 36 s (per ACME account)Certificates per registered domain50 per 7 days, refill 1 per 202 min (global, override by form)Certificates per exact set of identifiers5 per 7 days, refill 1 per 34 hours (global, no override)Issuedor refused with retry timeA renewal sent through ARI is exempt from all of these. Other renewals still count against the exact set limit.
Each new order is checked against the account, domain and exact set limits. A refusal at any gate returns a retry time, and only the exact set gate has no override.

The renewal rule matters. Let's Encrypt exempts renewals sent through ACME Renewal Info (ARI) from all rate limits. Older renewal detection counts an order for the same exact set as a renewal, and such orders can still hit limits. Whether your cert-manager sends ARI depends on its version and configuration, so read its release notes before you assume renewals are free.

Stop the retry loop

Before you change anything else, find out what keeps asking for certificates. cert-manager retries a failed Order with backoff, and a Certificate that is deleted and recreated starts over with a new Order. Either one adds to the count. Start with the Certificate, then its request, order and challenge objects:

shell
kubectl describe certificate example-com -n web
kubectl get certificaterequests,orders,challenges -n web
The Certificate condition and the Order or Challenge show the last refusal and its retry time.
shell
# The Order records the refusal from the ACME server
kubectl describe order -n web example-com-tls-1234567890-1
Substitute the Order name from the previous output. The Order status carries the ACME error text.
shell
# Summary of the Certificate, its request and its last failure (cmctl)
cmctl status certificate example-com -n web
cmctl summarises the same chain in one view, if you have the cert-manager CLI installed.

Then list every Certificate, to find duplicates. Two Certificates for the same DNS list in different namespaces are two separate issuance paths for one set:

shell
# Every Certificate in the cluster, with its secret and names
kubectl get certificates -A -o custom-columns=NS:.metadata.namespace,NAME:.metadata.name,SECRET:.spec.secretName,DNS:.spec.dnsNames
One line per Certificate. Look for identical dnsNames values.

Pause the source of the loop before you retry. Remove a GitOps application that re-creates the Certificate, or scale down the controller that keeps deleting the Secret. Do not delete the Secret to force a fresh issuance, because that starts a new order under the same limit.

cert-manager settings that matter

Use the staging issuer for every new Certificate until it reaches Ready. The staging server is a separate Let's Encrypt environment with its own limits. Its certificates are not trusted by browsers, which is fine for checking the chain, the DNS or HTTP challenge, and the Ingress wiring:

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-staging
spec:
  acme:
    # Staging: separate rate limits, certificates not trusted by browsers
    server: https://acme-staging-v02.api.letsencrypt.org/directory
    email: platform@example.com
    privateKeySecretRef:
      name: letsencrypt-staging-account
    solvers:
    - http01:
        ingress:
          ingressClassName: nginx
A staging ClusterIssuer. The server URL is the staging directory.

When the staging test passes, point the Certificate at a production issuer. The production directory is the same URL without -staging:

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: platform@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-account
    solvers:
    - http01:
        ingress:
          ingressClassName: nginx
The production issuer. Create it after staging has issued a certificate for the same names.

On the Certificate, set the lifetime and the renewal window explicitly. duration is the requested certificate lifetime and renewBefore sets how long before expiry the renewal starts. A short window with a retry loop means many attempts close together, so keep the default or a clear value and do not set it to the expiry date:

yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com
  namespace: web
spec:
  secretName: example-com-tls
  dnsNames:
  - example.com
  - www.example.com
  issuerRef:
    name: letsencrypt-staging
    kind: ClusterIssuer
  duration: 2160h     # 90 days
  renewBefore: 360h   # renew 15 days before expiry
A Certificate with explicit duration and renewBefore. Use one Certificate per name set.

Keep one Certificate per name set in the whole cluster. If two Ingresses request the same names, reference the same Secret from both, rather than letting each create its own Certificate. A duplicate Certificate is a second order for the same set.

Reduce how often you issue

The lasting fix is fewer orders for the same set. There are three ways to get there, and they combine well.

Use one wildcard where the names share a parent

A wildcard certificate such as *.example.com covers every single-label subdomain with one exact set. Let's Encrypt requires the DNS-01 challenge for wildcard names, so the issuer needs a DNS solver. The example below uses Route 53, with a placeholder hosted zone ID:

yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod-dns01
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: platform@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-dns-account
    solvers:
    - dns01:
        route53:
          region: us-east-1
          hostedZoneID: <your-hosted-zone-id>
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-example-com
  namespace: platform-tls
spec:
  secretName: wildcard-example-com-tls
  dnsNames:
  - "*.example.com"
  issuerRef:
    name: letsencrypt-prod-dns01
    kind: ClusterIssuer
A DNS-01 issuer and a wildcard Certificate. Replace the zone ID and the email. Other DNS providers use their own solver block.

A wildcard does not escape the registered domain limit. Every certificate for the domain still counts there, so a wildcard saves budget only on the exact set limit.

Issue once, copy the Secret

Secrets are namespaced, so a Certificate in one namespace cannot populate another. A common mistake is to create the same Certificate in every namespace. The cleaner pattern is one Certificate in one trusted namespace, then a Secret-copying controller that places the resulting Secret where it is needed. Only copy within a trust boundary, because the copy holds the private key.

Four namespaces that each request the same certificate use four orders for one identifier set. One Certificate and a copied Secret use oneLeft panel: four namespaces each hold a Certificate for the same hostnames, and each sends an order for the same exact set. Right panel: one Certificate in one namespace sends one order, and the resulting Secret is copied to the other namespaces.One Certificate per namespacens-weborder #1ns-apiorder #2ns-adminorder #3ns-jobsorder #44 orders, same exact setOne Certificate, one Secret copiedCertificate in ns-webone orderTLS Secretns-api copyns-admin copyns-jobs copy1 order, copies reuse the same issued certificate
Four namespaces with their own Certificates send four orders for one set. One Certificate and copied Secrets send one order.

Fix the validation failures first

A challenge that fails repeatedly fills the authorization failure limit and wastes time. Check the Challenge objects and the ingress path before you retry. An HTTP-01 challenge needs the ingress class and the DNS record to point at the controller. A DNS-01 challenge needs the solver credentials and the zone.

While the limit is full

Once the exact set limit refuses an order, nothing you change in the cluster lets that order through before the retry time. Use the wait for work that does not need a certificate:

  • Serve a temporary certificate with a different name set. A new name set has its own budget. A short-lived test hostname, issued on staging, lets you check the routes while production waits.
  • Keep the existing Secret in service. A Certificate that still has a valid certificate in its Secret keeps serving until it expires. A failed renewal does not remove the old Secret, so check the expiry date before you act.
  • Fix the cause before the retry time. Stop the duplicate Certificates and the GitOps loop now, so the first order after the retry time is the only one.

Avoid the common shortcut of creating a second Certificate with a slightly different name, such as an extra www hostname. It looks like a workaround, but it is a new exact set that consumes its own budget and leaves the original set still blocked.

A worked example

The example is illustrative. The namespace names and counts are invented to show the order of the checks. Suppose a platform team sees an exact set refusal for the same two hostnames in three namespaces. The list command returns three Certificates with identical dnsNames. Each one was created by a copy of the same Helm chart, and each one has its own cert-manager Order. Over one week, the chart re-creates them after each release, so the set is requested five times and the sixth order is refused.

The fix has three parts. First, the team keeps one Certificate in a platform namespace and copies its Secret to the two namespaces that need it. Second, the chart stops creating a Certificate in each release namespace and references the shared Secret instead. Third, the team adds an alert on Certificate Ready=False, so the next refusal is seen the day it happens. None of these changes needs an override, and the retry time is respected.

The lesson is that the limit counts orders, not the number of Secrets. A cluster that looks quiet can still issue the same set many times, because a chart or a controller does it on every deploy. Count orders per name set before you assume a problem is elsewhere.

Request an override

The registered domain limit can be raised. The override request form is linked from the rate limit page, and it asks for the registered domain or the account, the volume you need, and the reason. The form is at the Let's Encrypt override form. Requests take time, so plan for a delay.

An override is not a fix for a loop. It only moves the ceiling. Ask for one after you have stopped the source of the extra orders and can show the steady volume you expect. The exact set limit has no override, so an override request does nothing for a refused exact set.

Prevention checklist

  • New Certificates are tested on the staging issuer until Ready.
  • Each name set has one Certificate in the cluster. Duplicates are found with the list command above.
  • Wildcards are used where the names share a parent domain, with DNS-01 solved by a managed solver.
  • Secrets are copied from one trusted namespace, not re-issued in each namespace.
  • GitOps does not re-create a Certificate in a loop, and no script deletes Secrets to force renewal.
  • Alerts fire on Certificate Ready=False, with the Order error text in the alert.

How SeaGit handles this

SeaGit clusters run cert-manager inside your AWS account, and the platform issues Let's Encrypt certificates for the Ingress routes it creates. Two behaviours in the code bear on the rules above:

  • ALB-terminated routes skip Let's Encrypt. When an Ingress uses the ALB class or a certificate ARN annotation, TLS is served by an ACM certificate on the load balancer. The platform does not ask Let's Encrypt for a certificate for that route, which avoids an issuance the cluster would never use.
  • The app templates ship a staging issuer. The app template examples include a letsencrypt-staging ClusterIssuer that points at the staging directory, which is the safe place to test a new route first.

Whatever platform you run, the same limits apply to the certificates you request. For the cluster model and where certificates are issued, see the certificates documentation, and for wildcard DNS setup see the wildcard TLS guide.

Frequently asked questions

Let's Encrypt rate limit: FAQ

What does "too many certificates already issued for exact set of domains" mean?

Let's Encrypt has issued five certificates for exactly the same list of names in the last seven days, so it refuses another one until the oldest issuance ages out. The limit is global, so it counts orders from every account, and it has no override. The fix is to issue that name set less often, or to change the name set.

How long until a Let's Encrypt rate limit resets?

The limits use a rolling window. For the exact set limit, the documentation says the ability to issue refills at a rate of one certificate every 34 hours. For the registered domain limit, it refills at one certificate every 202 minutes. The retry time in the error message is the earliest moment the next order can succeed.

Does renewing a certificate count against the limit?

It depends on how the renewal is detected. Renewals sent through ACME Renewal Info (ARI) are exempt from all rate limits. Older renewal logic treats an order for the same exact set as a renewal, and such orders may still be subject to certain limits. Use a cert-manager version and ACME configuration that send ARI when your release notes say it is supported.

Can I get an override for the exact set limit?

No. Let's Encrypt states that it does not offer overrides for the exact set of identifiers limit. It does offer an override request form for the registered domain limit and for accounts. Plan the name set so it does not need one.

Will a staging issuer avoid the production limits?

Yes, for testing. Let's Encrypt runs a separate staging environment with its own rate limits, so test issuance does not use up the production budget. Staging certificates are not trusted by browsers, so switch the issuer back to production only after the Certificate reaches Ready on staging.

Should I use wildcard certificates to avoid the limit?

A wildcard covers many hostnames with one certificate, which reduces the number of exact sets you request. Let's Encrypt requires the DNS-01 challenge for wildcard names. A wildcard does not avoid the registered domain limit, because every certificate for that domain still counts against it.

Sources

Checked 10 October 2026.

  1. Let's Encrypt: Rate Limits — the limit names, the 5 per exact set and 50 per registered domain numbers, refill rates, ARI renewal exemption and the override form
  2. cert-manager: ACME issuer configuration — the ACME server URL for the staging environment and the issuer fields
  3. cert-manager: Certificate resource — secretName, dnsNames, duration and renewBefore on the Certificate resource

Read next