Fixing HubSpot API Rate Limit (429) and Gateway Timeout (504) Errors
Comprehensive SRE guide to resolving HubSpot API 429 Too Many Requests and 504 Timeouts. Learn to implement exponential backoff, batching, and query optimizatio
- Burst rate limits (100-150 requests per 10 seconds) are the primary cause of HubSpot 429 Too Many Requests errors.
- Daily API limits (250,000 to 1,000,000+) are strictly enforced based on your specific HubSpot subscription tier.
- 504 Gateway Timeouts typically occur during unoptimized Search API queries or when fetching massively nested associations.
- Implementing exponential backoff with jitter is the most resilient immediate fix for throttling.
- Migrating from single-record endpoints to batch endpoints reduces API overhead by up to 100x.
| Method | When to Use | Time to Implement | Risk / Cost |
|---|---|---|---|
| Exponential Backoff | Handling intermittent 429 Burst Limit errors | 1-2 Hours | Low |
| Batch Endpoints | Syncing large datasets (Contacts, Companies) | 4-6 Hours | Medium (Requires refactoring) |
| Query Optimization | Encountering frequent 504 Timeouts on Search API | 2-3 Hours | Low |
| API Limit Add-on | Consistently hitting the Daily limit (e.g., >500k calls) | 1 Day | Low Risk, High Financial Cost |
| Webhook Migration | Polling HubSpot for real-time changes | 1-2 Days | High (Architecture shift) |
Understanding the Error
When integrating enterprise systems with the HubSpot API at scale, encountering 429 Too Many Requests or 504 Gateway Timeout errors is a common bottleneck. These HTTP status codes signal that your application's request volume, frequency, or query complexity has exceeded the acceptable thresholds defined by HubSpot's infrastructure.
The Anatomy of a HubSpot 429 Error
HubSpot enforces two primary types of rate limits to ensure multi-tenant platform stability:
- Burst Limits (
TEN_SECONDLY_ROLLING): This limits the number of requests you can make within a rolling 10-second window. For Free and Starter tiers, this is typically 100 requests per 10 seconds. For Professional and Enterprise tiers, it is 150 requests per 10 seconds. - Daily Limits (
DAILY): This limits the total number of API calls within a 24-hour period (resetting at midnight UTC). This ranges from 250,000 to 1,000,000 based on your tier and purchased API add-ons.
When you hit a limit, HubSpot returns an exact payload indicating which limit was breached:
{
"status": "error",
"message": "You have reached your ten_secondly_rolling limit.",
"errorType": "RATE_LIMIT",
"correlationId": "a1b2c3d4-e5f6-7890-1234-56789abcdef0",
"policyName": "TEN_SECONDLY_ROLLING"
}
The Anatomy of a HubSpot 504 Timeout
Conversely, a 504 Gateway Timeout or 502 Bad Gateway occurs when a request takes too long for HubSpot's upstream servers to process. This rarely has to do with request volume and almost always points to payload size or query complexity, particularly on the CRM Search API or when retrieving deeply nested associations.
Step 1: Diagnose the Root Cause
Before refactoring code, you must determine whether you are hitting a burst limit, a daily limit, or a gateway timeout.
Inspecting API Response Headers
HubSpot includes rate limit data in the HTTP response headers of every successful API call. You can monitor these headers to preemptively detect exhaustion.
X-HubSpot-RateLimit-Daily: Your total daily allowance.X-HubSpot-RateLimit-Daily-Remaining: How many calls you have left today.X-HubSpot-RateLimit-Secondly: Your burst limit allowance.X-HubSpot-RateLimit-Secondly-Remaining: How many calls you have left in the current 10-second window.
Diagnostic Action: Log these headers in your application's telemetry (e.g., Datadog, Prometheus) to visualize usage spikes.
Step 2: Fix 429 Burst Limits (TEN_SECONDLY_ROLLING)
If you are hitting the 10-second rolling limit, your application is too aggressive.
Implement Exponential Backoff with Jitter
Never use a static sleep(10) when a 429 is encountered. If multiple worker threads pause for exactly 10 seconds and resume simultaneously, they will immediately trigger another 429 (the "thundering herd" problem).
Instead, use exponential backoff with jitter. This algorithm increases the wait time exponentially between retries and adds a random millisecond variance to spread out the retry requests.
Transition to Batch Endpoints
The most permanent fix for burst limits is to stop sending singular requests. HubSpot provides robust batch endpoints for CRMs.
Anti-Pattern (Causes 429s):
# Looping 100 times
POST /crm/v3/objects/contacts
Best Practice (1 API Call):
POST /crm/v3/objects/contacts/batch/create
# Send up to 100 contacts in a single JSON array payload
Batching reduces your API footprint by 99% when processing bulk records.
Step 3: Fix 429 Daily Limits (DAILY)
If you exhaust your daily limit, backoff algorithms will not help—your application will be blocked until midnight UTC.
- Audit Polling Behavior: Are you polling HubSpot every minute to check for new records? Replace this with HubSpot Webhooks. Let HubSpot push data to your endpoint only when a change actually occurs.
- Aggressive Caching: Cache HubSpot owners, properties, and pipeline stages locally (e.g., in Redis). These rarely change, and fetching them repeatedly wastes daily limits.
- Purchase an API Add-on: If your business logic genuinely requires millions of calls, you must purchase the HubSpot API Add-on to increase your limit to 1,000,000 calls per day.
Step 4: Fix 504 Gateway Timeouts
Timeouts require query optimization rather than request throttling.
- Reduce Payload Size: When using the CRM Search API, use the
propertiesarray to request only the specific fields you need. Do not fetch entire objects if you only need theemailandhs_object_id. - Simplify Search Filters: Complex
ORfilters across multiple associated objects take longer for HubSpot's backend elasticsearch clusters to process. Break complex queries into multiple simpler queries. - Decrease Limit/Pagination: If you are requesting
limit=100and timing out, drop the limit tolimit=50orlimit=25and paginate more frequently.
By systematically applying retry logic, utilizing batch endpoints, and optimizing query depth, you can ensure highly available, fault-tolerant integrations with the HubSpot platform.
Frequently Asked Questions
import requests
from tenacity import retry, stop_after_attempt, wait_exponential, retry_if_exception_type
import logging
logging.basicConfig(level=logging.INFO)
class RateLimitException(Exception):
pass
# Retry decorator: waits 2^x * 1 second between each retry, up to 10 seconds, max 5 attempts
@retry(
stop=stop_after_attempt(5),
wait=wait_exponential(multiplier=1, min=2, max=10),
retry=retry_if_exception_type(RateLimitException)
)
def fetch_hubspot_contacts(api_key):
url = "https://api.hubapi.com/crm/v3/objects/contacts"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
response = requests.get(url, headers=headers)
# Log rate limit headers for monitoring
daily_remaining = response.headers.get('X-HubSpot-RateLimit-Daily-Remaining')
logging.info(f"Daily limits remaining: {daily_remaining}")
if response.status_code == 429:
logging.warning("429 Too Many Requests encountered. Triggering backoff.")
raise RateLimitException("HubSpot API Rate Limit Exceeded")
if response.status_code in [502, 504]:
logging.error("Gateway Timeout. Query may be too complex.")
response.raise_for_status()
response.raise_for_status()
return response.json()
# Example usage
# data = fetch_hubspot_contacts('your_pat_token')Error Medic Editorial
Written by the Error Medic Site Reliability Engineering team. We specialize in debugging API integrations, scaling cloud infrastructure, and writing robust automation.