Rate Limiting Commands & Usage
Use certbot —dry-run for testing and —staging for development to avoid consuming production rate limits. This page covers command patterns for testing, production renewal, and monitoring so you stay within Let’s Encrypt’s quotas and avoid unnecessary limit consumption.
Rate Limiting Commands & Usage
Section titled “Rate Limiting Commands & Usage”TL;DR: Use certbot --dry-run for testing and --staging for development to avoid consuming production rate limits—monitor issuance via Certificate Transparency logs and never use --force-renewal unnecessarily to preserve your 5 certificates per exact set per 7 days quota.
Need help with ACME? Ask Axel Axelspire AI bot with own augmented memory for all ACME/certbot.
Overview
Section titled “Overview”Certificate automation commands directly impact rate limit consumption, making proper command usage critical for preventing service disruptions. This guide provides practical command patterns for testing, development, production operations, and monitoring that help teams stay within Let’s Encrypt’s rate constraints. Understanding which commands consume rate limits and which provide safe testing enables reliable certificate management.
Production teams must distinguish between operations that consume rate limits and those that don’t. Dry-run commands test configurations without requesting actual certificates, while staging environment requests use separate rate limit buckets with higher thresholds. Monitoring commands help track issuance rates and identify approaching limits before they cause operational issues.
Enterprise deployments benefit from automated monitoring scripts, renewal optimization strategies, and emergency recovery procedures. Implementing proper command patterns prevents common scenarios like exhausting the exact set of identifiers limit during troubleshooting or consuming new orders quota during bulk certificate operations.
Core Rate Limiting Commands
Section titled “Core Rate Limiting Commands”Certificate Management with Certbot
Section titled “Certificate Management with Certbot”The certbot command is susceptible to rate limiting issues when dealing with Let’s Encrypt’s certificate issuance limits.
Key Limits to Remember:
- 50 certificates per registered domain per 7 days (refills at 1 per 202 minutes)
- 5 certificates per exact set of identifiers per 7 days (refills at 1 per 34 hours)
- 5 authorization failures per identifier per hour (refills at 1 per 12 minutes)
# Basic certificate requestcertbot certonly --webroot -w /var/www/html -d example.com
# Check current certificatescertbot certificates
# Test configuration without requesting certificates (ALWAYS DO THIS FIRST)certbot --dry-run certonly --webroot -w /var/www/html -d example.comCommon Issue Pattern:
When troubleshooting SSL configurations, repeatedly running certbot to fix issues can quickly consume your exact set of identifiers limit (5 per 7 days). This creates a cascading problem where each failed attempt with the same domain set consumes your quota.
Best Practice Implementation:
#!/bin/bash# Always test first with dry-runcertbot --dry-run certonly --webroot -w /var/www/html -d example.com
# Only proceed if dry-run succeedsif [ $? -eq 0 ]; then echo "Dry run successful, proceeding with actual certificate request" certbot certonly --webroot -w /var/www/html -d example.comelse echo "Dry run failed - fix issues before requesting actual certificate" exit 1fiDevelopment and Testing Commands
Section titled “Development and Testing Commands”Staging Environment Setup
Section titled “Staging Environment Setup”Always use Let’s Encrypt’s staging environment for testing. The staging environment has significantly higher rate limits and is designed for development and troubleshooting.
# Use staging server for testing (RECOMMENDED for all development)certbot certonly --staging \ --webroot -w /var/www/html \ -d test.example.com \ --email admin@example.com
# Test staging renewalcertbot renew --staging --dry-run
# Production deployment ONLY after staging validationcertbot certonly --webroot -w /var/www/html -d example.com --email admin@example.comDevelopment Workflow Commands
Section titled “Development Workflow Commands”# Step 1: Initial testing with staging + dry-runcertbot certonly --staging --dry-run \ --webroot -w /var/www/html -d dev.example.com
# Step 2: Get staging certificate (doesn't affect production limits)certbot certonly --staging \ --webroot -w /var/www/html -d dev.example.com
# Step 3: Production certificate (only after staging success)certbot certonly \ --webroot -w /var/www/html -d example.comAdvanced Certificate Renewal Commands
Section titled “Advanced Certificate Renewal Commands”Force Renewal Considerations
Section titled “Force Renewal Considerations”The --force-renewal flag forces certificate renewal regardless of expiry date. Use with extreme caution due to its impact on rate limits.
# Standard renewal (recommended - only renews if needed)certbot renew
# Force renewal (USE WITH CAUTION)certbot renew --force-renewal
# Force renewal for specific certificate (USE WITH CAUTION)certbot renew --cert-name example.com --force-renewalCritical Warning: Using --force-renewal unnecessarily:
- Causes excessive load on Let’s Encrypt systems
- Consumes your Exact Set of Identifiers limit (5 per 7 days)
- Reserve this flag for genuine emergencies only
Enterprise Implementation Pattern:
#!/bin/bash# Enterprise-grade renewal script with rate limit protection
CERT_NAME="example.com"DAYS_BEFORE_EXPIRY=30
# Check if renewal is actually neededCERT_INFO=$(certbot certificates --cert-name "$CERT_NAME" 2>/dev/null)EXPIRY_DATE=$(echo "$CERT_INFO" | grep "Expiry Date" | awk '{print $3, $4, $5, $6}')
if [ -z "$EXPIRY_DATE" ]; then echo "Certificate not found: $CERT_NAME" exit 1fi
EXPIRY_EPOCH=$(date -d "$EXPIRY_DATE" +%s)NOW_EPOCH=$(date +%s)DAYS_TO_EXPIRY=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
echo "Certificate expires in $DAYS_TO_EXPIRY days"
if [ $DAYS_TO_EXPIRY -lt $DAYS_BEFORE_EXPIRY ]; then echo "Renewal needed, proceeding..." certbot renew --cert-name "$CERT_NAME"else echo "Certificate still valid for $DAYS_TO_EXPIRY days - no renewal needed"fiRate Limit Monitoring Commands
Section titled “Rate Limit Monitoring Commands”Status and Monitoring
Section titled “Status and Monitoring”# Check current certificate statuscertbot certificates
# View detailed certificate informationopenssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -text -noout
# Check certificate expiry date specificallyopenssl x509 -in /etc/letsencrypt/live/example.com/cert.pem -enddate -noout
# Monitor rate limit errors in logsgrep -i "rate limit" /var/log/letsencrypt/letsencrypt.log | tail -20Check Issued Certificates via Certificate Transparency
Section titled “Check Issued Certificates via Certificate Transparency”#!/bin/bash# Check how many certificates have been issued for your domain# Uses Certificate Transparency logs via crt.sh
DOMAIN="example.com"
echo "Checking certificates issued for $DOMAIN in the last 7 days..."
# Query crt.sh (public Certificate Transparency log aggregator)curl -s "https://crt.sh/?q=${DOMAIN}&output=json" | \ jq '[.[] | select(.not_before > (now - 604800 | todate))] | length' 2>/dev/null
echo "Remember: Limit is 50 certificates per registered domain per 7 days"Automated Monitoring Script
Section titled “Automated Monitoring Script”#!/bin/bash# Rate limit monitoring for enterprise environments
DOMAIN="example.com"LOG_FILE="/var/log/certbot-monitor.log"ALERT_THRESHOLD=40 # Alert at 80% of 50 limit
check_rate_limits() { local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
# Count certificates issued in last 7 days via crt.sh local count=$(curl -s "https://crt.sh/?q=${DOMAIN}&output=json" | \ jq '[.[] | select(.not_before > (now - 604800 | todate))] | length' 2>/dev/null)
if [ -z "$count" ] || [ "$count" = "null" ]; then echo "$timestamp: ERROR - Could not query crt.sh" >> $LOG_FILE return 1 fi
echo "$timestamp: Certificates issued this week for $DOMAIN: $count/50" >> $LOG_FILE
if [ "$count" -ge "$ALERT_THRESHOLD" ]; then echo "$timestamp: WARNING - Approaching rate limit (${count}/50)" >> $LOG_FILE # Send alert to monitoring system curl -X POST "https://monitoring.example.com/alert" \ -H "Content-Type: application/json" \ -d "{\"severity\":\"warning\",\"message\":\"Rate limit warning for $DOMAIN: ${count}/50 certificates\"}" \ 2>/dev/null fi}
check_rate_limitsTroubleshooting Commands
Section titled “Troubleshooting Commands”Rate Limit Recovery
Section titled “Rate Limit Recovery”When you’ve hit a rate limit, Let’s Encrypt cannot manually reset it. Your capacity will gradually refill over time.
# Check if rate limited (use dry-run to test without consuming limits)certbot certonly --dry-run --webroot -w /var/www/html -d example.com
# View recent certbot activityjournalctl -u certbot --since "1 week ago" | grep -i "rate\|limit\|error"
# Check certbot logs for rate limit messagesgrep -E "(rate limit|too many)" /var/log/letsencrypt/letsencrypt.log
# Clean up duplicate certificates (if any)certbot delete --cert-name example.com-0001Workaround for Exact Set of Identifiers Limit
Section titled “Workaround for Exact Set of Identifiers Limit”If you’ve hit the “5 certificates per exact set of identifiers” limit, you can request a certificate with a different set of identifiers:
# Original request (hit limit)# certbot certonly -d example.com -d www.example.com
# Workaround: Add another identifier to create a different setcertbot certonly -d example.com -d www.example.com -d blog.example.com
# Note: This new certificate will be subject to:# - New Orders per Account limit (300 per 3 hours)# - New Certificates per Registered Domain limit (50 per 7 days)Emergency Procedures
Section titled “Emergency Procedures”# If rate limited, optimize renewal configuration# Renew earlier (default is 30 days before expiry)echo "renew_before_expiry = 45 days" >> /etc/letsencrypt/renewal/example.com.conf
# Set up automated renewal checkecho "0 0,12 * * * root certbot renew --quiet" > /etc/cron.d/certbot-renew
# Monitor for when rate limit resets# Rate limit error messages include retry time, e.g.:# "retry after 2025-01-28 15:30:00 UTC"Command Quick Reference
Section titled “Command Quick Reference”| Task | Command | Notes |
|---|---|---|
| Test configuration | certbot --dry-run certonly -d example.com | Always do this first |
| Use staging | certbot --staging certonly -d example.com | For development/testing |
| Check certificates | certbot certificates | Shows expiry dates |
| Standard renewal | certbot renew | Only renews if needed |
| View logs | journalctl -u certbot | Check for errors |
| Check CT logs | curl "https://crt.sh/?q=example.com" | Count recent issuances |
Important Reminders
Section titled “Important Reminders”- Always use
--dry-runfirst before actual certificate requests - Use staging environment for all development and troubleshooting
- Monitor your issuance rate via Certificate Transparency logs
- Avoid
--force-renewalunless absolutely necessary - Revoking certificates does NOT reset rate limits
- Rate limit errors include
Retry-After- parse and respect this header
Related Documentation
Section titled “Related Documentation”- Rate Limiting Overview - Core concepts and quick reference
- Rate Limiting API Reference - Endpoint limits and integration
- Rate Limiting Troubleshooting - Error resolution and recovery
- Certificate Lifecycle Management - Automated renewal strategies
- Certbot Installation - Installing and configuring Certbot
- HTTP-01 Challenge Commands - Challenge validation commands