## TL;DR
During a bulk import, HubSpot fires webhooks faster than your endpoint can handle, your endpoint answers 429, and HubSpot backs off and retries. The fix: stop doing the work inside the webhook handler. Accept the batch, return 200 fast, and process it from a queue. If you must shed load, shed it gracefully and make your handler idempotent so retries are harmless.

## The error
```text
POST /webhooks/hubspot returned 429 Too Many Requests
HubSpot webhook subscription: delivery delayed, retrying
```

## Steps
1. Confirm the throttle is yours. Check your logs during the import window. Expected output: your app returning 429 while CPU or the database is saturated.
2. Slim the handler. Move everything except "store the batch and ack" into a background worker. Expected output: handler response time drops under a second.
3. Return 200 on receipt, not on completion. Expected output: HubSpot marks the batch delivered and stops retrying it.
4. Make processing idempotent. Key each record by its HubSpot object ID so a retried batch does not create duplicates. Expected output: reprocessing the same batch changes nothing.
5. Re-run a small import batch and watch. Expected output: webhooks deliver cleanly with no 429s in your logs.

## When to use
- Webhook 429s appear only during bulk imports or large syncs
- Your endpoint is healthy at normal volume but falls over in bursts
- HubSpot shows delayed or retried webhook deliveries

## When not to use
- HubSpot's own API (not your webhook) returns 429: that is their daily limit on your calls, a different fix
- You get 401s: auth problem, not throttling
- The import itself is slow but webhooks are fine: tune the import, not the webhook

## Tool compatibility
HubSpot webhook subscriptions (v3) for contacts, companies, deals, and custom objects. The queue-and-ack pattern works with any receiver stack; HubSpot's retry behavior is the same regardless of your framework.

## Variant phrasings
### hubspot webhooks delayed during import
Usually your endpoint throttling under burst load.
### hubspot subscription 429
Your endpoint asked HubSpot to slow down.
### hubspot bulk import sync stalls
Check the webhook receiver before the import job.
### hubspot webhook retry storm
Idempotency turns retries from a hazard into a no-op.

## Why it happens
A bulk import can generate thousands of object changes in minutes, and HubSpot fans those out as webhook batches nearly as fast. A handler that writes to the database synchronously, calls back into HubSpot, or does per-record enrichment cannot keep up. It starts answering 429 to shed load, HubSpot retries with backoff, and the retry traffic piles onto the original traffic. The import finishes long before your backlog drains. The structural fix is to separate receiving from processing: the HTTP handler only needs to be fast and durable.

## Edge cases
- 429s at normal volume: something else is wrong, like a database lock or a downstream API limit. Do not tune for bursts until the baseline is healthy.
- Retries create duplicates: add the idempotency key before you scale anything else.
- You return 200 but lose batches: the queue write is failing silently. Alert on queue-write failures, not just HTTP status.
- Multiple subscriptions share one endpoint: one noisy subscription can starve the others. Split heavy subscriptions onto their own route or queue.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_zwOh4MAwUJkU_GD88wHojw
