Fix Let's Encrypt "too many certificates" Rate Limits
Fix Let’s Encrypt rate limit errors such as too many certificates already issued for this exact set of domains and too many failed authorizations: stop reissuing on every deploy, persist certificates, and use the staging environment.
Problem statement
Certbot, Caddy, or Traefik suddenly cannot get a certificate:
An unexpected error occurred:
Error creating new order :: too many certificates (5) already issued for this exact set
of domains in the last 168 hours: example.com,www.example.com, retry after 2026-10-08T14:00:00Z
or too many failed authorizations recently. Let's Encrypt limits how often the same names can be issued and how many validations may fail. Normal use, renewing every 60 days or so, never comes close. Hitting a limit almost always means certificates are being thrown away and requested again, typically because a container's certificate storage is not persistent or a deploy script runs Certbot on every release.
- Wait until the
retry aftertime; limits cannot be reset by support for normal cases. - Persist certificate storage: a volume for
/etc/letsencrypt, Caddy's/data, or Traefik'sacme.json. - Never run
certbot certonlyunconditionally in deploy scripts; usecertbot renew, which only renews when due. - Use the staging environment (
--stagingor--dry-run) while testing configuration. - If you are blocked now and need HTTPS, issue for a slightly different set of names or use a temporary certificate.
Step-by-step solution
1. Identify which limit you hit
The main limits for Let's Encrypt production (check the current documentation, as values change):
- Duplicate certificate: 5 per week for the exact same set of names.
- Certificates per registered domain: 50 per week for
example.comand all its subdomains. - Failed validations: 5 per hostname, per account, per hour.
- New orders: 300 per account per 3 hours.
The error text names the limit and gives a retry after time. See what was issued recently in Certificate Transparency logs, for example on crt.sh:
curl -s "https://crt.sh/?q=example.com&output=json" | python3 -c "import sys,json; [print(c['not_before'], c['name_value'].replace(chr(10), ',')) for c in json.load(sys.stdin)[:15]]"
Several certificates with identical names a day apart confirm the reissue loop.
2. Persist certificate storage
In Docker, a reverse proxy without a volume for its ACME data starts empty every time the container is recreated:
services:
caddy:
image: caddy:2
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy_data:/data # certificates and ACME account
- caddy_config:/config
certbot:
image: certbot/certbot
volumes:
- letsencrypt:/etc/letsencrypt
volumes:
caddy_data:
caddy_config:
letsencrypt:
For Traefik, store acme.json on a volume with 600 permissions. On Kubernetes with cert-manager, certificates live in Secrets and survive pod restarts, but deleting and recreating Certificate resources or namespaces reissues them.
3. Remove unconditional issuance from deploys
This in a deploy script reissues on every release:
certbot certonly --nginx -d example.com -d www.example.com --non-interactive --agree-tos # avoid in deploys
Use certbot renew, which does nothing unless a certificate is within 30 days of expiry, and let the packaged systemd timer run it twice a day:
systemctl list-timers | grep certbot
sudo certbot renew --dry-run
If you must ensure a certificate exists, check first and only issue when missing, adding --keep-until-expiring.
4. Test against staging
Let's Encrypt's staging environment has much higher limits and issues untrusted certificates, perfect for testing configuration:
sudo certbot certonly --staging --webroot -w /var/www/letsencrypt -d example.com
For Caddy, set acme_ca https://acme-staging-v02.api.letsencrypt.org/directory in the global options while experimenting; for Traefik, set caServer on the resolver. Switch to production only once staging succeeds, and delete the staging certificates so they are not served.
5. If you are blocked right now
- The duplicate limit applies to the exact set of names. Issuing for
example.comalone, or adding a new subdomain to the set, is a different set. Use this sparingly. - Fall back to another ACME CA such as ZeroSSL or Google Trust Services (Caddy does this automatically).
- Put Cloudflare's proxy in front with its edge certificate while you wait.
Verification check: recreate the proxy container (docker compose up -d --force-recreate caddy) and confirm the logs show the existing certificate being loaded, not a new order. Check crt.sh a week later: there should be no new certificates until renewal.
Explanation
Let's Encrypt is a free public service that issues millions of certificates a day, and the limits protect it from runaway automation. They are generous for anyone who keeps certificates between restarts: a certificate lasts 90 days (shorter lifetimes are being introduced) and clients renew around two thirds of the way through. Containers changed the failure mode: a reverse proxy that obtains certificates automatically will happily request a new one every time it starts with empty storage, and fast deploy cycles can do that five times in an afternoon.
Edge cases / notes
- Preview environments per pull request on subdomains of one domain count toward the 50-per-registered-domain limit. Use a wildcard certificate for preview hosts.
- Multiple servers behind a load balancer should share one certificate (from shared storage or a central issuer) rather than each requesting their own.
- Account keys. Losing the ACME account also loses any rate-limit adjustments tied to it. Persist the whole directory.
- Renewal exemption. Renewals of an existing certificate are exempt from some limits, another reason to keep the original.
Next steps
- If validation itself fails, see Fix Certbot Challenge Failed.
- Caddy handles issuance and renewal automatically when its data is persisted: Deploy Django With Caddy and Automatic HTTPS.
FAQ
How long does a Let's Encrypt rate limit last?
Most limits use a sliding window of a week or an hour. The error message gives the exact retry time.
Can Let's Encrypt support lift the limit?
Not for duplicate certificates from misconfiguration. Larger organisations can request adjustments to some limits in advance.
Does certbot renew count toward the duplicate limit?
Only when it actually renews. It skips certificates that are not close to expiry.
Does the staging environment have limits?
Yes, but much higher. Its certificates are not trusted by browsers.