Introduction
Let's Encrypt imposes rate limits to prevent abuse and ensure fair access to their free certificate service. When you hit these limits, certificate issuance fails with specific error codes. Understanding the different limit types and their reset periods helps you plan certificate management and avoid blocking your deployments.
Symptoms
- Certbot fails with:
too many certificates already issued for: example.com - Error:
Rate limited by Let's Encrypt - Certificate renewal or issuance returns 429-style error
- ACME error code:
urn:ietf:params:acme:error:rateLimited - Multiple servers trying to get certificates for same domain
- CI/CD pipeline failing on certificate requests
Common Causes
- Requesting new certificates too frequently for same domain
- Testing certificate issuance without using
--dry-run - Multiple team members/servers requesting independently
- Certificate requests failing but still counting toward limits
- Bulk certificate issuance for many subdomains
- Renewing certificates manually instead of letting automation handle it
- Creating duplicate certificates for same names
Step-by-Step Fix
Step 1: Identify Which Rate Limit Was Hit
Let's Encrypt has several rate limits:
```bash # Check exact error message certbot certificates 2>&1 | grep -i "rate|limit"
# Common limits: # 50 certificates per registered domain per week # 10 duplicate certificates per week # 300 pending authorizations per account per week # 5 failed validations per account per hostname per hour # 20 certificates per account per week (Certificates per Account limit removed, but reorder limit exists) ```
```bash # Check your current certificates certbot certificates
# Count certificates for domain certbot certificates 2>/dev/null | grep -c "example.com" ```
Step 2: Use Existing Certificates
If you already have valid certificates:
```bash # List all certificates certbot certificates
# Copy existing certificate to new server scp /etc/letsencrypt/live/example.com/* newserver:/etc/ssl/certs/
# Or use certbot's certificate sharing certbot certonly --cert-name example.com -d example.com,www.example.com # Then copy the live directory ```
Step 3: Use Dry-Run for Testing
```bash # Always test with dry-run - doesn't count toward limits certbot certonly --dry-run -d example.com
# Test renewal certbot renew --dry-run
# Test certificate expansion certbot certonly --dry-run --cert-name example.com -d example.com,www.example.com,api.example.com --expand ```
Step 4: Wait for Limit Reset
```bash # Rate limits reset on weekly basis (mostly) # 50 certificates per domain per week - resets weekly # 5 failed validations per hostname per hour - resets hourly
# Check when you can request again # Visit: https://crt.sh/?q=.example.com # Shows certificate issuance history
# Calculate wait time based on first issuance in current week ```
Step 5: Use Alternative Methods
Expand existing certificate instead of new request:
```bash # Add subdomains to existing certificate (doesn't count as new cert) certbot certonly --cert-name example.com \ -d example.com,www.example.com,api.example.com \ --expand
# This modifies existing certificate, not creates new one ```
Use wildcard certificate:
```bash # Single wildcard cert covers all subdomains certbot certonly --dns-cloudflare \ -d "*.example.com" -d "example.com"
# Uses DNS challenge instead of HTTP-01 # Single certificate covers unlimited subdomains ```
Use different account:
```bash # Register new ACME account (separate rate limits) certbot register --email new-email@example.com
# Or use acme.sh with different account acme.sh --register-account --email new-email@example.com ```
Step 6: Use Alternative Certificate Providers
```bash # ZeroSSL - free alternative with similar ACME support acme.sh --issue -d example.com --server zerossl
# Buypass - Norwegian CA with free certificates acme.sh --issue -d example.com --server buypass
# Google Trust Services acme.sh --issue -d example.com --server google ```
Step 7: Plan Certificate Strategy
```bash # Don't request certificates repeatedly # Set up automation once and let it handle renewals
# For multiple servers, use centralized certificate management: # - Generate on one server # - Distribute to others via config management # - Or use load balancer for SSL termination
# Use --keep-until-expiring flag certbot certonly --keep-until-expiring -d example.com ```
Step 8: Monitor Rate Limit Status
```bash # Track certificate issuance at crt.sh curl -s "https://crt.sh/?q=%.example.com&output=json" | jq 'length'
# Set up monitoring for certificate count # Alert when approaching limits
# Use Let's Encrypt's staging environment for testing # Staging has much higher limits certbot certonly --staging -d example.com ```
Common Pitfalls
- Testing without
--dry-runrepeatedly - Multiple servers requesting same certificate independently
- Requesting new cert when renewal would suffice
- Using staging certificates in production (browser warnings)
- Not tracking certificate issuance history
- Panic-requesting multiple times when first fails
Best Practices
- Always use
--dry-runfor testing - Use wildcard certificates for multiple subdomains
- Centralize certificate management for multiple servers
- Set up automated renewal, don't request manually
- Monitor certificate issuance at crt.sh
- Use staging environment (
--staging) for initial setup testing - Keep existing certificates instead of requesting new ones
- Plan certificate strategy for deployments
Related Issues
- Let's Encrypt Challenge Failed
- SSL Certificate Expired
- SSL Auto-Renewal Not Working
- ACME HTTP-01 Challenge Failing